Can't call a variable from another file - python-3.x

I have two files. The first file, we'll call it "a.py". The second, "b.py".
Here's an example of "a.py":
#!/usr/bin/env python
# coding=utf-8
CHOOSE = input ('''
\033[1;35m choose 1 or 2:\033[0m
1)tom
2)jack
''')
a = 666
b = "bbb"
def f():
print("this is a test")
return "function"
if __name__ == '__main__':
if CHOOSE == '1':
username = 'tom'
print(username)
elif CHOOSE == '2':
username = 'jack'
print(username)
else:
print('wrong choice,scipt is exit...')
Here's an example of "b.py":
#!/usr/bin/env python
# coding=utf-8
import a
from a import b,f,CHOOSE,username
a = a.a
f()
print(b,a,CHOOSE,username)
when i run python b.py,system feedback error:
wherem am i wrong?how to fix it?

Because this snippet:
if __name__ == '__main__':
if CHOOSE == '1':
username = 'tom'
print(username)
elif CHOOSE == '2':
username = 'jack'
print(username)
else:
print('wrong choice,scipt is exit...')
Will get executed only if the a.py run as the main python file not imported from other module, so username will not be defined so you can not import it. Here how to fix it:
a.py:
...
def foo(CHOOSE):
if CHOOSE == '1':
username = 'tom'
elif CHOOSE == '2':
username = 'jack'
else:
username = None
return username
b.py:
from a import foo
CHOOSE = input ('''
\033[1;35m choose 1 or 2:\033[0m
1)tom
2)jack
''')
username = foo(CHOOSE)
if username:
print(username)
else:
print('Wrong choice')
Explanation: First you need to extract the code that calculate the name into something reusable. Function are meant for code reusability so I defined one which take one parameter and it return the corresponding value. This function is then used (imported then invoked) in b.py.
Usually if __name__ == '__main__': is placed in the module that you consider your entry-point, so if you want to use it maybe b.py is a better place.

The block if __name__ == '__main__' only triggers if the script is run with a.py being the main module (e.g. you ran it using the command python a.py). If anything else was used as the main module, and a was imported, then this condition is not met and the code inside of it does not run.
The variable username is created and added to a's namespace in the if __name__ == '__main__' block. When you do python b.py, the code inside this block does not execute, and as a result username never gets added to the namespace. So when you try to import it, immediately after loading the file a, you get an error saying that the 'username' doesn't exist - it was never created.

Related

My code repeats when I run it, is something wrong or am I able to make it run once?

So I am trying to make a quick menu to where a user can have their name and change the "game's" difficulty. Except it repeats itself once you finish it. Code below
print("Welcome to the menu! First we need your username!")'''
name = input("[>: ")
print()
print("Thanks! Next is your difficulty. Do you want (E) Easy or (N) Normal?")'''
print()
difficulty = input("[>: ")
if difficulty == "e" :
difficulty = "Easy"
elif difficulty == "n" :
difficulty = "Normal"
print()
print("Porting you to the stats page...")
print()
import stats
And then in my stats.py file I made, I put:
from main import name
from main import difficulty
print()
print("Username: " + name)
print("Difficulty: " + difficulty)
Assuming the first code snippet is main.py.
You want to put everything from main.py in if __name__ == '__main__' to prevent from main import name from running import stats again.
if __name__ == "__main__":
print("Welcome to the menu! First we need your username!")'''
name = input("[>: ")
print()
print("Thanks! Next is your difficulty. Do you want (E) Easy or (N) Normal?")'''
print()
difficulty = input("[>: ")
if difficulty == "e" :
difficulty = "Easy"
elif difficulty == "n" :
difficulty = "Normal"
print()
print("Porting you to the stats page...")
print()
import stats

How can I create a continuous / infinite CLI with Click?

I'm trying to use Click to create a CLI for my Python 3 app. Basically I need the app to run continuously, waiting for user commands and executing them, and quitting if a specific command (say, "q") is entered. Couldn't find an example in Click docs or elsewhere.
An example of interactive shell would be like this:
myapp.py
> PLEASE ENTER LOGIN:
mylogin
> PLEASE ENTER PASSWORD:
mypwd
> ENTER COMMAND:
a
> Wrong command!
> USAGE: COMMAND [q|s|t|w|f] OPTIONS ARGUMENTS
> ENTER COMMAND:
f
> (output of "f" command...)
> ENTER COMMAND:
q
> QUITTING APP...
I've tried like so:
import click
quitapp = False # global flag
#click.group()
def cli():
pass
#cli.command(name='c')
#click.argument('username')
def command1(uname):
pass # do smth
# other commands...
#cli.command(name='q')
def quitapp():
global quitapp
quitapp = True
def main():
while not quitapp:
cli()
if __name__ == '__main__':
main()
But the console just runs the app once all the same.
I've actually switched to fire and managed to make a shell-like continuous function like so:
COMMAND_PROMPT = '\nCOMMAND? [w to quit] >'
CAPTCHA_PROMPT = '\tEnter captcha text (see your browser) >'
BYE_MSG = 'QUITTING APP...'
WRONG_CMD_MSG = 'Wrong command! Type "h" for help.'
EMPTY_CMD_MSG = 'Empty command!'
class MyClass:
def __init__(self):
# dict associating one-letter commands to methods of this class
self.commands = {'r': self.reset, 'q': self.query, 'l': self.limits_next, 'L': self.limits_all,
'y': self.yandex_logo, 'v': self.view_params, 'h': self.showhelp, 'c': self.sample_captcha, 'w': None}
# help (usage) strings
self.usage = '\nUSAGE:\t[{}] [value1] [value2] [--param3=value3] [--param4=value4]'.format('|'.join(sorted(self.commands.keys())))
self.usage2 = '\t' + '\n\t'.join(['{}:{}'.format(fn, self.commands[fn].__doc__) for fn in self.commands if fn != 'w'])
def run(self):
"""
Provides a continuously running commandline shell.
The one-letter commands used are listed in the commands dict.
"""
entered = ''
while True:
try:
print(COMMAND_PROMPT, end='\t')
entered = str(input())
if not entered:
print(EMPTY_CMD_MSG)
continue
e = entered[0]
if e in self.commands:
if self.commands[e] is None:
print(BYE_MSG)
break
cmds = entered.split(' ')
# invoke Fire to process command & args
fire.Fire(self.commands[e], ' '.join(cmds[1:]) if len(cmds) > 1 else '-')
else:
print(WRONG_CMD_MSG)
self.showhelp()
continue
except KeyboardInterrupt:
print(BYE_MSG)
break
except Exception:
continue
# OTHER METHODS...
if __name__ == '__main__':
fire.Fire(MyClass)
Still, I'd appreciate if someone showed how to do that with click (which appears to me to be more feature-rich than fire).
I've finally found out other libraries for interactive shells in Python: cmd2 and prompt, which are way more advanced for REPL-like shells out of the box...
There's a quick example of how to do a continuous CLI application with Click here: python click module input for each function
It only has a way of running click commands on a loop, but you can put in any custom logic you want, either in commands or the main body of the loop. Hope it helps!
Here I found click in the loop but it is error prone when we try to use different commands with different options
!Caution: This is not a perfect solution
import click
import cmd
import sys
from click import BaseCommand, UsageError
class REPL(cmd.Cmd):
def __init__(self, ctx):
cmd.Cmd.__init__(self)
self.ctx = ctx
def default(self, line):
subcommand = line.split()[0]
args = line.split()[1:]
subcommand = cli.commands.get(subcommand)
if subcommand:
try:
subcommand.parse_args(self.ctx, args)
self.ctx.forward(subcommand)
except UsageError as e:
print(e.format_message())
else:
return cmd.Cmd.default(self, line)
#click.group(invoke_without_command=True)
#click.pass_context
def cli(ctx):
if ctx.invoked_subcommand is None:
repl = REPL(ctx)
repl.cmdloop()
# Both commands has --foo but if it had different options,
# it throws error after using other command
#cli.command()
#click.option('--foo', required=True)
def a(foo):
print("a")
print(foo)
return 'banana'
#cli.command()
#click.option('--foo', required=True)
def b(foo):
print("b")
print(foo)
# Throws c() got an unexpected keyword argument 'foo' after executing above commands
#cli.command()
#click.option('--bar', required=True)
def c(bar):
print("b")
print(bar)
if __name__ == "__main__":
cli()

Defining a main_menu function to be called from other methods within a class in Python

I have a class with several methods to assign attributes from user input, and three methods that will add, delete, or update a nested dictionary with the input.
I would like to add a main_menu function so that the user can access the add, delete, and update methods and then choose to either continue adding/deleting/updating the dictionary, or go back to the main menu.
When I tried to make a main_menu function, I receive NameError: name 'command' is not defined. The program will loop through as expected if the main_menu is not a function, but once I tried to turn it into a function, I get the error. I've tried different levels of indentation, but I'm new to Python and don't know what else to try.
class MyClass:
def __init__(self):
self.x = 0
self.y = 0
self.z = 0
def get_x(self):
#code to get x from user input
def get_y(self):
#code to get y from user
def get_z(self):
#code to get z from user
def add_info(self):
store_info = {}
id = 0
while command = '1':
new_info = {}
new_id = len(store_info) + 1
store_info[new_id] = new_info
x = h.get_x()
new_info['x'] = x
y = h.get_y()
new_info['y'] = y
z = h.get_z()
new_info['z'] = z
print('Your info has been updated.\n', store_info)
choice = input('To add more info, type 1. To return to the main menu, type 2')
if choice == '1':
continue
elif choice == '2':
main_menu()
else:
print('The End')
break
def delete_info(self):
#code to delete, with an option at the end to return to main_menu
def update_info(self):
#code to update, with option for main_menu
def main_menu():
main_menu_option = """Type 1 to add.
Type 2 to delete.
Type 3 to update.
Type any other key to quit.\n"""
h = MyClass()
command = input(main_menu_option)
if command == '1':
h.add_info()
elif command == '2':
h.delete_info()
elif command == '3':
h.update_info()
else:
print('Good bye.')
main_menu()
When I run the program, I get the main menu and type 1, but then receive the NameError for command.
Before I tried to make the main_menu a function, I could access the add method to add info to the nested dictionary.
In Python methods/functions only have access to variable in their scope or parent scopes. For example:
command = 1 # A
def foo():
print(command)
def bar():
command = 2 # B
print(command)
foo()
bar()
print(command)
prints out 1 and then 2 and then 1. This works because when we call foo, python looks at the local variables and realises there is no command variable there so it looks at the scope above and sees the command variable at label A. Then when we call bar() we add a variable called command (label B) to the local variables of bar and then print that, notice that python doesn't look at the global variables here so it prints 2 without changing the initial command variable (label A) as we can see when we finally print(command) at the end of the script.
It is because of this that your program is failing, your add_info method is trying to access a variable called command however none exists in its local variable or its global scope. The fix for this would be to add command to the add_info local variables by passing it as an argument to the method from main_menu.
# in main_menu
if command == '1':
h.add_info(command)
# in add_info
def add_info(self, command):
...

How to make a global inside two functions

import getpass
from passlib.hash import sha256_crypt
def register():
username = str(input('username '))
password = str(getpass.getpass('password ',stream=None))
exec('global '+username)
exec(username+'=user('+"'"+username+"'"+','+"'"+password+"'"+')')
def hashPassword(password):
Passhash = sha256_crypt.hash(password)
return Passhash
def verifyPassword(password,hashpass):
return sha256_crypt.verify(password,hashpass)
class user(object):
users=[]
def __init__(self, username, password):
password = str(password)
if len(password) <= 20:
self.username = username
user.users.append(username)
self.password = hashPassword(password)
else:
print("No more than 20 characters in the password")
def login(username, passsword):
if username in user.users:
if verifyPassword(password,exec(username+'.password'))==True:
print('logged in.')
else:
print('wrong password')
else:
print('unknown user.')
I am trying to make a text based login/register system since I am fairly new to coding. For some reason something with the register() function doesn't correctly register a user because when I go to login verifypassword() it says
if verifyPassword(password,exec(username+'.password'))==True:
File "<string>", line 1, in <module>
NameError: name 'test' is not defined
>>>
if someone could tell me what is happening. I think it it something with global variables but I don't know how to fix it
global in exec doesn't work.
Use globals()[var_name] = var_value to set dynamic variable names in global scope.
exec is gererally a (very) bad idea if called with user-supplied input.
It also has (more or less) unexpected bahaviour in functions, see this example:
def f():
exec('a=3')
print(a)
>>> f()
Traceback [...]
NameError: name 'a' is not defined
(This has something to do with local scope being known at compile-time, see here or here)
Also, you might consider storing the actual user objects in user.users -- this prevents users picking names that you actually use inside your code and prevents unexpected behavior
Edit: Elaboration on the "local scope known at compile-time"
Since the compiler knows what local variables you are using, access is by the bytecode STORE_FAST and LOAD_FAST instructions, which store and load to and from a kind of array (you can look at local variable names via f.__code__.co_varnames), you can't just add stuff dynamically.
Why is this relevant for global?
Well, as said above, the STORE_FAST and LOAD_FAST instructions are used (you guessed it, for speed), the bytecode for following function will be:
>>> def f():
exec('global x')
x = 3
>>> dis.dis(f)
2 0 LOAD_GLOBAL 0 (exec)
2 LOAD_CONST 1 ('global x')
4 CALL_FUNCTION 1
6 POP_TOP
3 8 LOAD_CONST 2 (3)
10 STORE_FAST 0 (x)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
The first part deals with calling exec. The second part is the assignment. STORE_FAST assigns to a local variable x, no matter what exec just did.
This is also the reason creating new local variables in exec doesn't work: there just isn't space for them. Note this isn't valid for local variables set in exec but also "normally", they will have space assigned nevertheless.
In python, there is a dictionary of global-variables, that you can access by calling globals(). I'm not sure why exec(...) doesn't work, but I would consider a different solution than storing users as variables, named by username. But to solve your problem, keeping this design-choice, you can set the global user like this: globals()[username] = user(username, password) and when loggin in, do verifyPassword(password, globals()[username].password).
But since globals is really just a dictionary, it might be better practice to maintain a dictionary of users yourself. A user could potentially overwrite a global variable, by choosing a username that clashes with another global variable. You could then also eliminate the static users list on your user class. It could look like this, where repository is your dictionary with users:
import hashlib
import base64
import uuid
import getpass
from passlib.hash import sha256_crypt
repository = {}
def register():
username = str(input('username '))
password = str(getpass.getpass('password ',stream=None))
repository[username] = user(username, password)
def hashPassword(password):
Passhash = sha256_crypt.hash(password)
return Passhash
def verifyPassword(password,hashpass):
return sha256_crypt.verify(password,hashpass)
class user(object):
def __init__(self,username,password):
password = str(password)
if len(password) <= 20:
self.username = username
self.password = hashPassword(password)
else:
print("No more than 20 characters in the password")
def loginUser(username):
if username == 'exit':
start()
if username in repository:
if loginPass(username)==True:
print('success')
else:
print('passfail')
else:
print('incorrect login USERNAME NOT IN USER.USERS LIST')
def loginPass(username):
password = getpass.getpass('password ',stream=None)
if verifyPassword(password, repository[username].password) == True:
return True
else:
return False
def start():
while 1:
key1=input('login or register (l/r)')
if key1=='register':
del key1
register()
elif key1=='r':
del key1
register()
elif key1=='l':
del key1
loginUser(input('username or exit to got to l/r screen '))
else:
print('ERROR string not reconised among ifs')
start()

Using two kv files in one program error

I am quite new to OOP, and I am currently trying to create my first project using kivy. The program is currently stuck at the point of when I login I try and open a new kv file, but it will not open. Here is the python code:
window_widget = Builder.load_file("LiveScoringV104KVLoggedIn.kv")
class LoginScreen(Screen):
def checkLogin(self, username, password):
usernamesFile = open("dataUsernamesV104.txt", "r")
passwordsFile = open("dataPasswordsV104.txt", "r")
for line in usernamesFile.readlines():
for lineb in passwordsFile.readlines():
with open("dataprintedUsernameV104.txt", "w") as printedUsername:
printedUsername.write(username + "\n")
if line == username and lineb == password:
print("This is working")
return window_widget
else:
print("All wrong")
root_widget = Builder.load_file("LiveScoringV104KV.kv")
class StartupHome(App):
def build(self):
return root_widget
if __name__ == "__main__":
StartupHome().run()
when I login, which is correct because this is working is printed, window_widget is not called as it does not run the kv file, yet root_widget is called .How can I get the kv file to run like root_widget? (If you need the kv code just ask)

Resources