programing

requests.get()이 반환되지 않는 이유는 무엇입니까?requests.get()에서 사용하는 기본 시간 제한은 무엇입니까?

randomtip 2023. 8. 29. 21:50
반응형

requests.get()이 반환되지 않는 이유는 무엇입니까?requests.get()에서 사용하는 기본 시간 제한은 무엇입니까?

제 대본에.requests.get반환 안 함:

import requests

print ("requesting..")

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

print(r.ok)

가능한 이유는 무엇입니까?치료법은?기본 제한 시간은 얼마입니까?get용도?

사용되는 기본 시간 제한은 얼마입니까?

기본 시간 초과는 다음과 같습니다.None즉, 연결이 닫힐 때까지 대기(정지)합니다.

다음과 같이 시간 초과 값을 지정하면 됩니다.

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

요청 문서에서 보낸 사람:

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

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

참고:

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

저는 request.get()가 반환되는 데 시간이 오래 걸리는 경우가 많습니다.timeout1초입니다.이 문제를 해결하는 몇 가지 방법이 있습니다.

사용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 창에 직접 기록했습니다.)

케빈 버크의 요청 포크를 사용합니다. 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))

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

사용evenlet또는signal유사한 질문에서 이미 언급했듯이, python 요청에 대한 시간 초과. 전체 응답 가져오기

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

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

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

문서화된 "보내기" 기능을 패치하면 많은 종속 라이브러리 및 sdk에서도 모든 요청에 대해 이 문제가 해결됩니다.립을 패치할 때는 TimeoutSource가 아닌 지원/문서화된 기능을 패치해야 합니다. 그렇지 않으면 자동으로 패치의 효과를 잃게 될 수 있습니다.

import requests

DEFAULT_TIMEOUT = 180

old_send = requests.Session.send

def new_send(*args, **kwargs):
     if kwargs.get("timeout", None) is None:
         kwargs["timeout"] = DEFAULT_TIMEOUT
     return old_send(*args, **kwargs)

requests.Session.send = new_send

TCP 자체에도 기본 시간 초과가 있기 때문에 시간 초과가 발생하지 않고 기본 시간 초과를 사용하면 거의 아무것도 손상되지 않습니다.

경우,returns"의 이유는 "requests.get never returns"이기 입니다.requests.get()먼저 ipv6 ip로 확인된 호스트에 연결을 시도합니다.ipv6 IP를 연결하는 데 문제가 발생하여 고착된 경우 명시적으로 설정한 경우에만 ipv4 IP를 재시도합니다.timeout=<N seconds>시간 제한을 설정합니다.

내 해결책은 파이썬을 원숭이 패치하는 것입니다.socketipv6(또는 ipv4가 작동하지 않는 경우 ipv4)를 무시하는 은 이 대답이나 이 대답하나가 나에게 효과적입니다.

그런지 수도 있습니다.curl 령이작다면, 하냐왜니입니다.curlcomplete를 합니다.은 소켓시호추수있습다니로 할 수 .strace -ff -e network -s 10000 -- curl -vLk '<your url>'지휘권비단뱀의 경우,strace -ff -e network -s 10000 -- python3 <your python script>명령을 사용할 수 있습니다.

모든 답변을 검토하고 문제가 여전히 존재한다는 결론을 내렸습니다.일부 사이트에서는 요청이 무한정 중단될 수 있으며 멀티프로세싱을 사용하는 것은 과도한 작업인 것 같습니다.제 접근 방식은 다음과 같습니다(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)

갱신하다

conn_timeout 및 read_timeout 사용에 대한 사용 중지 경고가 표시되면 이 참조의 하단 근처에서 ClientTimeout 데이터 구조를 사용하는 방법을 확인하십시오.위의 원래 코드에 대한 링크된 참조에 따라 이 데이터 구조를 적용하는 간단한 방법은 다음과 같습니다.

async def get_http(url):
    timeout = aiohttp.ClientTimeout(total=60)
    async with aiohttp.ClientSession(timeout=timeout) as client:
        try:
            etc.

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

반응형