如何“与”比用try / catch更好地在Python中打开一个文件? [英] How "with" is better than try/catch to open a file in Python?

查看:142
本文介绍了如何“与”比用try / catch更好地在Python中打开一个文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到语句有助于您:

  try:
f = open(my_file)
do_stuff_that_fails()
除了:
pass
finally:
f.close()

进入:

  with open(my_file)as f:
do_stuff_that_fails()

但是如何更好?您仍然需要处理该文件无法打开的情况(如提示用户告诉他他没有权限),所以在现实中你会有:

  try:
with open(my_file)as f:
do_stuff_that_fails()
except(IOError,OSError,Failure)as e:
do_stuff_when_it_doesnt_work()

相当于:

  try:
f = open(my_file)
do_stuff_that_fails()
除了(IOError,OSError,Faillure)为e:
do_stuff_when_it_doesnt_work()
finally:
f.close()

是你获得了两条线,但是你添加了一个嵌套级别,这样做并不容易阅读。 语句的目的是保存两行,还是我缺少某些东西?



只是为了添加一个关键字似乎很多,所以我觉得有一些语法来处理额外的try /除了我不知道。

解决方案

一开始,它有助于防止您在中引入的问题尝试...最后... 示例。



如果在尝试打开文件时抛出异常,那么您将其结构化,那么您将不要将打开的文件绑定到名称 f ,导致中的 NameError 子句(如果 f 从未在范围内绑定)或完全意外的(如果有)。



正确的结构(相当于)是:

  f = open(my_file)

try:
do_stuff_that_fails()
finally:
f.close()

(注意 - 不需要子句,如果你没有做那么)



你的第二个例子同样是错误的,应该如下结构:

 code> try:
f = open(my_file)

try:
do_stuff_that_fails()
除了EXPECTED_EXCEPTION_TYPES作为e:
do_stuff_when_it_doesnt_work()
finally:
f.close()

除了(IOError,OSError)为e:
do_other_stuff_when_it_we_have_file_IO_problems()
/ pre>

第二个是(如另一个答案所述),你不能忘记调用 f.close()



BTW,术语是上下文管理,而不是资源管理 - 语句管理上下文,其中一些可能是资源,但其他可能不是资源。例如,它也与 decimal 一起使用以为特定的代码块建立一个十进制上下文。



最后回应您对上一个答案的评论),您不应该依赖refcount语义来处理Python中的资源。 Jython,IronPython和PyPy都具有非引用语义,并且没有什么可以阻止CPython以其他方式进行(尽管在不久的将来不太可能)。在紧密循环(例如 os.walk )中,如果依赖于引用计数语义的代码在具有不同行为的VM上运行,则非常容易运行文件句柄。 / p>

I got that the with statement help you to turn this:

try:
    f = open(my_file)
    do_stuff_that_fails()
except:
    pass
finally:
    f.close()

Into:

with open(my_file) as f:
    do_stuff_that_fails()

But how is that better? You still got to handle the case with the file not being able to be opened (like prompting the user to tell him he doesn't have permissions), so in reality you'd have:

try:
    with open(my_file) as f:
        do_stuff_that_fails()
except (IOError, OSError, Failure) as e:
    do_stuff_when_it_doesnt_work()

Which is equivalent to:

try:
    f = open(my_file)
    do_stuff_that_fails()
except (IOError, OSError, Faillure) as e:
    do_stuff_when_it_doesnt_work()
finally:
    f.close()

Yes, you gained two lines, but you added a level of nesting wich doesn't make it easier to read. Is the purpose of the with statement to save you two lines or am I missing something?

It seems a lot to add a keyword just for that, so I feel like there is some syntaxe to handle the additional try/except that I don't know about.

解决方案

For a start, it helps prevent the problem you've introduced in your try ... finally ... example.

The way you've structured it, if an exception is thrown while trying to open the file then you will never bind an open file to the name f, leading to either a NameError in the finally clause (if f has never been bound within scope) or something entirely unexpected (if it has).

The correct structure (equivalent to the with) is:

f = open(my_file)

try:
    do_stuff_that_fails()
finally:
    f.close()

(note - no need for an except clause if you've got nothing to do there).

Your second example similarly is wrong, and should be structured like:

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()

The second is (as stated in another answer) that you can't forget to call f.close().

BTW, the term is "context management", not "resource management" - the with statement manages contexts, some of which may be resources, but others not. For example, it's also used with decimal to establish a decimal context for a particular block of code.

Finally (responding to your comment to the previous answer) you should never rely on refcount semantics for handling resources in Python. Jython, IronPython and PyPy all have non-refcount semantics, and there's nothing preventing CPython from going the other way (though it's highly unlikely for the immediate future). In a tight loop (e.g. os.walk) it is very very easy to run out of file handles if code relying on refcount semantics is run on a VM with different behaviour.

这篇关于如何“与”比用try / catch更好地在Python中打开一个文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆