Need some guidance here please. This is probably a stupid mistake, but I'm getting the "builtins.NameError: global name -- is not defined" error and I'm not seeing why - I'm still learning the language :).
Here is my code:
def option(x):
if x == "E":
enter()
elif x == "V":
view()
else:
exit()
def enter():
msg = input("Enter the message\n")
main()
def view():
##if msg == 0:
#print("no message yet")
#main()
#else:
print("The message is:", msg )
main()
def exit():
print("Goodbye!")
def main():
print("Welcome to BBS")
print("MENU")
print("(E)nter a message")
print("(V)iew message")
print("e(X)it")
print("Enter your selection:")
choice = input()
option(choice)
#msg = 0
main()
My problem is that I'm getting this even though I'm choosing the "E" option first:
Traceback (most recent call last):
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 36, in <module>
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 33, in main
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 3, in option
pass
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 11, in enter
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 33, in main
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 5, in option
File "C:\Program Files (x86)\Wing IDE 101 5.0\src\debug\tserver\_sandbox.py", line 18, in view
builtins.NameError: global name 'msg' is not defined
Could I please be guided? I've been searching for info and haven't found anything, and my conclusion is that it is probably something really stupid and noobish.
Also, as you guys can see from what I've commented out, I've attempted to restrict "view" from giving an error by checking that msg != 0 -- I made msg = 0 in main() - this obviously doesn't work because after going through enter() it goes back to main() and makes msg == 0 again. Could you guys link me to a page/guide that will help me understand how to solve this? I don't want to be spoon fed that much..
Thanks,
Itachi
The problem here is that msg inside enter() is a local variable: it's created when the enter() function runs, and it ceases to exist when enter() returns. Normally, whenever you set a variable inside a function, you're setting a local variable. If you want to set a global variable, which retains its value even after the function returns, use a global statement:
def enter():
global msg
msg = input("Enter the message\n")
main()
That said, global variables are often not the best way to do things. It may be better to have the enter() function return the message instead of storing it in a variable.
msg is a name that's not scoped to be used anywhere. That's why you get the NameError.
Each one of the functions you've created should stand alone and have straightforward inputs and outputs.
main is your entry point and it should call other functions as appropriate.
Those functions will return to their caller when their execution is complete. They can and in some cases should return some amount of data back to their caller.
For example, here's a subset of your problem showing how main invokes view and then returns:
def view(text):
if not text:
print("no message yet")
else:
print("The message is:", msg )
def main():
print("Welcome to BBS")
print("MENU")
print("(E)nter a message")
print("(V)iew message")
print("e(X)it")
print("Enter your selection:")
while not exiting:
choice = input()
view(choice)
exiting = True # TODO: set this based on the value in choice
Related
This is my code:
import os
if os.path.exists(r'C:\Genisis_AI'):
print("Main File path exists! Continuing with startup")
else:
createDirs()
def createDirs():
os.makedirs(r'C:\Genisis_AI\memories')
When I execute this, it throws an error:
File "foo.py", line 6, in <module>
createDirs()
NameError: name 'createDirs' is not defined
I made sure it's not a typo and I didn't misspell the function's name, so why am I getting a NameError?
You can't call a function unless you've already defined it. Move the def createDirs(): block up to the top of your file, below the imports.
Some languages allow you to use functions before defining them. For example, javascript calls this "hoisting". But Python is not one of those languages.
Note that it's allowable to refer to a function in a line higher than the line that creates the function, as long as chronologically the definition occurs before the usage. For example this would be acceptable:
import os
def doStuff():
if os.path.exists(r'C:\Genisis_AI'):
print("Main File path exists! Continuing with startup")
else:
createDirs()
def createDirs():
os.makedirs(r'C:\Genisis_AI\memories')
doStuff()
Even though createDirs() is called on line 7 and it's defined on line 9, this isn't a problem because def createDirs executes before doStuff() does on line 12.
I am trying this code provided and accepted here: https://stackoverflow.com/a/55369170/14307622
but I am getting this error. Any ideas why ? I am new here so if I am breaking some rules for this question, then please let me know but if possible, please suggest some solutions to the problem first.
import keyboard
import time
listedSongs = []
currentSong = "idk"
exit = False # make a loop control variable
def alt_k():
i = 1
paused = False
def alt_q():
global exit
exit = True
def alt_s():
if currentSong not in listedSongs:
listedSongs.append(currentSong)
print(listedSongs)
# assign hooks to the keyboard
keyboard.on_press_key("alt+k", alt_k) # on press alt+k, execute alt_k()
keyboard.on_press_key("alt+q", alt_q)
keyboard.on_press_key("alt+s", alt_s)
# main loop
while not exit:
keyboard.wait() # "block" for input (essentially, do nothing until a key is pressed and yield CPU resources to anything else that wants them)
The error I am getting is this:
Traceback (most recent call last):
File "D:\AJ\Coding\test.py", line 26, in <module>
keyboard.on_press_key("alt+k", alt_k) # on press alt+k, execute alt_k()
File "C:\Users\AJ\AppData\Local\Programs\Python\Python39\lib\site-packages\keyboard\__init__.py", line 510, in on_press_key
return hook_key(key, lambda e: e.event_type == KEY_UP or callback(e), suppress=suppress)
File "C:\Users\AJ\AppData\Local\Programs\Python\Python39\lib\site-packages\keyboard\__init__.py", line 493, in hook_key
scan_codes = key_to_scan_codes(key)
File "C:\Users\AJ\AppData\Local\Programs\Python\Python39\lib\site-packages\keyboard\__init__.py", line 324, in key_to_scan_codes
raise ValueError('Key {} is not mapped to any known key.'.format(repr(key)), e)
ValueError: ("Key 'alt+k' is not mapped to any known key.", ValueError("Key name 'alt+k' is not mapped to any known key."))
It seems on_press_key() works only with single key like q but not with combination alt+q. Or maybe it is problem only on some systems. At least it doesn't work on my Linux.
Or maybe they change code in module. Answer in Checking for keyboard inputs uses too much cpu usage, Is there something wrong with my code? is 2 years old.
You can use add_hotkey() and it doesn't need wait()
import keyboard
import time
listedSongs = []
currentSong = "idk"
exit = False # make a loop control variable
def alt_k():
print('pressed: alt+k')
i = 1
paused = False
def alt_q():
global exit # need it to assign `True` to global/external variable instead of creating local variable
print('pressed: alt+q')
exit = True
def alt_s():
print('pressed: alt+s')
if currentSong not in listedSongs:
listedSongs.append(currentSong)
print(listedSongs)
keyboard.add_hotkey('alt+k', alt_k)
keyboard.add_hotkey('alt+q', alt_q)
keyboard.add_hotkey('alt+s', alt_s)
# main loop
while not exit:
time.sleep(1)
See examples in documentation: Example
Eventually you may use hotkye = read_hotkey(...) with if/else to execute correct function.
I'm not sure but sometimes it works for me also with hotkey = keyboard.wait(suppress=False) but sometimes it doesn't work.
while not exit:
hotkey = keyboard.read_hotkey(suppress=False)
#hotkey = keyboard.wait(suppress=False)
print('hotkey:', hotkey)
if hotkey == 'alt+k':
alt_k()
elif hotkey == 'alt+q':
alt_q()
This is how I solved my issue.
I ditched the keyboard module since it was not working the way I wanted it to and then I used the Python Global-Hotkeys Module. The code was pretty much the same but now everything just clicked in place.
Hope this helps someone in the future.
I'm trying to make a text game in python and i'm trying to debug the game right now.
I think this code I'm writing is supposed to type out the letters/characters one by one and make a typing effect.
here it is:
def setup_game():
### BACKSTORY TELLING
backstory = "something something boring backstory"
typeout(backstory)
def typeout(x):
time.sleep(0.03)
sys.stdout.write(char)
sys.stdout.flush()
option = input('> ')
if option.lower() == '> ok':
title_screen()
else:
print("please try again\n")
option = input('> ')
#Actual game
def start_game():
print_location()
main_game_loop()
setup_game()
but whatever i do it always gives me an error and i don't know how to fix it.
here it is:
Traceback (most recent call last):
File "textgame.py", line 612, in <module>
setup_game()
File "textgame.py", line 600, in setup_game
typeout(backstory)
File "textgame.py", line 604, in typeout
sys.stdout.write(char)
NameError: name 'char' is not defined
all the lines referenced in the error are in the code from the top.
I did find another post about the:
time.sleep(0.03)
sys.stdout.write(char)
sys.stdout.flush()
part and i tried doing what the answer said but instead it just gave me a different error which is what i have now.
help would be appreciated, thanks
You need to do something like:
sys.stdout.write(x)
Because char is not defined in your code. You're passing x to the function.
I'm teaching myself how to Python3. I wanted to train my acquired skills and write a command-line backup program. I'm trying to save the default backup and save locations with the Shelve module but it seems that it keeps forgetting the variables I save whenever I close or restart the program.
Here is the main function that works with the shelves:
def WorkShelf(key, mode='get', variable=None):
"""Either stores a variable to the shelf or gets one from it.
Possible modes are 'store' and 'get'"""
config = shelve.open('Config')
if mode.strip() == 'get':
print(config[key])
return config[key]
elif mode.strip() == 'store':
config[key] = variable
print(key,'holds',variable)
else:
print("mode has not been reconginzed. Possible modes:\n\t- 'get'\n\t-'store'")
config.close()
So, whenever I call this function to store variables and call the function just after that, it works perfectly. I tried to access the shelf manually and everything is there.
This is the code used to store the variables:
WorkShelf('BackUpPath','store', bupath)
WorkShelf('Path2BU', 'store', path)
The problem comes when I try to get my variables from the shelf after restarting the script. This code:
config = shelve.open('Config')
path = config['Path2BU']
bupath = config['BackUpPath']
Gives me this error:
Traceback (most recent call last):
File "C:\Python35-32\lib\shelve.py", line 111, in __getitem__
value = self.cache[key]
KeyError: 'Path2BU'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
config['Path2BU']
File "C:\Python35-32\lib\shelve.py", line 113, in __getitem__
f = BytesIO(self.dict[key.encode(self.keyencoding)])
File "C:\Python35-32\lib\dbm\dumb.py", line 141, in __getitem__
pos, siz = self._index[key] # may raise KeyError
KeyError: b'Path2BU
Basically, this is an error I could reproduce by calling ShelveObject['ThisKeyDoesNotExist'].
I am really lost right now. When I try to manually create a shelf, close it and access it again it seems to work (even though I got an error doing that before) now. I've read every post concerning this, I thought about shelf corruption (but it's not likely it happens every time), and I've read my script A to Z around 20 times now.
Thanks for any help (and I hope I asked my question the right way this time)!
EDIT
Okay so this is making me crazy. Isolating WorkShelf() does work perfectly, like so:
import shelve
def WorkShelf(key, mode='get', variable=None):
"""Either stores a variable to the shelf or gets one from it.
Possible modes are 'store' and 'get'"""
config = shelve.open('Config')
if mode.strip() == 'get':
print(config[key])
return config[key]
elif mode.strip() == 'store':
config[key] = variable
print(key,'holds',variable)
else:
print("mode has not been reconginzed. Possible modes:\n\t- 'get'\n\t-'store'")
config.close()
if False:
print('Enter path n1: ')
path1 = input("> ")
WorkShelf('Path1', 'store', path1)
print ('Enter path n2: ')
path2 = input("> ")
WorkShelf('Path2', 'store', path2)
else:
path1, path2 = WorkShelf('Path1'), WorkShelf('Path2')
print (path1, path2)
No problem, perfect.
But when I use the same function in my script, I get this output. It basically tells me it does write the variables to the shelve files ('This key holds this variable' message). I can even call them with the same code I use when restarting. But when calling them after a program reset it's all like 'What are you talking about m8? I never saved these'.
Welcome to this backup manager.
We will walk you around creating your backup and backup preferences
What directory would you like to backup?
Enter path here: W:\Users\Damien\Documents\Code\Code Pyth
Would you like to se all folders and files at that path? (enter YES|NO)
> n
Okay, let's proceed.
Where would you like to create your backup?
Enter path here: N:\
Something already exists there:
19 folders and 254 documents
Would you like to change your location?
> n
Would you like to save this destination (N:\) as your default backup location ? That way you don't have to type it again.
> y
BackUpPath holds N:\
If you're going to be backing the same data up we can save the files location W:\Users\Damien\Documents\Code\Code Pyth so you don't have to type all the paths again.
Would you like me to remember the backup file's location?
> y
Path2BU holds W:\Users\Damien\Documents\Code\Code Pyth
>>>
======== RESTART: W:\Users\Damien\Documents\Code\Code Pyth\Backup.py ========
Welcome to this backup manager.
Traceback (most recent call last):
File "C:\Python35-32\lib\shelve.py", line 111, in __getitem__
value = self.cache[key]
KeyError: 'Path2BU'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "W:\Users\Damien\Documents\Code\Code Pyth\Backup.py", line 198, in <module>
path, bupath = WorkShelf('Path2BU'), WorkShelf('BackUpPath')
File "W:\Users\Damien\Documents\Code\Code Pyth\Backup.py", line 165, in WorkShelf
print(config[key])
File "C:\Python35-32\lib\shelve.py", line 113, in __getitem__
f = BytesIO(self.dict[key.encode(self.keyencoding)])
File "C:\Python35-32\lib\dbm\dumb.py", line 141, in __getitem__
pos, siz = self._index[key] # may raise KeyError
KeyError: b'Path2BU'
Please help, I'm going crazy and might develop a class to store and get variables from text files.
Okay so I just discovered what went wrong.
I had a os.chdir() in my setup code. Whenever Setup was done and I wanted to open my config files it would look in the current directory but the shelves were in the directory os.chdir() pointed to in the setup.
For some reason I ended up with empty shelves in the directory the actual ones were supposed to be. That cost me a day of debugging.
That's all for today folks!
I currently have this as my code.
def makeFolder():
if not os.path.exists('Game Saves'): os.makedirs('Game Saves')
def saveAllPlayerInfo(dest,fileName):
f=open(dest+fileName,'w')
f.write("{0}:{1}\n".format('playerName',playerName))
f.write("playerStats={\n")
f.write("\t'{0}':'{1}'\n".format('playerMaxHp',playerStats['playerMaxHp']))
f.write("\t'{0}':'{1}'\n".format('playerCurrentHp',playerStats['playerCurrentHp']))
f.write("\t'{0}':'{1}'\n".format('playerAtk',playerStats['playerAtk']))
f.write("\t'{0}':'{1}'\n".format('playerDef',playerStats['playerDef']))
f.write("\t'{0}':'{1}'\n".format('playerDefending',playerStats['playerDefending']))
f.write("\t'{0}':'{1}'\n".format('playerRunAbility',playerStats['playerRunAbility']))
f.write("\t'{0}':'{1}'\n".format('luck',playerStats['luck']))
f.write("\t'{0}':'{1}'\n".format('playerExperience',playerStats['playerExperience']))
f.write("\t'{0}':'{1}'\n".format('level',playerStats['level']))
f.write("\t}")
f.close()
def saveFile():
makeFolder()
dest=os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+'\\Game Saves\\'
fileName="{0}.txt".format(playerName)
if not (os.path.isfile(dest+fileName)):
print("New File Created")
print("Game Has Been Saved")
saveAllPlayerInfo(dest,fileName)
elif (os.path.isfile(dest+fileName)):
saveAllPlayerInfo(dest,fileName)
print("Game Has Been Saved")
def readFile():
gameFiles=[f for f in os.listdir(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+'\\Game Saves\\') if isfile(join(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+'\\Game Saves\\',f))]
dest=os.path.basename(os.path.abspath(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+'\\Game Saves\\'))
print("What would you like to do?")
print("1. Load a Game")
print("2. Start a New Game")
ans=input()
a=0
while a==0:
if ans.lower() in ["1.","1","load a game","load game","load"]:
print("")
print("Select Which Game: ")
filesRead=0
for saves in gameFiles:
gameSave=(open(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+'\\Game Saves\\'+gameFiles[filesRead],'r'))
firstLine=gameSave.readline()
print("{0}. {1}".format(filesRead+1, firstLine[11:]))
filesRead+=1
gameToLoad=input("")
if int(gameToLoad)<=filesRead:
exec(gameSave.read())
a=1
elif ans.lower() in ["2.","2","start a new game","start a game","start game","start"]:
clr()
newGame()
a=1
else:
print("I didn't understand that. Can you say that again?")
And this is the file it is pulling from. It is called 'Alex.txt'
playerName:Alex
playerStats={
'playerMaxHp':'10'
'playerCurrentHp':'10'
'playerAtk':'5'
'playerDef':'5'
'playerDefending':'0'
'playerRunAbility':'10'
'luck':'10'
'playerExperience':'0'
'level':'1'
}
Now, I understand that it currently doesn't have anyway to translate what file you input into the code for what the program should load. But that's not what I'm worrying about.
The problem here is that I want as elegant and simple of a solution as possible to load the file. That's why I saved it in the format I did. That's the exact format it is inside the code itself.
But when I execute it as is, I get
Traceback (most recent call last):
File "E:\Game.py", line 614, in <module>
readFile()
File "E:\Game.py", line 82, in readFile
exec(gameSave.read())
File "<string>", line 3
'playerCurrentHp':'10'
^
SyntaxError: invalid syntax
And when I do an eval() instead, I get.
Traceback (most recent call last):
File "E:\Game.py", line 614, in <module>
readFile()
File "E:\Game.py", line 82, in readFile
eval(gameSave.read())
File "<string>", line 1
playerStats={
^
SyntaxError: invalid syntax
Both have problems. I'd like to just have a few lines of code if possible.
I've also tried having it go line by line, but neither will accept the line that eval is getting stuck on (Unexpected EOF error).
I will not import any third party modules. I am working on many computers, and I do not want to have to install modules on all the computers I'm working on for one project.
Can someone offer an elegant solution to my problem?
(Also, is there a way to simplify my reading function, specifially the dest= part? Seems pretty complex to me. I just searched here, did some testing, threw something together until it worked, and stuck with it. But it feels like it should be able to be far less obtuse.)