来自datamodel docs上下文管理员:
请注意,
__exit__()
方法不应该重新引用传入的异常;这是来电者的责任。
我有一个临时文件,我想用close
释放其文件描述符,但是没有写任何东西到磁盘。我的直观解决方案是传递异常,但那是discouraged in the docs - 当然有充分的理由。
class Processor(object):
...
def write(self, *args, **kwargs):
if something_bad_happens:
raise RuntimeError('This format expects %s columns: %s, got %s.' % (
(len(self.cols), self.cols, len(args))))
self.writer.writerow(args)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
# the RuntimeError from write will be set as type, value and so on ..
# I'd like to close the stream here (release the file descriptor),
# but I do not leave a trace of the associated file -
# (one can always 'manually' delete with `os.remove` but maybe there's a
# better way ..?)
self.output_pipe.close()
此外,我不希望在此特定情况下调用者中的错误处理有两个原因:
上下文管理器的用法如下:
class Worker(object):
...
def run(self):
# output setup so it will emit a three column CSV
with self.output().open('w') as output:
output.write('John', 'CA', 92101)
output.write('Jane', 'NY', 10304)
# should yield an error, since only three 'columns' are allowed
output.write('Hello', 'world')
答案 0 :(得分:9)
__exit__
返回True时,将吞下传递给它的任何异常。__exit__
返回False时,将重新启动该异常。def __exit__(self, type, value, traceback):
self.output_pipe.close() # always close the file
if type is not None: # an exception has occurred
os.unlink(...) # remove the file
return False # reraise the exception
您当然可以省略return False
,因为Python默认会返回None
(这是Falsish)。
顺便说一下,self.output()
是Processor
的一个实例吗?如果是的话,
with self.output().open('w') as output:
应该是
with self.output() as output:
在任何情况下,如果你可以安排后者是正确的语法会更好。您可能需要将__enter__
更改为:
def __enter__(self):
return self.output_pipe.open('w')
答案 1 :(得分:2)
没有需要raise
例外;该异常已经已经被引发,并且您的上下文管理器仅被告知该情况。
测试是否有 no 例外:
if type is None:
# if no exception is raised, proceed as usual:
self.output_pipe.close()
如果您的上下文管理员要在那一刻返回True
,您将取消该异常;只是退出函数而不是返回None
,异常仍然是“被提升”。
请注意,tempfile
module包含两种类型的临时文件对象,它们充当上下文管理器,自行删除已经,独立于平台。在POSIX系统上,您可以在创建后立即取消链接文件;在关闭文件之前,文件描述符仍然有效。 Windows也提供“关闭时删除”选项。 tempfile.NamedTemporaryFile()
类为您的平台使用正确的选项。