初始化变量时收到"UnboundLocalError:赋值前引用的局部变量'e'"

Ale*_*lex 3 python exception-handling exception while-loop python-3.x

[社区编辑提供可重复的示例:]

def main():
    e = None
    print(locals())
    while not e:
        try:
            raise Exception
        except Exception as e:
            pass            

main()
Run Code Online (Sandbox Code Playgroud)

产生

~/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
Run Code Online (Sandbox Code Playgroud)

[已编辑]包含可重现的代码

我正在尝试运行while循环,我使用的条件是循环在变量时继续e==None.相关代码如下:

    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])
Run Code Online (Sandbox Code Playgroud)

完整的代码在这里: https://www.dropbox.com/s/llj5xwexzfsoppv/stats_quiz_feb24_2013.py

它需要的数据文件(用于测验运行)在此链接中: https://www.dropbox.com/s/70pbcb80kss2k9e/stats_quiz.dat

main() 需要编辑才能使用正确的数据文件地址:

我收到的完整错误消息如下.这很奇怪,因为我e在while循环之前初始化了.我希望有人可以帮我解决这个问题.谢谢!

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
Run Code Online (Sandbox Code Playgroud)

nym*_*ymk 10

此错误是由新try...except...范围引起的,这是一个Python 3功能.
PEP-3110

在Python 3中,以下块

try:
    try_body
except E as N:
    except_body
...
Run Code Online (Sandbox Code Playgroud)

被翻译成(用Python 2.5术语)

try:
    try_body
except E, N:
    try:
        except_body
    finally:
        N = None
        del N
...
Run Code Online (Sandbox Code Playgroud)

因此,这个函数在Python 3中

def main():
    e = None
    print(locals())
    while not e:
        try:
            raise Exception
        except Exception as e:
            pass
Run Code Online (Sandbox Code Playgroud)

相当于

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
    ...
Run Code Online (Sandbox Code Playgroud)

e已初始化,但在第一个try except块之后已被删除.
因此,UnboundLocalError是不可避免的.


ent*_*opy 5

好吧,我不知道是什么导致了实际问题,但是为什么不只是break在发生异常时使用呢?你的循环变成:

while True:
    try:
        score = pickle.load(score_list)
        name = pickle.load(score_list)
        score_name.append([score, name])
    except EOFError as e:
        break
Run Code Online (Sandbox Code Playgroud)

据我所知,这是实现“无一例外地运行循环”的惯用方式

编辑:为什么会发生这种情况

似乎在 python3 中,一旦退出异常处理程序的范围,异常绑定到的变量就会从命名空间中删除。我将代码修改为以下内容:

def main():
    e = None
    print(locals())
    while not e:
        try:
            raise Exception
        except Exception as e:
            pass
        print(locals())

main()
Run Code Online (Sandbox Code Playgroud)

输出:

{'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
Run Code Online (Sandbox Code Playgroud)

在python2中不是这种情况。鉴于为变量分配异常的方式更改了语法,我对它的语义也发生了变化并不感到惊讶。尽管我确实认为这是“令人惊讶”的行为(从某种意义上说,这不是您所期望的)。

在任何情况下,发生异常时退出循环的正确方法都在上面的代码中。如果您想将异常保留在异常处理程序的范围之外,我想您仍然可以执行以下操作:

def main():
   e = None
   print(locals())
   while not e:
      try:
         raise Exception
      except Exception as ex:
         e = ex
      print(locals())

main()
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

{'e': None}
{'e': Exception()}
Run Code Online (Sandbox Code Playgroud)

但是您真的不应该为您的特定用例这样做。