re-raising an exception in a context handler
从上下文管理器上的datamodel文档:
Note that
__exit__() methods should not reraise the passed-in exception; this is the caller’s responsibility.
我有一个临时文件,其文件描述符我想用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  | 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()  | 
此外,我不希望在此特定情况下调用者中的错误处理有两个原因:
- 保持调用者中的代码最小化(见下文)
 - 调用者对异常感到满意(快速失败就是我们想要的)
 
上下文管理器的用法如下:
1 2 3 4 5 6 7 8 9  | 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')  | 
更新:我的问题有点不合理,因为我的问题真的归结为:在嵌套的上下文管理器中,如何将异常传递给最外层的CM?
- 
当
__exit__ 返回True时,将吞下传递给它的任何异常。 - 
当
__exit__ 返回False时,将重新启动该异常。 
1 2 3 4 5  | 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  | 
您当然可以省略
那么
1  | with self.output().open('w') as output:  | 
应该
1  | with self.output() as output:  | 
在任何情况下,如果你能安排后者是正确的语法会更好。您可能需要将
1 2  | def __enter__(self): return self.output_pipe.open('w')  | 
没有必要
测试是否没有例外:
1 2 3  | if type is None: # if no exception is raised, proceed as usual: self.output_pipe.close()  | 
如果您的上下文管理器在那一刻返回
请注意,