Python 回溯:AttributeError:addinfourl 实例没有属性“__exit__”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30627937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Traceback: AttributeError:addinfourl instance has no attribute '__exit__'
提问by Brenda Olivia Martis
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)
Error message:
错误信息:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: addinfourl instance has no attribute '__exit__'
I am not understanding what's wrong with the above code and how to resolve it?
我不明白上面的代码有什么问题以及如何解决它?
System information : python 2.7 in ubuntu oracle virtual box.
系统信息:ubuntu oracle virtual box 中的python 2.7。
采纳答案by xyres
That error is caused by this line:
该错误是由这一行引起的:
with urlopen('https://www.python.org') as story:
You can't use any random object in a with...as
statement.
您不能在with...as
语句中使用任何随机对象。
There are two ways to fix this:
有两种方法可以解决这个问题:
Solution 1:Use contextlib.closing
:
解决方案1:使用contextlib.closing
:
from contextlib import closing
with closing(urlopen('https://www.python.org')) as story:
...
Solution 2:Don't use a with...as
statement; instead assign the value to a variable:
解决方案2:不要使用with...as
语句;而是将值分配给变量:
story = urlopen('https://www.python.org')
...
Why is this happening?
为什么会这样?
You can't use any random object in a with ... as
statement.
您不能在with ... as
语句中使用任何随机对象。
Only those objects will work which have two magic methods: __enter__
and __exit__
implemented on them. Collectively, these methods are called "context manager". An introductory tutorial about this can be found below.
只有那些具有两个魔术方法的对象才能工作:__enter__
并__exit__
在它们上实现。这些方法统称为“上下文管理器”。可以在下面找到有关此的介绍性教程。
The AttributeError
was raised because there isn't any context manager implemented for urlopen
(i.e.it doesn't have __enter__
and __exit__
methods defined for it).
之所以AttributeError
被提出,是因为没有为其实现任何上下文管理器urlopen
(即它没有为它定义__enter__
和__exit__
方法)。
This leaves you with two choices:
这让您有两个选择:
- either don't use
with...as
statement. - or use
contextlib.closing
(thanks to @vaultahwho provided this solution in a comment below). It automatically implements context manager for any object, thereby allowing you to usewith...as
statement.
- 要么不使用
with...as
声明。 - 或使用
contextlib.closing
(感谢@vaultah在下面的评论中提供了此解决方案)。它自动为任何对象实现上下文管理器,从而允许您使用with...as
语句。
(Note: In Python 3, urlopen
does have a context manager, and thus can be used in a with...as
statement.)
(注意:在 Python 3 中,urlopen
确实有上下文管理器,因此可以在with...as
语句中使用。)
Tutorial: How to implement the context manager?
教程:如何实现上下文管理器?
To make an object work in a with...as
statement, you first need to implement the context manager for that object. In simpler terms, you need to define __enter__
and __exit__
methods for that object/class.
要使对象在with...as
语句中工作,您首先需要为该对象实现上下文管理器。简单来说,您需要为该对象/类定义__enter__
和__exit__
方法。
Do read these docs on context managers.
请阅读有关上下文管理器的这些文档。
Example:
例子:
>>> 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
回答by shruti1810
You can try the following in Python 2.7:
您可以在 Python 2.7 中尝试以下操作:
from urllib import urlopen
story = urlopen('https://www.python.org')
story_words = []
for line in story:
line_words = line.split()
for words in line_words:
story_words.append(words)