3

我正在尝试为 Linux 构建下载加速器。我的程序使用 gevent、os 和 urllib2。我的程序收到一个 URL 并尝试同时下载该文件。我所有的代码都是有效的。我唯一的问题是 urllib2.urlopen.read() 阻止我同时运行 .read() 函数。

这是向我抛出的异常。

Traceback (most recent call last):
File "/usr/lib/pymodules/python2.7/gevent/greenlet.py", line 405, in run
result = self._run(*self.args, **self.kwargs)
File "gevent_concurrent_downloader.py", line 94, in childTasklet
_tempRead = handle.read(divisor) # Read/Download part
File "/usr/lib/python2.7/socket.py", line 380, in read
data = self._sock.recv(left)
File "/usr/lib/python2.7/httplib.py", line 561, in read
s = self.fp.read(amt)
File "/usr/lib/python2.7/socket.py", line 380, in read
data = self._sock.recv(left)
File "/usr/lib/pymodules/python2.7/gevent/socket.py", line 407, in recv
wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
File "/usr/lib/pymodules/python2.7/gevent/socket.py", line 153, in wait_read
assert event.arg is None, 'This event is already used by another greenlet: %r' % (event.arg, )
AssertionError: This event is already used by another greenlet: (<Greenlet at 0x2304958: childTasklet(<__main__.NewFile object at 0x22c4390>, 4595517, <addinfourl at 37154616 whose fp = <socket._fileob, 459551, 1)>, timeout('timed out',))
<Greenlet at 0x2304ea8: childTasklet(<__main__.NewFile object at 0x22c4390>,4595517, <addinfourl at 37154616 whose fp = <socket._fileob, 7, -1)failed with AssertionError

我的程序通过调用从 URL 获取文件字节大小来工作:

urllib2.urlopen(URL).info().get("Content-Length") 

并将文件大小除以除数,从而将下载过程分成几部分。在这个例子中,我将下载分成 10 个部分。

每个greenlet都以这种方式运行一个命令:

urllib2.urlopen(URL).read(offset)

这是我在 Pastie 上托管的代码的链接: http : //pastie.org/3253705

感谢您的帮助!

仅供参考:我在 Ubuntu 11.10 上运行。

4

2 回答 2

2

您正在尝试读取来自不同 greenlets 的单个请求的响应。

如果您想使用多个并发连接下载相同的文件,那么如果服务器支持它,您可以使用Rangehttp 标头(对于带有 Range 标头的请求,您将获得 206 状态而不是 200)。见HTTPRangeHandler

于 2012-01-26T05:36:15.503 回答
1

to 的参数read是字节数,而不是偏移量。

似乎 gevent 会让您异步调用 urllib,但不允许您从多个 greenlet 访问相同的资源。

此外,由于它使用的是 wait_read,因此效果仍然是从文件中同步、顺序读取(与您想要实现的完全相反)。

我建议您可能需要低于或使用与 urllib2 不同的库。

于 2012-02-07T16:08:23.757 回答