Python, gevent, urllib2.urlopen.read (), ускоритель загрузки

Я пытаюсь создать ускоритель загрузки для 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

Спасибо вам за помощь!

К вашему сведению: я работаю на Ubuntu 11.10.


person Froweey    schedule 26.01.2012    source источник
comment
Канал #gevent на irc.freenode.net может оказать некоторую помощь.   -  person Anorov    schedule 26.01.2012


Ответы (2)


Вы пытаетесь прочитать ответ на один запрос от разных гринлетов.

Если вы хотите загрузить один и тот же файл, используя несколько одновременных подключений, вы можете использовать http://tools.ietf.org/html/rfc2616#section-14.35, если сервер поддерживает его (вы получаете статус 206 вместо 200 для запроса с заголовком Range). См. HTTPRangeHandler.

person jfs    schedule 26.01.2012

аргумент read - это количество байтов, а не смещение.

Кажется, что gevent позволит вам вызывать urllib асинхронно, но не позволит вам получить доступ к одному и тому же ресурсу из нескольких гринлетов.

Кроме того, поскольку он использует wait_read, эффект по-прежнему будет синхронным, последовательным чтением из файла (полная противоположность тому, чего вы хотели достичь).

Я бы посоветовал вам использовать библиотеку ниже urllib2 или использовать другую библиотеку вместо urllib2.

person Ivo    schedule 07.02.2012