Voglio collegarmi a un elenco di molti siti diversi molto velocemente. Sto usando asyncio per farlo in modo asincrono e ora voglio aggiungere un timeout per quando le connessioni devono essere ignorate se impiegano troppo tempo a rispondere.Come posso aggiungere un timeout della connessione con asyncio?
Come implementarlo?
import ssl
import asyncio
from contextlib import suppress
from concurrent.futures import ThreadPoolExecutor
import time
@asyncio.coroutine
def run():
while True:
host = yield from q.get()
if not host:
break
with suppress(ssl.CertificateError):
reader, writer = yield from asyncio.open_connection(host[1], 443, ssl=True) #timout option?
reader.close()
writer.close()
@asyncio.coroutine
def load_q():
# only 3 entries for debugging reasons
for host in [[1, 'python.org'], [2, 'qq.com'], [3, 'google.com']]:
yield from q.put(host)
for _ in range(NUM):
q.put(None)
if __name__ == "__main__":
NUM = 1000
q = asyncio.Queue()
loop = asyncio.get_event_loop()
loop.set_default_executor(ThreadPoolExecutor(NUM))
start = time.time()
coros = [asyncio.async(run()) for i in range(NUM)]
loop.run_until_complete(load_q())
loop.run_until_complete(asyncio.wait(coros))
end = time.time()
print(end-start)
(Su un sidenote: Ha qualcuno un'idea di come ottimizzare questo?)
Hai dimenticato di "cedere da" le chiamate a 'q.put (None)' all'interno di 'load_q', quindi questo codice non funzionerà come attualmente scritto. – dano
non hai bisogno di lettori, scrittori qui. Si potrebbe usare 'asyncio.create_connection' con' Protocol' che non fa nulla (chiude la connessione di rete non appena viene stabilita). Ecco [esempio di codice che ho provato sulla top milioni di elenchi di siti di Alexa] (http://stackoverflow.com/a/20722204/4279) (potrebbe essere leggermente sorpassato ad esempio, non usa alcune funzioni di convenienza come ' asyncio.wait_for() '). Usa un singolo thread e si apre alle connessioni 'limit' ssl. – jfs