Python 在 __init__ 中处理异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20059766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handle exception in __init__
提问by Abhishek Chanda
Is it fine to raise an exception in __init__in python? I have this piece of code:
__init__在python中引发异常可以吗?我有这段代码:
class VersionManager(object):
def __init__(self, path):
self._path = path
if not os.path.exists(path): os.mkdir(path)
myfunction(path)
The second line can potentially result in an exception. In that case the object will not be init'ed properly. Is there a better way to handle situations where code in __init__might throw an exception?
第二行可能会导致异常。在这种情况下,对象将不会被正确初始化。有没有更好的方法来处理代码__init__可能抛出异常的情况?
EDITAdded a call to a function after os.mkdir
Added a check to see if directory exists
编辑在os.mkdir
添加了检查目录是否存在之后添加了对函数的调用
采纳答案by dawg
It is perfectly fine to raise an exception in __init__. You would then wrap the object initiation/creation call with try/exceptand react to the exception.
在__init__. 然后,您将使用该对象启动/创建调用包装try/except并对异常做出反应。
One potential odd result though is that __del__is run anyway:
一个潜在的奇怪结果__del__是无论如何都会运行:
class Demo(object):
def __init__(self, value):
self.value=value
if value==2:
raise ValueError
def __del__(self):
print '__del__', self.value
d=Demo(1) # successfully create an object here
d=22 # new int object labeled 'd'; old 'd' goes out of scope
# '__del__ 1' is printed once a new name is put on old 'd'
# since the object is deleted with no references
Now try with the value 2that we are testing for:
现在尝试使用2我们正在测试的值:
Demo(2)
Traceback (most recent call last):
File "Untitled 3.py", line 11, in <module>
Demo(2)
File "Untitled 3.py", line 5, in __init__
raise ValueError
ValueError
__del__ 2 # But note that `__del__` is still run.
The creation of the object with value 2raises a ValueErrorexception and show that __del__is still run to clean up the object.
创建具有值的对象2会引发ValueError异常并显示__del__仍在运行以清理对象。
Keep in mind that if you raise an exception during __init__your object will not get a name. (It will, however, be created and destroyed. Since __del__is paired with __new__it still gets called)
请记住,如果您在__init__对象期间引发异常将不会获得名称。(然而,它将被创建和销毁。因为__del__与__new__它配对仍然被调用)
ie, just like this does not create x:
即,就像这样不会创建x:
>>> x=1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
Potential sneakier:
潜行者:
>>> x='Old X'
>>> x=1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> x
'Old X'
Same thing if you catch an exception of __init__:
如果您捕获以下异常,则同样的事情__init__:
try:
o=Demo(2)
except ValueError:
print o # name error -- 'o' never gets bound to the object...
# Worst still -- 'o' is its OLD value!
So don't try to refer to the incomplete object o-- it's gone out of scope by the time you get to except. And the name ois either nothing (i.e., NameErrorif you try to use it) or its old value.
所以不要试图引用不完整的对象o——当你到达except. 并且名称o要么是空的(即,NameError如果您尝试使用它)或它的旧值。
So wrapping up (thanks to Steve Jessop for the User Defined Exceptionidea), you can wrap the creation of the object and catch the exception. Just figure out how to react appropriately to the OS error you are looking at.
所以总结一下(感谢 Steve Jessop 提出用户定义异常的想法),您可以包装对象的创建并捕获异常。只需弄清楚如何对您正在查看的操作系统错误做出适当的反应。
So:
所以:
class ForbiddenTwoException(Exception):
pass
class Demo(object):
def __init__(self, value):
self.value=value
print 'trying to create with val:', value
if value==2:
raise ForbiddenTwoException
def __del__(self):
print '__del__', self.value
try:
o=Demo(2)
except ForbiddenTwoException:
print 'Doh! Cant create Demo with a "2"! Forbidden!!!'
# with your example - react to being unusable to create a directory...
Prints:
印刷:
trying to create with val: 2
Doh! Cant create Demo with a "2"! Forbidden!!!
__del__ 2
回答by jramirez
You can use try/except when initializing the object.
您可以在初始化对象时使用 try/except。
try:
ver = VersionManager(my_path)
except Exception as e:
# raise e or handle error
print e
回答by mAsT3RpEE
My favourite is to simply output errors to console and march on:
我最喜欢的是简单地将错误输出到控制台并继续:
import sys, os, traceback
class Myclass
def __init__(self, path):
self._path = path
"""Risky Code"""
try:
os.mkdir(path)
except:
traceback.print_exc(file = sys.stdout)
This way an exception will print out more like a warning rather than a real exception.
这样,异常将更像是一个警告而不是真正的异常。
回答by aIKid
You can wrap the call, as jramirez suggested:
您可以按照 jramirez 的建议结束通话:
try:
ver = VersionManager(path)
except:
raise
Or you can use a context manager:
或者您可以使用上下文管理器:
class VersionManager(object):
def __init__(self):
#not-so-harmful code
self.path = path
def __enter__(self):
try:
self.path = path
os.mkdir(path)
self.myfunction(path)
except Exception as e:
print e
print "The directory making has failed, the function hasn't been executed."
return self
def __exit__(self, exc_type, exc_value, traceback):
print(exc_type, exc_value, traceback)
And to run it:
并运行它:
with VersionManager(my_path) as myVersionManager:
#do things you want with myVersionManager
This way, you'll catch errors inside the withstatement as well.
这样,您也将在with语句中捕获错误。

