Python等待一个带有循环的函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python等待一个带有循环的函数相关的知识,希望对你有一定的参考价值。

我使用Sanic作为服务器并尝试同时处理多个请求。

我已经使用了await for encode函数(我使用for循环来模拟做某事)但是当我在两个独立的控制台中尝试time curl http://0.0.0.0:8000/时,它不会同时运行。

我搜索过谷歌,但只找到event_loop,但它是安排注册的conroutines。

我如何等待for循环以便不会阻止请求?

谢谢。

from sanic import Sanic
from sanic import response
from signal import signal, SIGINT
import asyncio
import uvloop

app = Sanic(__name__)


@app.route("/")
async def test(request):
    # await asyncio.sleep(5)
    await encode()
    return response.json({"answer": "42"})

async def encode():
    print('encode')
    for i in range(0, 300000000):
        pass

asyncio.set_event_loop(uvloop.new_event_loop())
server = app.create_server(host="0.0.0.0", port=8000)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(server)
signal(SIGINT, lambda s, f: loop.stop())
try:
    loop.run_forever()
except:
    loop.stop()
答案

运行for i in range()是阻止。如果你改变它以将你的await asyncio.sleep(5)放入encode方法,你会发现它按预期运行。

@app.route("/")
async def test(request):
    await encode()
    return response.json({"answer": "42"})

async def encode():
    print('encode')
    await asyncio.sleep(5)

当你调用await encode()并且encode是一种阻塞方法时,它仍然会阻止因为你没有“等待”任何其他东西。你的线程仍然被锁定。

您还可以添加另一个工作人员:

app.create_server(worker=2)

尝试浏览this answer

另一答案

由于异步处理程序实际上在事件循环中运行,因此它作为回调异步运行而不是并发运行。 loop.run_forever()将一遍又一遍地调用loop._run_once来运行所有已注册的事件,每个await将停止协程并将控制权返回到eventloop并且eventloop安排运行下一个事件。

所以基本上如果你不想在长时间运行的for循环中阻塞,你需要手动将控制权交给for循环中的eventloop,see the issue about relinquishing control

async def encode():
    print('encode')
    for i in range(0, 300000000):
        await asyncio.sleep(0)

这是来自Guido的quote

asyncio.sleep(0)就是说 - 让任何其他任务运行然后再回到这里。

以上是关于Python等待一个带有循环的函数的主要内容,如果未能解决你的问题,请参考以下文章

使用从循环内的代码片段中提取的函数避免代码冗余/计算开销

Python之如何优雅的重试

带有菜单功能的 Python 主函数循环不起作用?

python yield函数

python yield函数

如何在python里面for循环中放了一个定时函数,当定时函数运行时跳过本次循环,执行那个循环