在python中__init__
引发异常是否可以?我有这段代码:
class VersionManager(object):
def __init__(self, path):
self._path = path
if not os.path.exists(path): os.mkdir(path)
myfunction(path)
第二行可能会导致异常。在这种情况下,对象将不会正确初始化。有没有更好的方法来处理__init__
中的代码可能引发异常的情况?
修改
在os.mkdir
之后添加了对函数的调用
添加了检查以查看目录是否存在
答案 0 :(得分:21)
在__init__
中引发异常完全没问题。然后,您将使用try/except
包装对象启动/创建调用,并对异常做出反应。
但有一个奇怪的结果是__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
现在尝试使用我们正在测试的值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.
创建值为2
的对象会引发ValueError
异常,并显示仍然运行__del__
来清理对象。
请注意,如果您在__init__
期间提出异常,您的对象将无法获得名称。 (但是,它会被创建和销毁。由于__del__
与__new__
配对,它仍会被调用)
即,就像这样不会创建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
潜在的偷偷摸摸:
>>> x='Old X'
>>> x=1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> x
'Old X'
如果你发现__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!
所以不要试图引用不完整的对象o
- 当你到达except
时它已超出范围。名称o
要么没有(例如,NameError
,如果您尝试使用它)或其旧值。
结束(感谢Steve Jessop的User Defined Exception想法),你可以包装对象的创建并捕获异常。只需弄清楚如何对您正在查看的操作系统错误作出适当的反应。
所以:
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...
打印:
trying to create with val: 2
Doh! Cant create Demo with a "2"! Forbidden!!!
__del__ 2
答案 1 :(得分:3)
你可以打电话,正如jramirez建议的那样:
try:
ver = VersionManager(path)
except:
raise
或者您可以使用上下文管理器:
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)
并运行它:
with VersionManager(my_path) as myVersionManager:
#do things you want with myVersionManager
这样,您也会在with
语句中捕获错误。
答案 2 :(得分:0)
我最喜欢的是简单地输出错误到控制台并继续前进:
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)
这样,异常会打印出更像是警告而不是真正的异常。
答案 3 :(得分:-1)
初始化对象时可以使用try / except。
try:
ver = VersionManager(my_path)
except Exception as e:
# raise e or handle error
print e