I have two blocks of python code, one works, and the other doesn't.
Working block:
env = {'user':'xyz'}
for key, value in env.items():
exec("{} = value".format(key))
print(user)
output:
xyz
The block, which doesn't work:
def test():
env = {'user':'xyz'}
for key, value in env.items():
exec("{} = value".format(key))
print(user)
test()
output:
NameError: name 'user' is not defined
The only difference I see is that the first block is being called in the global scope.
Could you please explain?
Many thanks!
PS: With all due respect, I know, I should avoid using exec() but what if I want to.
I recommend you reading this
You have to use locals() or exec or eval to access variables defined by exec in a function in Python3.
def test():
env = {'user': 'xyz'}
for key, value in env.items():
exec("{} = value".format(key))
exec("print(user)")
print(locals()['user'])
print(eval("user"))
test()
It should be noted that, if you attempt to store value returned from eval. You will get NameError.
def test():
env = {'user': 'xyz'}
for key, value in env.items():
exec("{} = value".format(key))
user = eval("user")
print(user)
test()
returns
Traceback (most recent call last):
File "D:/Git/sscgc/test.py", line 8, in <module>
test()
File "D:/Git/sscgc/test.py", line 5, in test
user = eval("user")
File "<string>", line 1, in <module>
NameError: name 'user' is not defined
Related
Python is raising the below exception when running my script. Could somebody please explain why this is happening and how to fix it?
Traceback (most recent call last):
File "C:\Users\vinsunny\AppData\Local\Programs\Python\Python36\test.py", line 28, in <module>
test.my_func()
File "C:\Users\vinsunny\AppData\Local\Programs\Python\Python36\test.py", line 23, in my_func
print('non secret no. from test_func: ', self.number2)
AttributeError: 'Test' object has no attribute 'number2'"
class Test():
__class_secret_number = 100
def __secret_func(self):
self.number1 = 1
self.__secret_number1 = 11
print('You cannot see this unless accessing from the Class itself')
def test_func(self):
self.number2 = 2
self.__secret_number2 = 22
def my_func(self):
self.__secret_func()
print('Secret no. from class: ', self.__class_secret_number)
print('non secret no. from secret func: ', self.number1)
print('Secret no. from secret func: ', self.__secret_number1)
# These two prints raise an exception.
print('non secret no. from test_func: ', self.number2)
print('Secret no. from test_func: ', self.__secret_number2)
test = Test()
test.my_func()
At the time the offending print statement is executed, the number2 attribute on your Test instance has not been defined.
The first time the number2 attribute gets set is in the test_func() method. i.e. Attempting to access number2 before calling test_func() will result in the error you are observing.
You should assign a default value to self.number2 in the initializer for the Test class. You could also call test_func() before calling my_func(). But, either way, it's still good practice to initialize all instance attributes in Test.__init__.
The interpreter will raise an exception for the same reason when you try to access the undefined attribute __secret_number_2 in my_func().
test_func is never called, so number2 and __secret_number2 doesn't exist.
Need to call the function before try to access them, or init them with init method.
I am trying to dynamically create 2 functions defined within a string. Code:
def main():
fns = '''
def plus_one(x):
return x + 1
def plus_two(x):
return plus_one(x) + 1
'''
exec(fns)
result = eval('plus_two(11)')
print(result)
if __name__ == '__main__':
main()
Saving this code to a file called dyn_code.py and running it gives me the following error:
python dyn_code.py
Traceback (most recent call last):
File "dyn_code.py", line 19, in <module>
main()
File "dyn_code.py", line 14, in main
result = eval('plus_two(11)')
File "<string>", line 1, in <module>
File "<string>", line 7, in plus_two
NameError: name 'plus_one' is not defined
Problem here is that plus_one cannot be resolved inside plus_two.
plus_one on its own is fine here and can be called with the correct result.
Can anybody please give me an idea on how to inject code like this into the local namespace? Specifically, I want to create 2 functions, with one referring to the other.
I have intentionally used the most open form of both exec and eval, I do know how to restrict them, etc. I have also verified that after the call to exec both functions are present in the local namespace.
What makes this more frustrating is that the code works fine in an interpreter session! That is, after injecting these 2 functions into the interpreter namespace via exec, plus_two runs without any issues.
Ideally, I would like to avoid a function-in-function scenario i.e.
def plus_two(x):
def plus_one(x):
return x + 1
return plus_one(x) + 1
This technique actually works but I want 2 explicitly named and standalone functions.
indentations of your function in fns matters! and you have to pass globals() optional argument for mapping!
def main():
fns = '''def plus_one(x):
return x + 1
def plus_two(x):
return plus_one(x) + 1
'''
exec(fns,globals())
result = eval('plus_two(11)')
print(result)
if __name__ == '__main__':
main()
Output:
13
Hope it helps!
You need to add the globals() dictionary in your call to exec(). You can also omit the eval call for plus_two, like so:
def main():
exec('def plus_one(x):\n return x + 1\n\ndef plus_two(x): return plus_one(x) + 1', globals())
print(plus_two(11))
if __name__ == '__main__':
main()
Below is my code
global PostgresDatabaseNameSchema
global RedShiftSchemaName
PostgresDatabaseNameSchema = None
RedShiftSchemaName = None
def check_assign_global_values():
if not PostgresDatabaseNameSchema:
PostgresDatabaseNameSchema = "Superman"
if not RedShiftSchemaName:
RedShiftSchemaName = "Ironman"
check_assign_global_values()
But i am getting an error saying
Traceback (most recent call last):
File "example.py", line 13, in <module>
check_assign_global_values()
File "example.py", line 8, in check_assign_global_values
if not PostgresDatabaseNameSchema:
UnboundLocalError: local variable 'PostgresDatabaseNameSchema' referenced before assignment
So can't we access or set the global variables from inside a function ?
global should always be defined inside a function, the reason for this is because it's telling the function that you wanted to use the global variable instead of local ones. You can do so like this:
PostgresDatabaseNameSchema = None
RedShiftSchemaName = None
def check_assign_global_values():
global PostgresDatabaseNameSchema, RedShiftSchemaName
if not PostgresDatabaseNameSchema:
PostgresDatabaseNameSchema = "Superman"
if not RedShiftSchemaName:
RedShiftSchemaName = "Ironman"
check_assign_global_values()
You should have some basic understanding of how to use global. There is many other SO questions out there you can search. Such as this question Using global variables in a function other than the one that created them.
I'm invoking one function using a button click. But it is giving me error: NameError: global name 'new' is not defined ,even though I have defined new as a new window.
My code for a new window:
def result():
root.withdraw()
new = Toplevel()
new.geometry("1105x605+300+300")
button3 = Button(new, text='Select a Query Image',command = matching_image)
button3.pack(padx = 1, pady = 1,anchor='ne')
button3.place( x = 570, y = 60)
The button will invoke matching_image function, and the code will be:
def matching_image():
path1 = tkFileDialog.askopenfilename(filetypes=[("Image File",'.jpg')])
im = Image.open(path1)
resized = im.resize((200, 200),Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(resized)
myvar1 = Label(new,image = tkimage)
myvar1.image = tkimage
myvar1.pack()
myvar1.place(x = 30, y = 100)
And this is giving the error. The error message is as follows:
%run "D:/6th sem/Major project/Code/frame.py"
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\HP\AppData\Local\Enthought\Canopy32\App\appdata\canopy-1.0.3.1262.win-x86\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "D:\6th sem\Major project\Code\frame.py", line 194, in matching_image
myvar1 = Label(new,image = tkimage)
NameError: global name 'new' is not defined
Any suggestions! So that I can solve this error.
Thanks in advance :)
You defined new in a function, so that variable only exists in that function's scope. Therefore, when you try to access it in another scope (here it is the global scope) you will get a NameError as it is not available at that level.
You can fix this by doing global new at the start of the function in which you define it.
This statement puts it in the global scope, meaning that it is defined at the module level. Therefore, you can access it anywhere in the program and you will not get that error.
Like this:
def result():
global new
new = Toplevel()
# Other stuff.
Though note that doing global declarations is considered bad practice. Much better to put your code in class form and assign applicable variables to self.
Your problem is condensed down to this:
def foo():
var = 1
def bar():
print var
foo()
bar()
The principle problem you have is that 'var' is a local, not a global.
This code example works:
def foo():
global var
var = 1
def bar():
print var
foo()
bar()
Because var is declared to be global instead.
def buy():
while True:
items={"Armor": 25, "Sword": 25}
print("What do you want to buy?\n1/Armor +25 defense\t50 golds\n2/Sword +25 damage\t50 golds")
s1=input("Choose the item you want to buy (1 and/or 2 only): ")
try:
global a
a=int(s1)
if a in range (1,3):
break
except ValueError:
pass
buy()
print(a)
error message:
Traceback (most recent call last):
File "C:\code\work\The Role-Playing combat game.py", line 58, in <module>
print(a) NameError: global name 'a' is not defined
Line 58 is print(a)
I declared "a" as the global value, but somehow the interpreter gives me the error message. Please help, thanks.
Solved, declare "a" outside of the function first
Did you declare the a variable earlier in your code? Otherwise, calling global a before declaring it will throw that error. You need to put a = something before you call global a on it.