python - شرح - requests معنى




مهلة لطلبات python. الحصول على استجابة كاملة (10)

Set stream=True واستخدم r.iter_content(1024) . نعم ، eventlet.Timeout فقط بطريقة ما لا يعمل بالنسبة لي.

try:
    start = time()
    timeout = 5
    with get(config['source']['online'], stream=True, timeout=timeout) as r:
        r.raise_for_status()
        content = bytes()
        content_gen = r.iter_content(1024)
        while True:
            if time()-start > timeout:
                raise TimeoutError('Time out! ({} seconds)'.format(timeout))
            try:
                content += next(content_gen)
            except StopIteration:
                break
        data = content.decode().split('\n')
        if len(data) in [0, 1]:
            raise ValueError('Bad requests data')
except (exceptions.RequestException, ValueError, IndexError, KeyboardInterrupt,
        TimeoutError) as e:
    print(e)
    with open(config['source']['local']) as f:
        data = [line.strip() for line in f.readlines()]

المناقشة هنا https://redd.it/80kp1h

https://code.i-harness.com

أنا أجمع إحصاءات حول قائمة مواقع الويب وأستخدم طلبات لها لبساطتها. هنا الكود:

data=[]
websites=['http://google.com', 'http://bbc.co.uk']
for w in websites:
    r= requests.get(w, verify=False)
    data.append( (r.url, len(r.content), r.elapsed.total_seconds(), str([(l.status_code, l.url) for l in r.history]), str(r.headers.items()), str(r.cookies.items())) )

الآن ، أرغب في request.get إلى انتهاء المهلة بعد 10 ثوانٍ حتى لا تتعطل الحلقة.

لقد كان هذا السؤال محل اهتمام من before أيضًا ولكن لم تكن أي من الإجابات نظيفة. سأضع بعض الفضل في هذا للحصول على إجابة لطيفة.

أسمع أن ربما لا تستخدم طلبات فكرة جيدة ولكن بعد ذلك كيف يمكنني الحصول على طلبات الأشياء لطيفة تقدم. (تلك الموجودة في المجموعة)


UPDATE: http://docs.python-requests.org/en/master/user/advanced/#timeouts

في الإصدار الجديد من requests :

إذا قمت بتحديد قيمة واحدة للمهلة ، مثل هذا:

r = requests.get('https://github.com', timeout=5)

سيتم تطبيق قيمة المهلة على كل من connect ومهلة read . حدد فئة إذا كنت ترغب في تعيين القيم بشكل منفصل:

r = requests.get('https://github.com', timeout=(3.05, 27))

إذا كان الخادم البعيد بطيئًا جدًا ، فيمكنك إخبار "الطلبات" بالانتظار إلى الأبد للاستجابة ، وذلك بتمرير "بلا" كقيمة مهلة ثم استرداد كوب من القهوة.

r = requests.get('https://github.com', timeout=None)

جوابي القديم (الذي عفا عليه الزمن) (والذي تم نشره منذ فترة طويلة):

هناك طرق أخرى للتغلب على هذه المشكلة:

1. استخدم الفئة الداخلية TimeoutSauce

من: https://github.com/kennethreitz/requests/issues/1928#issuecomment-35811896

import requests from requests.adapters import TimeoutSauce

class MyTimeout(TimeoutSauce):
    def __init__(self, *args, **kwargs):
        connect = kwargs.get('connect', 5)
        read = kwargs.get('read', connect)
        super(MyTimeout, self).__init__(connect=connect, read=read)

requests.adapters.TimeoutSauce = MyTimeout

من المفترض أن يؤدي هذا الرمز إلى تعيين مهلة القراءة على أنها تساوي مهلة الاتصال ، وهي قيمة المهلة التي تمر عليها في مكالمة Session.get () الخاصة بك. (لاحظ أني لم اختبر هذا الكود فعليًا ، لذا قد يحتاج إلى بعض التصحيح السريع ، لقد قمت بكتابته مباشرة في نافذة GitHub.)

2. استخدام شوكة من الطلبات من kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout

من وثائقه: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst

إذا قمت بتحديد قيمة واحدة للمهلة ، مثل هذا:

r = requests.get('https://github.com', timeout=5)

سيتم تطبيق قيمة المهلة على كل من الاتصال ومهلة القراءة. حدد فئة إذا كنت ترغب في تعيين القيم بشكل منفصل:

r = requests.get('https://github.com', timeout=(3.05, 27))

طلب Kevinburke دمجها في مشروع الطلبات الرئيسية ، ولكن لم يتم قبولها بعد.


إذا وصل الأمر إلى ذلك ، قم بإنشاء مؤشر ترابط مراقب يقوم بتعطيل الحالة الداخلية للطلبات بعد 10 ثوانٍ ، على سبيل المثال:

  • يغلق المقبس الأساسي ، ومن الناحية المثالية
  • يؤدي إلى حدوث استثناء في حالة إعادة الطلبات للعملية

لاحظ أنه استنادًا إلى مكتبات النظام ، قد لا تتمكن من تحديد موعد نهائي على حل DNS.


اضبط معلمة المهلة :

r = requests.get(w, verify=False, timeout=10)

طالما لم تقم بتعيين stream=True على هذا الطلب ، سيؤدي ذلك إلى استدعاء requests.get() إلى المهلة إذا استغرق الاتصال أكثر من عشر ثوانٍ ، أو إذا كان الخادم لا يرسل البيانات لأكثر من عشرة ثواني.


حل واحد آخر (يمكنك الحصول عليه من http://docs.python-requests.org/en/master/user/advanced/#streaming-uploads )

قبل التحميل ، يمكنك معرفة حجم المحتوى:

TOO_LONG = 10*1024*1024  # 10 Mb
big_url = "http://ipv4.download.thinkbroadband.com/1GB.zip"
r = requests.get(big_url, stream=True)
print (r.headers['content-length'])
# 1073741824  

if int(r.headers['content-length']) < TOO_LONG:
    # upload content:
    content = r.content

ولكن كن حذرًا ، يمكن للمرسل إعداد قيمة غير صحيحة في حقل استجابة "طول المحتوى".


عفوا لكنني أتساءل لماذا لا أحد اقترح الحل الأبسط التالية؟ : -o

requests.get ('www.mypage.com' ، timeout = 20)


في حالة استخدامك stream=True الخيار stream=True يمكنك إجراء ذلك:

r = requests.get(
    'http://url_to_large_file',
    timeout=1,  # relevant only for underlying socket
    stream=True)

with open('/tmp/out_file.txt'), 'wb') as f:
    start_time = time.time()
    for chunk in r.iter_content(chunk_size=1024):
        if chunk:  # filter out keep-alive new chunks
            f.write(chunk)
        if time.time() - start_time > 8:
            raise Exception('Request took longer than 8s')

لا يحتاج الحل إلى إشارات أو معالجة متعددة.


قد يكون هذا مبالغة ، ولكن قائمة انتظار المهام الموزعة من Celery لديها دعم جيد للمهلة.

على وجه الخصوص ، يمكنك تحديد حد زمني بسيط يقوم فقط برفع استثناء في العملية (حتى تتمكن من التنظيف) و / أو حدًا صعبًا ينتهي بالمهمة عندما يتم تجاوز الحد الزمني.

تحت الأغطية ، يستخدم هذا الأسلوب الإشارات نفسها كما هو مشار إليه في المنشور "قبل" الخاص بك ، ولكن بطريقة أكثر قابلية للاستخدام وسهولة التحكم. وإذا كانت قائمة مواقع الويب التي تراقبها طويلة ، فقد تستفيد من ميزتها الأساسية - كل أنواع الطرق لإدارة تنفيذ عدد كبير من المهام.


لقد توصلت إلى حل مباشر أكثر قبيحًا ، لكنه حل المشكلة الحقيقية. يذهب قليلا مثل هذا:

resp = requests.get(some_url, stream=True)
resp.raw._fp.fp._sock.settimeout(read_timeout)
# This will load the entire response even though stream is set
content = resp.content

يمكنك قراءة الشرح الكامل here


ماذا عن استخدام eventlet؟ إذا كنت تريد مهلة الطلب بعد 10 ثوانٍ ، حتى إذا تم تلقي البيانات ، فسيعمل هذا المقتطف من أجلك:

import requests
import eventlet
eventlet.monkey_patch()

with eventlet.Timeout(10):
    requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip", verify=False)




python-requests