2016-12-27 71 views
1

在asyncio中工作時,我試圖使用列表理解來構建我的任務列表。該函數的基本形式如下:不執行函數的Python asyncio任務列表生成

import asyncio 
import urllib.request as req 
@asyncio.coroutine 
def coro(term): 
    print(term) 
    google = "https://www.google.com/search?q=" + term.replace(" ", "+") + "&num=100&start=0" 
    request = req.Request(google, None, headers) 
    (some beautiful soup stuff) 

我的目標是使用的術語列表創建我的任務列表:

terms = ["pie", "chicken" ,"things" ,"stuff"]  
tasks=[ 
    coro("pie"), 
    coro("chicken"), 
    coro("things"), 
    coro("stuff")] 

我最初的想法是:

loop = asyncio.get_event_loop() 
tasks = [my_coroutine(term) for term in terms] 
loop.run_until_complete(asyncio.wait(tasks)) 
loop.close() 

這不會創建它在列表理解期間運行該函數的任務列表。有沒有辦法使用快捷方式來創建任務列表,而無需編寫任何任務?

回答

2

你的HTTP客戶端不支持ASYNCIO,你就不會得到預期的結果。試試這個看.wait()不工作,你希望:

import asyncio 
import random 

@asyncio.coroutine 
def my_coroutine(term): 
    print("start", term) 
    yield from asyncio.sleep(random.uniform(1, 3)) 
    print("end", term) 


terms = ["pie", "chicken", "things", "stuff"] 
loop = asyncio.get_event_loop() 
tasks = [my_coroutine(term) for term in terms] 
print("Here we go!") 
loop.run_until_complete(asyncio.wait(tasks)) 
loop.close() 

如果使用asyncio.gather()你得到一個未來封裝所有的任務,它可以與.cancel()輕易取消,在這裏與Python 3.5+ async def/await語法(證明但工作原理是一樣與@coroutineyield from):

import asyncio 

import random 


async def my_coroutine(term): 
    print("start", term) 
    n = random.uniform(0.2, 1.5) 
    await asyncio.sleep(n) 
    print("end", term) 
    return "Term {} slept for {:.2f} seconds".format(term, n) 


async def stop_all(): 
    """Cancels all still running tasks after one second""" 
    await asyncio.sleep(1) 
    print("stopping") 
    fut.cancel() 
    return ":-)" 


loop = asyncio.get_event_loop() 
terms = ["pie", "chicken", "things", "stuff"] 
tasks = (my_coroutine(term) for term in terms) 
fut = asyncio.gather(stop_all(), *tasks, return_exceptions=True) 

print("Here we go!") 
loop.run_until_complete(fut) 

for task_result in fut.result(): 
    if not isinstance(task_result, Exception): 
     print("OK", task_result) 
    else: 
     print("Failed", task_result) 

loop.close() 

最後,如果你想使用異步HTTP客戶端,嘗試aiohttp。先用安裝:

pip install aiohttp 

然後嘗試這個例子,它採用asyncio.as_completed

import asyncio 

import aiohttp 


async def fetch(session, url): 
    print("Getting {}...".format(url)) 
    async with session.get(url) as resp: 
     text = await resp.text() 
    return "{}: Got {} bytes".format(url, len(text)) 


async def fetch_all(): 
    async with aiohttp.ClientSession() as session: 
     tasks = [fetch(session, "http://httpbin.org/delay/{}".format(delay)) 
       for delay in (1, 1, 2, 3, 3)] 
     for task in asyncio.as_completed(tasks): 
      print(await task) 
    return "Done." 


loop = asyncio.get_event_loop() 
resp = loop.run_until_complete(fetch_all()) 
print(resp) 
loop.close() 
0

這部作品在Python 3.5(添加了新的async-await語法):

import asyncio 

async def coro(term): 
    for i in range(3): 
     await asyncio.sleep(int(len(term))) # just sleep 
     print("cor1", i, term) 

terms = ["pie", "chicken", "things", "stuff"] 
tasks = [coro(term) for term in terms] 

loop = asyncio.get_event_loop() 
cors = asyncio.wait(tasks) 
loop.run_until_complete(cors) 

should't你yield from req.Request(google, None, headers)版本?和(這是什麼庫?)這個庫甚至用於asyncio

(這裏是相同的代碼與蟒蛇< = 3.4語法,缺少的部分是與上述相同):

@asyncio.coroutine 
def coro(term): 
    for i in range(3): 
     yield from asyncio.sleep(int(len(term))) # just sleep 
     print("cor1", i, term)