python معنى - مهلة لطلبات python. الحصول على استجابة كاملة




8 Answers

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

import requests
import eventlet
eventlet.monkey_patch()

with eventlet.Timeout(10):
    requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip", verify=False)
شرح بالعربي

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

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 دمجها في مشروع الطلبات الرئيسية ، ولكن لم يتم قبولها بعد.




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

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

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




هذا الرمز يعمل على socketError 11004 و 10060 ......

# -*- encoding:UTF-8 -*-
__author__ = 'ACE'
import requests
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class TimeOutModel(QThread):
    Existed = pyqtSignal(bool)
    TimeOut = pyqtSignal()

    def __init__(self, fun, timeout=500, parent=None):
        """
        @param fun: function or lambda
        @param timeout: ms
        """
        super(TimeOutModel, self).__init__(parent)
        self.fun = fun

        self.timeer = QTimer(self)
        self.timeer.setInterval(timeout)
        self.timeer.timeout.connect(self.time_timeout)
        self.Existed.connect(self.timeer.stop)
        self.timeer.start()

        self.setTerminationEnabled(True)

    def time_timeout(self):
        self.timeer.stop()
        self.TimeOut.emit()
        self.quit()
        self.terminate()

    def run(self):
        self.fun()


bb = lambda: requests.get("http://ipv4.download.thinkbroadband.com/1GB.zip")

a = QApplication([])

z = TimeOutModel(bb, 500)
print 'timeout'

a.exec_()



على الرغم من أن السؤال يتعلق بالطلبات ، فإنني أجد من السهل جدًا إجراء ذلك مع pycurl CURLOPT_TIMEOUT أو CURLOPT_TIMEOUT_MS.

لا يوجد خيوط أو إشارة مطلوبة:

import pycurl
import StringIO

url = 'http://www.example.com/example.zip'
timeout_ms = 1000
raw = StringIO.StringIO()
c = pycurl.Curl()
c.setopt(pycurl.TIMEOUT_MS, timeout_ms)  # total timeout in milliseconds
c.setopt(pycurl.WRITEFUNCTION, raw.write)
c.setopt(pycurl.NOSIGNAL, 1)
c.setopt(pycurl.URL, url)
c.setopt(pycurl.HTTPGET, 1)
try:
    c.perform()
except pycurl.error:
    traceback.print_exc() # error generated on timeout
    pass # or just pass if you don't want to print the error



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




حل واحد آخر (يمكنك الحصول عليه من 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

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




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

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




Related

python timeout python-requests