2014-06-19 2 views
5

방금 ​​Python3.4에서 asyncio 라이브러리를 사용하기 시작했으며 한 번에 50 개의 웹 페이지를 동시에 가져 오는 작은 프로그램을 작성했습니다. '너무 많은 파일 열기'예외가있는 수백 건의 요청 후에 프로그램이 폭발합니다.Python3 asyncio 동시 HTTP get 요청으로 연결이 닫히지 않습니다

내 fetch 메소드가 'response.read_and_close()'메소드 호출로 연결을 닫는 것으로 생각했습니다.

여기에 어떤 아이디어가 있습니까? 나는이 문제에 대해 올바른 방향으로 가고 있는가?

import asyncio 
import aiohttp 

@asyncio.coroutine 
def fetch(url): 
    response = yield from aiohttp.request('GET', url) 
    response = yield from response.read_and_close() 
    return response.decode('utf-8') 

@asyncio.coroutine 
def print_page(url): 
    page = yield from fetch(url) 
    # print(page) 

@asyncio.coroutine 
def process_batch_of_urls(round, urls): 
    print("Round starting: %d" % round) 
    coros = [] 
    for url in urls: 
     coros.append(asyncio.Task(print_page(url))) 
    yield from asyncio.gather(*coros) 
    print("Round finished: %d" % round) 

@asyncio.coroutine 
def process_all(): 
    api_url = 'https://google.com' 
    for i in range(10): 
    urls = [] 
    for url in range(50): 
     urls.append(api_url) 
    yield from process_batch_of_urls(i, urls) 


loop = asyncio.get_event_loop() 
loop.run_until_complete(process_all()) 

내가지고있어 오류가 있습니다 : 나는 마침내 그것이 작동있어

Traceback (most recent call last): 
    File "/usr/local/lib/python3.4/site-packages/aiohttp/client.py", line 106, in request 
    File "/usr/local/lib/python3.4/site-packages/aiohttp/connector.py", line 135, in connect 
    File "/usr/local/lib/python3.4/site-packages/aiohttp/connector.py", line 242, in _create_connection 
    File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/asyncio/base_events.py", line 424, in create_connection 
    File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/asyncio/base_events.py", line 392, in create_connection 
    File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socket.py", line 123, in __init__ 
OSError: [Errno 24] Too many open files 

During handling of the above exception, another exception occurred: 
+0

나를 위해 잘 작동합니다. 'aiohttp '의 어떤 버전을 사용하고 있습니까? 나는 0.8.1을 얻었다. – dano

답변

2

좋아.

밝혀졌습니다. 연결을 풀링하는 TCPConnector를 사용해야했습니다.

connector = aiohttp.TCPConnector(share_cookies=True, loop=loop) 

각각 얻을 요청에 통과 :

그래서 나는이 변수를했다. 내 새 가져 오기 루틴은 다음과 같습니다.

@asyncio.coroutine 
def fetch(url): 
    data = "" 
    try: 
    yield from asyncio.sleep(1) 
    response = yield from aiohttp.request('GET', url, connector=connector) 
    except Exception as exc: 
     print('...', url, 'has error', repr(str(exc))) 
    else: 
     data = (yield from response.read()).decode('utf-8', 'replace') 
     response.close() 

    return data 
5

아하, 나는 grok 문제.

명백한 커넥터가이 문제를 확실히 해결할 수 있습니다.

https://github.com/KeepSafe/aiohttp/pull/79도 암시 적 커넥터 용으로 수정해야합니다.

UPD aiohttp 에서 자원 누출을 찾아 주셔서 대단히 감사합니다. aiohttp 0.8.2에는 문제가 없습니다.

관련 문제