python - 与另一个 asyncio 长时间运行的任务一起运行 Tornado
问题描述
我想asyncio
在 Python 3.7 中运行 Tornado 服务器以及独立的长时间运行的任务。我是新手asyncio
。我读过你应该只调用asyncio.run()
一次,所以我把这两个任务放在了main()
方法下,这样我就可以将一个参数传递给asyncio.run()
. 当我运行这段代码时,我得到了错误TypeError: a coroutine was expected, got <function start_tornado at 0x105c8e6a8>
。我想让代码在没有错误的情况下运行,但最终我想知道如何以正确的方式做到这一点。我在下面写的代码感觉就像一个丑陋的黑客。
import asyncio
import datetime
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
# Fake background task I got from here:
# https://docs.python.org/3/library/asyncio-task.html#sleeping
async def display_date():
while True:
print(datetime.datetime.now())
await asyncio.sleep(1)
async def start_tornado():
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
async def main():
await asyncio.create_task(start_tornado)
await asyncio.create_task(display_date)
asyncio.run(main())
解决方案
create_task
与函数一起使用时async def
,正常调用该函数,然后将结果传递给create_task
.await asyncio.create_task(start_tornado()) await asyncio.create_task(display_date())
create_task
如果您要await
立即使用,则无需使用。使用create_task
withoutawait
在后台启动任务,例如display_date()
.start_tornado
从这个意义上说,它不是后台任务,因为它没有无限循环,它只是启动了一个由 Tornado 放入后台的服务器。所以我会这样写:await start_tornado() asyncio.create_task(display_date())
从 Tornado 5.0 开始,Tornado IOLoop 和 asyncio 事件循环默认是集成的,所以你只需要启动一个,而不是两个都启动。所以只需删除
IOLoop.start()
.start_tornado
start_tornado
目前没有做任何异步的事情,所以它可能只是一个正常的功能。但它也是一个合理的地方,可以添加异步启动逻辑,例如建立数据库连接,因此您可以将其保留为协程。
代码的工作版本与我的编辑:https ://repl.it/@bdarnell/FarawayAdmiredConversions
推荐阅读
- vim - Vim matchadd 命令不适用于多个选项卡
- php - 如何在 url 中读取时间以及如何在 url 上写入?
- javascript - 如何在 Preact 中使用 useEffect?
- python-3.x - 我如何检测程序何时关闭?
- java - 无法在 JNI 共享库中使用 intel mkl
- linux - 如何可靠地为用户添加或附加到 PATH
- python - Live Graph Matplotlib - 使用相同的窗口循环更新图形
- qlikview - QlikView 使用表达式结果作为选择或列表框
- wordpress - 预计下一件事是转义功能:WordPress
- sql-server - 将大型 SQL Server 表从一个数据库移动到另一个数据库的最佳方法?