Reputation: 3081
I'm trying to do asynchronous downloading of files using urllib2 but have no succeeded in finding out the socket (or its fileno) to wait for new data for for HTTP requests. Here's what I've already tried.
>>> from urllib2 import urlopen
>>> from select import select
>>> r = urlopen('http://stackoverflow.com/')
>>> select([r], [], [])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/socket.py", line 307, in fileno
return self._sock.fileno()
AttributeError: HTTPResponse instance has no attribute 'fileno'
>>> r.fileno()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/socket.py", line 307, in fileno
return self._sock.fileno()
AttributeError: HTTPResponse instance has no attribute 'fileno'
>>> r.fp.fileno()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/socket.py", line 307, in fileno
return self._sock.fileno()
AttributeError: HTTPResponse instance has no attribute 'fileno'
>>> select([r.fp], [], [])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/socket.py", line 307, in fileno
return self._sock.fileno()
AttributeError: HTTPResponse instance has no attribute 'fileno'
>>>
Upvotes: 5
Views: 2548
Reputation: 176930
See http://www.velocityreviews.com/forums/t512553-re-urllib2-urlopen-broken.html.
The problem is that urlib2 was changed to wrap an HTTPResponse object in a socket._fileobject to get a few more file methods. Except (as reported above) HTTPResponse doesn't have a fileno() method, so when _fileobject tries to use it, it blows up.
The solution
Adding an appropriate method to HTTPResponse:
def fileno(self):
return self.fp.fileno()
Or, alternatively, use urllib.urlopen
instead of urrlib2.urlopen
.
There is a bug report for this issue; it was fixed in Python 3 and in Python 2.7.
Upvotes: 3