回溯:AttributeError:addinfourl实例没有属性'__exit__'

Bre*_*tis 16 python python-2.7

from urllib import urlopen
with urlopen('https://www.python.org') as story:
    story_words = []
    for line in story:
        line_words = line.split()
        for words in line_words:
            story_words.append(word)
Run Code Online (Sandbox Code Playgroud)

错误信息:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: addinfourl instance has no attribute '__exit__'
Run Code Online (Sandbox Code Playgroud)

我不明白上面的代码有什么问题以及如何解决它?

系统信息:ubuntu oracle虚拟盒中的python 2.7.

xyr*_*res 70

该错误是由此行引起的:

with urlopen('https://www.python.org') as story:
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请使用以下行替换该行:

from contextlib import closing

with closing(urlopen('https://www.python.org')) as story:
    ...
Run Code Online (Sandbox Code Playgroud)

有关错误的其他信息

为什么会这样?

要使with...as语句为对象起作用,必须实现该对象的上下文管理器.它的意思是,对象/类必须有contextlib.closingwith...as它定义的方法.

with ... as有人提出,因为没有为实现任何情况管理器__enter__(它没有__exit__AttributeError它定义的方法).

由于作者urlopen尚未实现,除了以下内容之外,您无能为力:

  1. 或者不要使用__enter__声明.
  2. 或者,如果必须,您可以使用__exit__(感谢@vaultah,他在下面的评论中提供了此解决方案).它自动为任何对象实现上下文管理器,从而允许您使用with...as语句.

如何实现上下文管理器?

您可以通过定义执行上下文管理contextlib.closingwith...as方法的对象/类.

请阅读有关上下文管理器的这些文档.

例:

story = urlopen('https://www.python.org')
...
Run Code Online (Sandbox Code Playgroud)

上面,我们得到了一个,urlopen因为我们还没有实现上下文管理器with...as.以下是上下文管理器的实现方式.

>>> class Person(object):
        """To implement context manager, just create two methods 
           __enter__ and __exit__.
        """

        def __init__(self, name):
            self.name = name

        def __enter__(self):
            # The value returned by this method is 
            # assigned to the variable after ``as``
            return self

        def __exit__(self, exc_type, exc_value, exc_traceback ):
            # returns either True or False
            # Don't raise any exceptions in this method
            return True


>>> with Person("John Doe") as p:
        print p.name

>>> "John Doe" #success
Run Code Online (Sandbox Code Playgroud)

  • @vaultah更新了答案. (3认同)