it-swarm.dev

لماذا لا يعود request.get ()؟ ما هي المهلة الافتراضية التي يستخدمها orders.get ()؟

في البرنامج النصي الخاص بي ، requests.get لا يُرجع أبدًا:

import requests

print ("requesting..")

# This call never returns!
r = requests.get(
    "http://www.justdial.com",
    proxies = {'http': '222.255.169.74:8080'},
)

print(r.ok)

ماذا يمكن أن يكون السبب (الأسباب) المحتمل؟ أي علاج؟ ما هي المهلة الافتراضية التي يستخدمها get؟

71
Nawaz

ما هي المهلة الافتراضية التي تحصل عليها؟

المهلة الافتراضية هي None ، مما يعني أنها ستنتظر (يحدث تعليق) حتى يتم إغلاق الاتصال.

ماذا يحدث عندما تمر في قيمة المهلة؟

r = requests.get(
    'http://www.justdial.com',
    proxies={'http': '222.255.169.74:8080'},
    timeout=5
)
104
ron rothman

من طلبات الوثائق :

يمكنك إخبار الطلبات بالتوقف عن انتظار استجابة بعد عدد معين من الثواني مع معلمة المهلة:

>>> requests.get('http://github.com', timeout=0.001)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(Host='github.com', port=80): Request timed out. (timeout=0.001)

ملحوظة:

المهلة ليست مهلة لتنزيل الاستجابة بالكامل ؛ بدلاً من ذلك ، يتم رفع استثناء إذا لم يصدر الخادم استجابة لثواني المهلة (بشكل أكثر دقة ، إذا لم يتم تلقي أي بايت على المقبس الأساسي لثواني المهلة).

يحدث لي كثيرًا أن طلبات .get () تستغرق وقتًا طويلاً للعودة حتى إذا كانت timeout هي ثانية واحدة. هناك بعض الطرق للتغلب على هذه المشكلة:

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):
        if kwargs['connect'] is None:
            kwargs['connect'] = 5
        if kwargs['read'] is None:
            kwargs['read'] = 5
        super(MyTimeout, self).__init__(*args, **kwargs)

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)

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

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

ملاحظة: تم دمج التغيير منذ ذلك الحين في مشروع الطلبات الرئيسي .

3. استخدام evenlet أو signal كما هو مذكور بالفعل في سؤال مماثل: مهلة ل python طلبات. احصل على استجابة كاملة

29
Hieu

استعرض جميع الإجابات وخلص إلى أن المشكلة لا تزال قائمة. في بعض المواقع ، قد يتعطل الطلبات إلى ما لا نهاية ويبدو أن استخدام المعالجة المتعددة مبالغ فيه. إليكم مقاربي (Python 3.5+):

import asyncio

import aiohttp


async def get_http(url):
    async with aiohttp.ClientSession(conn_timeout=1, read_timeout=3) as client:
        try:
            async with client.get(url) as response:
                content = await response.text()
                return content, response.status
        except Exception:
            pass


loop = asyncio.get_event_loop()
task = loop.create_task(get_http('http://example.com'))
loop.run_until_complete(task)
result = task.result()
if result is not None:
    content, status = task.result()
    if status == 200:
        print(content)
2
Alex Polekha

أردت إضافة مهلة افتراضية بسهولة إلى مجموعة من التعليمات البرمجية (على افتراض أن المهلة تحل مشكلتك)

هذا هو الحل الذي التقطته من بطاقة مقدمة إلى مستودع الطلبات.

الائتمان: https://github.com/kennethreitz/requests/issues/2011#issuecomment-477784399

الحل هو آخر سطرين هنا ، لكنني أظهر المزيد من التعليمات البرمجية لسياق أفضل. أحب استخدام جلسة لإعادة محاولة السلوك.

import requests
import functools
from requests.adapters import HTTPAdapter,Retry


def requests_retry_session(
        retries=10,
        backoff_factor=2,
        status_forcelist=(500, 502, 503, 504),
        session=None,
        ) -> requests.Session:
    session = session or requests.Session()
    retry = Retry(
            total=retries,
            read=retries,
            connect=retries,
            backoff_factor=backoff_factor,
            status_forcelist=status_forcelist,
            )
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    # set default timeout
    for method in ('get', 'options', 'head', 'post', 'put', 'patch', 'delete'):
        setattr(session, method, functools.partial(getattr(session, method), timeout=30))
    return session

ثم يمكنك أن تفعل شيئا مثل هذا:

requests_session = requests_retry_session()
r = requests_session.get(url=url,...
0
Tim Richardson