Python 的 try、except 和 finally

4 投票
2 回答
6373 浏览
提问于 2025-04-16 08:42

看起来我还没完全掌握异常处理的技巧。我有点困惑 :(

下面的代码有时会返回这个错误:

File "applications/pingback/modules/plugin_h_pingback.py", line 190, in ping
    db(table.id==id_).update(status=status)
UnboundLocalError: local variable 'status' referenced before assignment

我本来以为status应该总是被赋值的。难道是其他的异常被抛出了(可能是在内部的try里),然后finally把它给遮住了?

...
try:
    server_url = self._get_pingback_server(target)
except PingbackClientError, e:
    status = e.message
else:
    try:
        server = xmlrpclib.ServerProxy(server_url)
        status = server.pingback.ping(self.source, target)
    except xmlrpclib.Fault, e:
        status = e
finally:
    db(table.id==id_).update(status=status) # <-- UnboundLocalError
...

谢谢,HC

2 个回答

3

作为一个简单的解决办法,我会在任何代码块外面先初始化状态:

status = None
try: 
    # etc

这样一来,状态就会一直有值。这虽然不能解决所有未处理的错误问题,但可以解决“未绑定局部变量错误”。

(另外,在第一个代码块里,你是用 e.message 来给状态赋值,而在后面的代码块里,你直接用了完整的错误 e,而不仅仅是消息部分。)

10

你的代码并不是每次都会给状态(status)赋值。我发现了几种情况,可能会导致状态没有被赋值,我在下面列出了这些情况:

try:
    server_url = self._get_pingback_server(target)
except PingbackClientError, e:
    # If evaluating `e.message` raises an exception then status is not set.
    status = e.message  # <--- here
else:
    try:
        # If either of these two lines fails with something other than
        # xmlrcplib.Fault, then status is not set.
        server = xmlrpclib.ServerProxy(server_url)             # <--- here
        status = server.pingback.ping(self.source, target)     # <--- here
    # If xmlrpclib.Fault is not defined status is not set.
    except xmlrpclib.Fault, e:                                 # <--- here
        status = e
finally:
    db(table.id==id_).update(status=status)

我觉得出错的地方最有可能是在内部的try块里,因为你只捕获了xmlrpclib.Fault这种错误,而没有处理其他类型的异常。

撰写回答