code

requests.get ()이 반환되지 않는 이유는 무엇입니까?

codestyles 2020. 10. 12. 07:33
반응형

requests.get ()이 반환되지 않는 이유는 무엇입니까? requests.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사용 하는 기본 제한 시간은 무엇입니까 ?


사용되는 기본 시간 제한은 무엇입니까?

기본 제한 시간은 None연결이 닫힐 때까지 대기 (중단)됨을 의미합니다.

시간 초과 값을 전달하면 어떻게됩니까?

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

에서 요청 문서 :

timeout 매개 변수를 사용하여 지정된 시간 (초) 후에 응답 대기를 중지하도록 Requests에 지시 할 수 있습니다.

>>> 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)

노트 :

시간 제한은 전체 응답 다운로드에 대한 시간 제한이 아닙니다. 오히려 서버가 timeout 초 동안 응답을 발행하지 않은 경우 (더 정확하게는 timeout 초 동안 기본 소켓에 수신 된 바이트가없는 경우) 예외가 발생합니다.

requests.get () timeout이 1 초라도 반환하는 데 시간이 너무 오래 걸리는 일이 많이 발생합니다 . 이 문제를 극복하는 몇 가지 방법이 있습니다.

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)

제한 시간 값은 연결 및 읽기 제한 시간 모두에 적용됩니다. 값을 개별적으로 설정하려면 튜플을 지정하십시오.

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

참고 : 이후 변경 사항이 기본 요청 프로젝트에 병합되었습니다 .

3. 유사한 질문에서 이미 언급했듯이 evenlet또는 사용 signal: python requests.get 전체 응답에 대한 시간 초과


모든 답변을 검토하고 문제가 여전히 존재한다는 결론에 도달했습니다. 일부 사이트에서는 요청이 무한히 멈출 수 있으며 다중 처리를 사용하는 것은 과도한 것 같습니다. 내 접근 방식 (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)

기본 제한 시간을 코드 묶음에 쉽게 추가하고 싶었습니다 (시간 제한이 문제를 해결한다고 가정)

이것이 요청 저장소에 제출 된 티켓에서 선택한 솔루션입니다.

크레딧 : 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,...

참고 URL : https://stackoverflow.com/questions/17782142/why-doesnt-requests-get-return-what-is-the-default-timeout-that-requests-get

반응형