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の部分に分割しています。

各グリーンレットは、このファションでコマンドを実行します。

urllib2.urlopen(URL).read(offset)

これがpastieでホストされている私のコードへのリンクです:http ://pastie.org/3253705

お手伝いありがとう!

参考:Ubuntu11.10で実行しています。

4

2 に答える 2

2

異なる greenlet からの単一のリクエストに対するレスポンスを読み取ろうとしています。

複数の同時接続を使用して同じファイルをダウンロードしたい場合、サーバーがサポートしている場合はRangehttp ヘッダーを使用できます (Range ヘッダーを使用した要求では 200 ではなく 206 ステータスを取得します)。を参照してくださいHTTPRangeHandler

于 2012-01-26T05:36:15.503 に答える
1

への引数readは、オフセットではなく、バイト数です。

gevent では urllib を非同期に呼び出すことができるようですが、複数の greenlet から同じリソースにアクセスすることはできません。

さらに、wait_read を使用しているため、効果はファイルからの同期的な順次読み取りになります (達成したいこととは正反対です)。

urllib2 より低くするか、urllib2 とは別のライブラリを使用する必要があるかもしれないことをお勧めします。

于 2012-02-07T16:08:23.757 に答える