12

Pythonで大きなファイルをダウンロードするときは、接続プロセスだけでなく、ダウンロードにも時間制限を設けたいと思います。

私は次のPythonコードで試しています:

import requests

r = requests.get('http://ipv4.download.thinkbroadband.com/1GB.zip', timeout = 0.5, prefetch = False)

print r.headers['content-length']

print len(r.raw.read())

ドキュメントに正しく記載されているように、これは機能しません(ダウンロードには時間制限がありません):https ://requests.readthedocs.org/en/latest/user/quickstart/#timeouts

可能であれば、これは素晴らしいことです。

r.raw.read(timeout = 10)

問題は、ダウンロードに時間制限を設ける方法です。

4

3 に答える 3

11

そして答えは次のとおりです。ブロックしているため、リクエストを使用しないでください。イベントレットなどの非ブロッキングネットワークI/Oを使用します。

import eventlet
from eventlet.green import urllib2
from eventlet.timeout import Timeout

url5 = 'http://ipv4.download.thinkbroadband.com/5MB.zip'
url10 = 'http://ipv4.download.thinkbroadband.com/10MB.zip'

urls = [url5, url5, url10, url10, url10, url5, url5]

def fetch(url):
    response = bytearray()
    with Timeout(60, False):
        response = urllib2.urlopen(url).read()
    return url, len(response)

pool = eventlet.GreenPool()
for url, length in pool.imap(fetch, urls):
    if (not length):
        print "%s: timeout!" % (url)
    else:
        print "%s: %s" % (url, length)

期待される結果を生み出します:

http://ipv4.download.thinkbroadband.com/5MB.zip: 5242880
http://ipv4.download.thinkbroadband.com/5MB.zip: 5242880
http://ipv4.download.thinkbroadband.com/10MB.zip: timeout!
http://ipv4.download.thinkbroadband.com/10MB.zip: timeout!
http://ipv4.download.thinkbroadband.com/10MB.zip: timeout!
http://ipv4.download.thinkbroadband.com/5MB.zip: 5242880
http://ipv4.download.thinkbroadband.com/5MB.zip: 5242880
于 2012-11-27T20:42:52.250 に答える
2

Requestsのprefetch=Falseパラメーターを使用すると、(一度にすべてではなく)一度に任意のサイズの応答のチャンクを取り込むことができます。

あなたがする必要があるのは、リクエスト全体をプリロードしないようにリクエストに指示し、一度に小さなチャンクをフェッチしながら、これまでに読んだ時間を自分で保持することです。を使用してチャンクをフェッチできますr.raw.read(CHUNK_SIZE)。全体として、コードは次のようになります。

import requests
import time

CHUNK_SIZE = 2**12  # Bytes
TIME_EXPIRE = time.time() + 5  # Seconds

r = requests.get('http://ipv4.download.thinkbroadband.com/1GB.zip', prefetch=False)

data = ''
buffer = r.raw.read(CHUNK_SIZE)
while buffer:
    data += buffer
    buffer = r.raw.read(CHUNK_SIZE)

    if TIME_EXPIRE < time.time():
        # Quit after 5 seconds.
        data += buffer
        break

r.raw.release_conn()

print "Read %s bytes out of %s expected." % (len(data), r.headers['content-length'])

r.raw.read(...)決勝戦は任意の時間遅れる可能性があるため、これには割り当てられた5秒より少し長い時間がかかる場合があることに注意してください。ただし、少なくともマルチスレッドやソケットのタイムアウトには依存しません。

于 2012-11-27T03:46:02.093 に答える
-3

スレッドでダウンロードを実行します。これは、時間どおりに終了しなかった場合に中止できます。

import requests
import threading

URL='http://ipv4.download.thinkbroadband.com/1GB.zip'
TIMEOUT=0.5

def download(return_value):
    return_value.append(requests.get(URL))

return_value = []
download_thread = threading.Thread(target=download, args=(return_value,))
download_thread.start()
download_thread.join(TIMEOUT)

if download_thread.is_alive():
    print 'The download was not finished on time...'
else:
    print return_value[0].headers['content-length']
于 2012-11-26T21:14:08.527 に答える