Python中的异常安全状态如何?

3 投票
3 回答
1451 浏览
提问于 2025-04-16 07:30

我知道Python中有一个叫做with的语句,用来处理资源。那在Python中,写出安全的代码还有哪些需要注意的地方呢?

补充一下:这里主要是关于打开文件之类的事情。比如说,如果一个初始化的函数抛出了一个异常,那这个正在初始化的对象的状态会是什么样的呢?

3 个回答

0

Python和C++不太一样。在Python中,出现错误时会给出有用的错误追踪信息。如果你在程序中需要处理用户输入,记得捕捉一些合适的错误,比如EOFError。但如果不是这种情况,你就不需要特别处理错误,Python会帮你处理得很好。如果程序出现了意外情况并抛出了错误,你可以利用错误信息来调试你的问题。如果你希望程序能一直稳定运行,可以考虑在最外层加一个try/except,并放在一个循环里,这样可以记录日志并重启程序。

3

如果你在问关于语言结构的事情:

  • 使用 try: except: else: 这种写法可以确保你不会捕捉到错误的异常。
  • 在捕捉 BaseExceptionException 或者使用裸 except: 之前要三思,因为这样很容易捕捉到太多东西:
    • 比如你的拼写错误 - NameError、ImportError
    • 用户试图终止你的程序 - KeyboardInterrupt、SystemExit
    • 表示实现不完整的错误 - NotImplementedError
  • 如果你决定捕捉通用异常,记得用 log.exception('你的信息', e) 来记录它们。
  • 要记住,Python 中的异常也可以用来进行正常的流程控制(比如 StopIteration 异常)。
  • 使用新的语法: except MyException as myex:,而不是 except MyException, myex:。这样对于不太熟悉 Python 的开发者来说更容易阅读。

下面是一个捕捉 NameError 的例子:

try:
   this_doesn_not_exisit();
except Exception: #Don't do that!
   pass

print "But this line is still printed"

对编辑后问题的回答:

  • 关于文件,如果你要读取文本文件,始终使用 codecs.open 而不是 open,这样可以确保你安全地存储 Unicode 字符串。
  • 关于 __init__ 和对象的状态。 __init__ 是一个初始化器,所以在调用 __init__ 时对象已经存在。如果你抛出异常,流程会被中断,对象不会被存储在任何变量中,所以它会被垃圾回收。至少这是我的理解。可以想象 MyObject() 就像是一个函数,如果你抛出异常,你就什么都不返回,流程被中断,你原本要赋值的内容也不会被修改。

看看这个:

>>> def throw(): raise Exception() 
... 
>>> a=1
>>> a=throw()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in throw
Exception
>>> a
1

这里有一个例子可以证明即使在 __init__ 中抛出异常,对象仍然会被创建。我无法在评论中发布这个片段给 @S.Lott 的回答:

 >>> global_collection=[]
 >>> class Partial(object):
 ...    def __init__(self):
 ...       self.test="test"
 ...       global_collection.append(self)
 ...       raise Exception()
 ...
 >>> x=Partial()
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 5, in __init__
 Exception
 >>> global_collection
 [<__main__.Partial object at 0xb74f8f6c>]
 >>> global_collection[0].test
 'test'

更新: 包含了 @Paul McGuire、@martineau、@aaronasterling 的评论

4

比如说,假设一个初始化函数出现了错误。那么,这个正在初始化的对象状态是什么呢?

提示:如果不确定,可以实际做个实验。

>>> class Partial( object ):
...     def __init__( self ):
...         self.a= 1
...         raise Exception
...         self.b= 2
... 
>>> p= Partial()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
Exception
>>> p
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'p' is not defined

整个语句都会失败。对象没有被创建,变量也没有被赋值。还有其他问题吗?

在C++中,事情就复杂多了。在Python中,这个对象会被简单地丢弃。

撰写回答