【问题标题】:Received "UnboundLocalError: local variable 'e' referenced before assignment" when the variable was initialized初始化变量时收到“UnboundLocalError: local variable 'e' referenced before assignment”
【发布时间】:2013-02-11 05:14:48
【问题描述】:

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

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()需要编辑才能使用正确的数据文件地址:

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

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

【问题讨论】:

  • 旁白:score_name = score = name = [] 行可能不会像您认为的那样。它不会创建三个列表,而是创建 一个 列表,并将三个名称绑定到它。在控制台上尝试,然后score.append(3); print (score, score_name, name)。在这里可能无关紧要,因为您重新绑定了scorename,但仍然如此。
  • 呃,我完全忘记了参考的问题(来自 R,它没有这个问题)。感谢您指出这一点!
  • 无法复制。请提供一个最小的独立示例。
  • 我不知道如何复制 - 代码中一定有我们看不到的东西。您能否尝试制作一个可重现的示例 - 即可以运行并产生此错误的代码的简短版本? (很可能在这样做的过程中,您会首先发现导致问题的原因)。
  • 完整的代码对我有用。请提供一个最小的失败代码,而不是这个怪物。

标签: python exception exception-handling python-3.x while-loop


【解决方案1】:

此错误是由新的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 是不可避免的。

【讨论】:

  • 我没有过多地使用python3(我现在仍然停留在我以前的python2方式中)。谢谢你的解释 :) 我猜这个问题是从 python2 到 python3 的语义改变了,但不知道到底是怎么回事
  • 感谢您的解释!刚开始用python,听朋友说3和2有很多不方便的区别。(我的朋友只用python 2)
【解决方案2】:

好吧,我不知道是什么导致了实际问题,但是为什么不在发生异常时使用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()}

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

【讨论】:

  • 感谢您的简单解决方案和解释!非常感谢
  • nymk 的回答对为什么会发生这种情况的解释比我的要好得多,因为我对 python3 的经验有限。如果您有时间阅读,他链接到的 PEP 特别具有指导意义:)
猜你喜欢
  • 2021-05-11
  • 1970-01-01
  • 2017-08-08
  • 1970-01-01
  • 2019-07-11
  • 2023-02-13
  • 2018-01-22
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多