2014-06-19 9 views
5

Ho appena iniziato a utilizzare le librerie asyncio di Python3.4 e ho scritto un piccolo programma che tenta di scaricare contemporaneamente 50 pagine Web alla volta. Il programma esplode dopo alcune centinaia di richieste con un'eccezione "Troppi file aperti".Le connessioni non si stanno chiudendo con Python3 asyncio richieste HTTP simultanee get

Ho pensato che il mio metodo di recupero chiudesse le connessioni con la chiamata al metodo 'response.read_and_close()'.

Qualche idea cosa sta succedendo qui? Sto andando su questo problema nel modo giusto?

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

L'errore che sto ottenendo è:

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

Questo funziona per me. Quale versione di 'aiohttp' stai usando? Ho 0.8.1. – dano

risposta

2

Ok finalmente ho potuto farlo funzionare.

Risulta che ho dovuto utilizzare un TCPConnector che raggruppa le connessioni.

Così ho fatto questa variabile:

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

e farla passare attraverso ad ogni richiesta GET. La mia nuova routine di recupero si presenta in questo modo:

@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

Aha, mi sto lamentando.

Il connettore esplicito può sicuramente risolvere il problema.

https://github.com/KeepSafe/aiohttp/pull/79 dovrebbe risolvere anche per connettori impliciti.

La ringrazio molto per la ricerca di perdita di risorse in aiohttp

UPD. aiohttp 0.8.2 non ha alcun problema.

Problemi correlati