在Python中使用和关闭文件
我已经读到,像这样打开的文件在离开with块时会自动关闭:在Python中使用和关闭文件,python,with-statement,urlopen,contextmanager,Python,With Statement,Urlopen,Contextmanager,我已经读到,像这样打开的文件在离开with块时会自动关闭: with open("x.txt") as f: data = f.read() do something with data 然而,当从web打开时,我需要: from contextlib import closing from urllib.request import urlopen with closing(urlopen('http://www.python.org')) as page: for
with open("x.txt") as f:
data = f.read()
do something with data
然而,当从web打开时,我需要:
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('http://www.python.org')) as page:
for line in page:
print(line)
为什么,有什么区别?(我用的是蟒蛇3)你不用<代码>urlopen('http://www.python.org“)还返回上下文管理器:
with urlopen('http://www.python.org') as page:
这记录在:
对于传统URLopener
和FancyURLopener
类处理的ftp、文件和数据URL以及请求,此函数返回一个urllib.response.addInfo URL
对象,该对象可以用作上下文管理器[…]
我的。对于HTTP响应,返回,它也是一个上下文管理器:
响应是一个iterable对象,可用于with语句
还将对象用作上下文管理器:
由于python.org网站使用其meta标记中指定的utf-8编码,因此我们将使用相同的编码来解码bytes对象
>>> with urllib.request.urlopen('http://www.python.org/') as f:
... print(f.read(100).decode('utf-8'))
...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtm
使用urllib.request.urlopen('http://www.python.org/“)作为f:
... 打印(f.read(100).解码('utf-8'))
...
细节有点技术性,所以让我们从简单的版本开始: 有些类型知道如何在
with
语句中使用。文件对象,比如从open
中获取的内容,就是这种类型的一个例子。事实证明,您从urllib.request.urlopen
返回的对象也是这种类型的一个示例,因此第二个示例的编写方法与第一个示例相同
但是有些类型不知道如何在with
语句中使用。close
函数用于包装此类类型,只要它们具有close
方法,当您退出with
语句时,它将调用它们的close
方法
当然,有些类型不知道如何在with
语句中使用,也不能与closing
一起使用,因为它们的清理方法没有命名为close
(或者因为清理它们比仅仅关闭它们更复杂)。在这种情况下,您需要编写一个自定义上下文管理器。但即使这样,通常也没那么难
在技术方面:
with
语句需要一个、一个具有\uuuuuuuuuuuuuuuuuuuuuuuu进入
和\uuuuuuuuuuuuu退出
方法的对象。它将调用\uuuuuuuuuuuuuu
方法,并在as
子句中为您提供该方法返回的值,然后它将在with
语句末尾调用\uuuuuuuuuu
方法
文件对象继承自,它是一个上下文管理器,其\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>方法返回自身
返回的对象是(假设是http
或https
URL),正如文档所说,“可以与with
语句一起使用”
职能:
返回一个上下文管理器,该管理器在块完成时关闭对象。这基本上相当于:
文档中并不总是100%清楚哪些类型是上下文管理器,哪些类型不是。特别是自从3.1以来,有了一个主要的驱动力,可以将所有可以作为上下文管理器的内容都整合到一个上下文管理器中(并且,对于这个问题,如果有意义的话,可以将所有主要是文件的内容都整合到实际的IOBase
),但到3.4为止,它仍然没有100%完成
你总是可以试试看。如果您得到一个属性错误:\uuuu exit\uuu
,则该对象不能用作上下文管理器。如果您认为应该这样做,请提交一个建议更改的bug。如果您没有收到该错误,但文档没有提到它是合法的,请提交一个bug,建议更新文档。我正要写这个:-)。关键是文档说它返回一个“类似文件”的对象。如果它不能用作上下文管理器,那么它实际上就不是像文件一样的。但是为什么这个例子出现在python文档中呢@nekomimi:可能是Python2的遗留版本,对象不是上下文管理器。引用的文档不是相关部分。他有一个http
url,它不返回addinfourl
,而是返回一个HTTPResponse
。当然,这些也可以用作上下文管理器。@abarnert:和往常一样,它有点复杂。谢谢你纠正我,更新。我正要建议有人为此在contextlib
上提交一个docs错误,如果不是你,不管是谁,都应该归功于你……但在我完成之前,Martijn已经提交了错误,链接回到这里。:)
@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()