4

[社区编辑给出可重现的例子:]

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

main()

生产

~/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

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

我正在尝试运行一个 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])

完整的代码在这里: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
4

2 回答 2

10

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

在 Python 3 中,以下块

try:
    try_body
except E as N:
    except_body
...

被翻译成(在 Python 2.5 术语中)

try:
    try_body
except E, N:
    try:
        except_body
    finally:
        N = None
        del N
...

因此,Python 3 中的这个函数

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

相当于

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已初始化,但在第一个try except块之后已被删除。
因此,UnboundLocalError是必然的。

于 2013-02-25T23:08:39.517 回答
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

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

编辑:为什么会这样

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

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

main()

输出:

{'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

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

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

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

main()

产生以下输出:

{'e': None}
{'e': Exception()}

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

于 2013-02-25T22:49:51.283 回答