How “with” is better than try/catch to open a file in Python?
我知道
1 2 3 4 5 6 7 | try: f = open(my_file) do_stuff_that_fails() except: pass finally: f.close() |
进入:
1 2 | with open(my_file) as f: do_stuff_that_fails() |
但这怎么会更好呢?您仍然需要处理无法打开的文件(如提示用户告诉他他没有权限)的情况,因此实际上您可以:
1 2 3 4 5 | try: with open(my_file) as f: do_stuff_that_fails() except (IOError, OSError, Failure) as e: do_stuff_when_it_doesnt_work() |
相当于:
1 2 3 4 5 6 7 | try: f = open(my_file) do_stuff_that_fails() except (IOError, OSError, Faillure) as e: do_stuff_when_it_doesnt_work() finally: f.close() |
是的,你得到了两行,但是你添加了一个嵌套的wich级别并不能使它更容易阅读。这句话的目的是为了让你省去两行,还是我遗漏了什么?
仅仅为这个添加一个关键字似乎很难,所以我觉得有一些语法可以处理额外的try/except,我不知道。
首先,它有助于防止您在
您构造它的方式是,如果在试图打开文件时抛出异常,那么您将永远不会将打开的文件绑定到名称为
正确的结构(相当于
1 2 3 4 5 6 | f = open(my_file) try: do_stuff_that_fails() finally: f.close() |
(注:如果你没有做任何事的话,不需要使用
您的第二个示例同样是错误的,其结构应该如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 | try: f = open(my_file) try: do_stuff_that_fails() except EXPECTED_EXCEPTION_TYPES as e: do_stuff_when_it_doesnt_work() finally: f.close() except (IOError, OSError) as e: do_other_stuff_when_it_we_have_file_IO_problems() |
第二个是(如另一个答案所述),你不能忘记打电话给
顺便说一句,术语是"上下文管理",而不是"资源管理"——
最后(对上一个答案的注释作出响应),您不应该依赖refcount语义来处理Python中的资源。Jython、Ironpython和Pypy都有非refcount语义,而且没有什么能阻止CPython向另一个方向发展(尽管这在不久的将来是极不可能的)。如果依赖refcount语义的代码在具有不同行为的VM上运行,则在一个紧密的循环(例如
在你给出的例子中,情况并不好。最好的做法是尽可能接近抛出的点捕获异常,以避免捕获同一类型的无关异常。
1 2 3 4 5 6 7 8 9 | try: file = open(...) except OpenErrors...: # handle open exceptions else: try: # do stuff with file finally: file.close() |
不幸的是,尽管这很冗长,
1 2 3 4 | with open(...) as file: # do stuff with file except OpenErrors...: # handle open exceptions |
但这是被击落的。
最后值得注意的是,您可以这样直接进入和退出上下文管理器:
1 2 | file = open(...).__enter__() file.__exit__(typ, val, tb) |
这在这里和这里有更详细的描述。
作为一般准则,
用于资源管理…不是因为你对异常的反应,否则:)
使用
快乐编码。