2012-01-26 14 views
3

Linux用のダウンロードアクセラレータを構築しようとしています。私のプログラムはgevent、os、urllib2を利用しています。私のプログラムはURLを受け取り、ファイルを同時にダウンロードしようとします。私のコードはすべて有効です。私の唯一の問題は、urllib2.urlopen.read()が.read()関数を同時に実行するのを妨げていることです。Python、gevent、urllib2.urlopen.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パートに分割しています。

このfassionでコマンドを実行しますgreenlet各:

urllib2.urlopen(URL).read(offset) 

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

が助けてくれてありがとう!

FYI:私はUbuntu 11.10で動作しています。

+0

irc.freenode.netの#geventチャネルが何らかのヘルプを提供する可能性があります。 – Anorov

答えて

2

あなたは別のグリーンレットからの1回のリクエストに対する応答を読み込もうとしています。

あなたは、サーバーがサポートしている場合、あなたは(あなたが206ステータスの代わりに、Rangeヘッダを持つ要求のための200を取得)Range http headerを使用することができいくつかのの同時接続を使用して同じファイルをダウンロードしたい場合。 HTTPRangeHandlerを参照してください。

1

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

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

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

urllib2よりも低くするか、別のライブラリを使用する必要があるかもしれません。

関連する問題