简体   繁体   English

Python asyncio 任务列表生成,不执行函数

[英]Python asyncio task list generation without executing the function

While working in asyncio, I'm trying to use a list comprehension to build my task list.在 asyncio 中工作时,我正在尝试使用列表理解来构建我的任务列表。 The basic form of the function is as follows:该函数的基本形式如下:

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)

My goal is to use a list of terms to create my task list:我的目标是使用术语列表来创建我的任务列表:

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

My initial thought was:我最初的想法是:

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

This doesn't create the task list it runs the function during the list comprehension.这不会创建在列表理解期间运行该函数的任务列表。 Is there a way to use a shortcut to create the task list wihout writing every task?有没有办法使用快捷方式来创建任务列表而无需编写每个任务?

Your HTTP client does not support asyncio, and you will not get the expected results.您的 HTTP 客户端不支持 asyncio,您将无法获得预期的结果。 Try this to see .wait() does work as you expected:试试这个,看看.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()

If you use asyncio.gather() you get one future encapsulating all your tasks, which can be easily canceled with .cancel() , here demonstrated with python 3.5+ async def / await syntax (but works the same with @coroutine and yield from ):如果你使用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()

And finally, if you want to use an async HTTP client, try aiohttp .最后,如果您想使用异步 HTTP 客户端,请尝试aiohttp First install it with:首先安装它:

pip install aiohttp

then try this example, which uses asyncio.as_completed :然后试试这个例子,它使用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()

this works in python 3.5 (added the new async-await syntax):这适用于 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 your version yield from req.Request(google, None, headers) ?你的版本yield from req.Request(google, None, headers)吗? and (what library is that?) is this library even made for use with asyncio ?和(那是什么库?)这个库甚至是为与asyncio一起使用而asyncio吗?

(here is the same code with the python <= 3.4 syntax; the missing parts are the same as above): (这里是与python <= 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)

Create queue and run event loop创建队列并运行事件循环

def main():
    while terms:
        tasks.append(asyncio.create_task(terms.pop())

responses = asyncio.gather(*tasks, return_exception=True)
loop = asyncio.get_event_loop()
loop.run_until_complete(responses)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM