[python] 파이썬 요청으로 비동기 요청

파이썬 요청 라이브러리 문서에 제공된 샘플을 사용해 보았습니다 .

async.map(rs)응답 코드를 얻었지만 요청 된 각 페이지의 내용을 가져오고 싶습니다. 예를 들어 이것은 작동하지 않습니다.

out = async.map(rs)
print out[0].content



답변

노트

아래 답변은 v0.13.0 + 요청 에는 적용 되지 않습니다 . 이 질문이 작성된 후 비동기 기능이 grequests 로 이동되었습니다 . 그러나, 당신은 대체 할 수 requests와 함께 grequests아래 그것은 작동합니다.

<v0.13.0 요청 사용에 관한 원래 질문을 반영하기 위해이 답변을 그대로 두었습니다.


async.map 비동기 적으로 여러 작업을 수행하려면 다음을 수행 해야합니다.

  1. 각 객체로 수행하려는 작업 (작업)에 대한 기능 정의
  2. 요청에 이벤트 후크로 해당 기능 추가
  3. async.map모든 요청 / 조치 목록에서 전화

예:

from requests import async
# If using requests > v0.13.0, use
# from grequests import async

urls = [
    'http://python-requests.org',
    'http://httpbin.org',
    'http://python-guide.org',
    'http://kennethreitz.com'
]

# A simple task to do to each response object
def do_something(response):
    print response.url

# A list to hold our things to do via async
async_list = []

for u in urls:
    # The "hooks = {..." part is where you define what you want to do
    # 
    # Note the lack of parentheses following do_something, this is
    # because the response will be used as the first argument automatically
    action_item = async.get(u, hooks = {'response' : do_something})

    # Add the task to our list of things to do via async
    async_list.append(action_item)

# Do our list of things to do via async
async.map(async_list)


답변

async이제 독립 모듈 grequests입니다.

여기를 참조하십시오 : https://github.com/kennethreitz/grequests

그리고 거기에 : 파이썬을 통해 여러 HTTP 요청을 보내는 이상적인 방법은 무엇입니까?

설치:

$ pip install grequests

용법:

스택을 빌드하십시오.

import grequests

urls = [
    'http://www.heroku.com',
    'http://tablib.org',
    'http://httpbin.org',
    'http://python-requests.org',
    'http://kennethreitz.com'
]

rs = (grequests.get(u) for u in urls)

스택을 보내

grequests.map(rs)

결과는 다음과 같습니다

[<Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>]

grequests는 동시 요청에 대한 제한을 설정하지 않는 것 같습니다 (예 : 여러 요청이 동일한 서버로 전송되는 경우).


답변

나는 request-futuresgrequests를 테스트 했습니다 . Grequests는 빠르지 만 원숭이 패치 및 종속성과 관련된 추가 문제가 발생합니다. requests-futures는 grequest보다 몇 배 느립니다. 나는 내 자신을 작성하고 간단하게 요청을 ThreadPoolExecutor에 래핑하기로 결정했으며 그 요청 은 거의 빠르지 만 외부 종속성은 없었습니다.

import requests
import concurrent.futures

def get_urls():
    return ["url1","url2"]

def load_url(url, timeout):
    return requests.get(url, timeout = timeout)

with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:

    future_to_url = {executor.submit(load_url, url, 10): url for url in     get_urls()}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            resp_err = resp_err + 1
        else:
            resp_ok = resp_ok + 1


답변

어쩌면 요청-선물은 또 다른 선택이다.

from requests_futures.sessions import FuturesSession

session = FuturesSession()
# first request is started in background
future_one = session.get('http://httpbin.org/get')
# second requests is started immediately
future_two = session.get('http://httpbin.org/get?foo=bar')
# wait for the first request to complete, if it hasn't already
response_one = future_one.result()
print('response one status: {0}'.format(response_one.status_code))
print(response_one.content)
# wait for the second request to complete, if it hasn't already
response_two = future_two.result()
print('response two status: {0}'.format(response_two.status_code))
print(response_two.content)

사무실 문서 에도 권장됩니다 . gevent를 포함하고 싶지 않다면 좋은 것입니다.


답변

게시 된 대부분의 답변에 많은 문제가 있습니다. 제한된 기능으로 포팅 된 더 이상 사용되지 않는 라이브러리를 사용하거나 요청 실행에 너무 많은 마술을 제공하여 오류 처리가 어렵습니다. 위의 카테고리 중 하나에 속하지 않으면 타사 라이브러리이거나 더 이상 사용되지 않습니다.

일부 솔루션은 순수하게 http 요청에서 정상적으로 작동하지만 솔루션은 다른 종류의 요청에 대해서는 부족합니다. 여기에는 고도로 맞춤화 된 솔루션이 필요하지 않습니다.

파이썬 내장 라이브러리를 사용하면 asyncio모든 유형의 비동기 요청을 수행하기에 충분할뿐만 아니라 복잡하고 사용 사례 별 오류 처리에 충분한 유동성을 제공 할 수 있습니다.

import asyncio

loop = asyncio.get_event_loop()

def do_thing(params):
    async def get_rpc_info_and_do_chores(id):
        # do things
        response = perform_grpc_call(id)
        do_chores(response)

    async def get_httpapi_info_and_do_chores(id):
        # do things
        response = requests.get(URL)
        do_chores(response)

    async_tasks = []
    for element in list(params.list_of_things):
       async_tasks.append(loop.create_task(get_chan_info_and_do_chores(id)))
       async_tasks.append(loop.create_task(get_httpapi_info_and_do_chores(ch_id)))

    loop.run_until_complete(asyncio.gather(*async_tasks))

작동 방식은 간단합니다. 비동기 적으로 발생하는 일련의 작업을 만든 다음 해당 작업을 실행하고 완료되면 종료하도록 루프를 요청합니다. 추가 라이브러리는 유지 관리 부족, 기능 부족이 필요하지 않습니다.


답변

나는 이것이 한동안 폐쇄되었다는 것을 알고 있지만 요청 라이브러리에 구축 된 다른 비동기 솔루션을 홍보하는 것이 유용 할 수 있다고 생각했습니다.

list_of_requests = ['http://moop.com', 'http://doop.com', ...]

from simple_requests import Requests
for response in Requests().swarm(list_of_requests):
    print response.content

문서는 다음과 같습니다. http://pythonhosted.org/simple-requests/


답변

threads=list()

for requestURI in requests:
    t = Thread(target=self.openURL, args=(requestURI,))
    t.start()
    threads.append(t)

for thread in threads:
    thread.join()

...

def openURL(self, requestURI):
    o = urllib2.urlopen(requestURI, timeout = 600)
    o...