[Community edit to give reproducible example:]
def main():
e = None
print(locals())
while not e:
try:
raise Exception
except Exception as e:
pass
main()
produces
~/coding$ python3.3 quiz2.py
{'e': None}
Traceback (most recent call last):
File "quiz2.py", line 11, in <module>
main()
File "quiz2.py", line 5, in main
while not e:
UnboundLocalError: local variable 'e' referenced before assignment
[EDITED] to include a reproducible code
I am trying to run a while-loop, and the condition I use is that the loop continues when the variable e==None
. The relevant code is below:
print("\nThe current score list contains the following people's scores: ")
score_list = open("score_list.dat", "rb")
score_name = []
e = None
while not e:
try:
score = pickle.load(score_list)
name = pickle.load(score_list)
score_name.append([score, name])
except EOFError as e:
pass
score_list_sorted=sorted(score_list)
sort_list.close()
for item in score_list_sorted:
print("Score: ", item[0], "\t", item[1])
the complete code is here: https://www.dropbox.com/s/llj5xwexzfsoppv/stats_quiz_feb24_2013.py
The data file it requires (for the quiz to run) is in this link: https://www.dropbox.com/s/70pbcb80kss2k9e/stats_quiz.dat
main()
needs to be edited to use the proper data file address:
The complete error message I received is below. This is weird because I initialized e
right before the while-loop. I hope someone can help me resolve this problem. Thanks!
Traceback (most recent call last):
File "<pyshell#217>", line 1, in <module>
main()
File "/Users/Dropbox/folder/stats_quiz_feb24_2013.py", line 83, in main
while not e:
UnboundLocalError: local variable 'e' referenced before assignment
This error is caused by the new try...except...
scope, which is a Python 3 feature.
See PEP-3110
In Python 3, the following block
try:
try_body
except E as N:
except_body
...
gets translated to (in Python 2.5 terms)
try:
try_body
except E, N:
try:
except_body
finally:
N = None
del N
...
Therefore, this function in Python 3
def main():
e = None
print(locals())
while not e:
try:
raise Exception
except Exception as e:
pass
is equivalent to
def main():
e = None
print(locals())
if not e:
try:
raise Exception
except Exception as e:
pass
del e
if not e:
try:
raise Exception
except Exception as e:
pass
del e
...
e
was initialized, but it has been deleted after the first try except
block.
Thus, UnboundLocalError
is inevitbale.
Well, I don't know what's causing the actual problem, but why don't you just use break
when an exception occurs? Your loop becomes:
while True:
try:
score = pickle.load(score_list)
name = pickle.load(score_list)
score_name.append([score, name])
except EOFError as e:
break
As far as I know, this is the idiomatic way of achieving "run loop while there's no exception"
Edit: Why this happens
It would seem that in python3, once you exit the scope of an exception handler, the variable that the exception was bound to is removed from the namespace. I modified the code to the following:
def main():
e = None
print(locals())
while not e:
try:
raise Exception
except Exception as e:
pass
print(locals())
main()
Output:
{'e': None}
{}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in main
UnboundLocalError: local variable 'e' referenced before assignment
This is not the case in python2. Given that the syntax was changed for how you assign an exception to a variable, I'm not surprised that the semantics of it were changed as well. Although I do think that this is "surprising" behaviour(in the sense that it is not what you would expect).
In any case, the proper way to exit a loop when an exception occurs is in the code above. If you want to keep the exception outside of the exception handler's scope I guess you could still do something like this:
def main():
e = None
print(locals())
while not e:
try:
raise Exception
except Exception as ex:
e = ex
print(locals())
main()
Which produces the following output:
{'e': None}
{'e': Exception()}
But you really shouldn't be doing that for your particular use-case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With