python - 在辅助线程上运行任何 Web 服务器事件循环
问题描述
我们有一个丰富的后端应用程序来处理消息/队列、数据库查询和计算机视觉。我们需要的另一个特性是 tcp 通信——最好是通过 http。关键是:这主要不是一个Web 应用程序。我们希望为不同的目的设置一组 http 通道。是的——我们了解包括主题和发布-订阅在内的消息传递:但是基于直接 tcp 的请求/响应也有它的位置。
我已经查看并尝试了半打 python http web 服务器。它们或隐式或显式地描述了event loop
在主线程上运行的要求。这对我们来说是本末倒置:main
线程已经被其他任务占用,包括其他活动的协调。
为了说明预期的结构,我将从我的aiohttp
特定问题如何在辅助线程中运行 aiohttp Web 应用程序中提取代码。在那个问题中,我尝试在另一个独立脚本中运行,但在从属线程上运行:
def runWebapp():
from aiohttp import web
async def handle(request):
name = request.match_info.get('name', "Anonymous")
text = "Hello, " + name
return web.Response(text=text)
app = web.Application()
app.add_routes([web.get('/', handle),
web.get('/{name}', handle)])
web.run_app(app)
if __name__ == '__main__':
from threading import Thread
t = Thread(target=runWebapp)
t.start()
print('thread started let''s nap..')
import time
time.sleep(50)
这给出了错误:
RuntimeError: There is no current event loop in thread 'Thread-1'.
这个错误原来的意思是“嘿,你没有在main
线程上运行它”。
我们可以aiohttp
在这里逻辑地替换为其他 Web 服务器。这种要求 Web 服务器的事件处理循环在辅助线程上运行的方法是否适用?到目前为止,我也尝试过cherrypy
,tornado
和flask
.
请注意,我没有尝试过的一个著名的网络服务器是django
. 但这似乎需要围绕django
. 我们不希望这样做,因为该应用程序有一组其他目的,这些目的取代了拥有 http 服务器的这种杂耍。
我看过的一种方法是asyncio
. 我不明白它是否可以支持在侧线程上运行事件循环:如果是这样,那么它将是这个问题的答案。
无论如何,是否有任何 Web 服务器明确支持将其事件循环从主线程中移除?
解决方案
您可以在辅助线程上创建和设置事件循环:
asyncio.set_event_loop(asyncio.new_event_loop())
cherrypy
没有这个就flask
已经工作了;tornado
与此一起使用。
On aiohttp
,您会从它调用另一个错误loop.add_signal_handler()
:
ValueError:set_wakeup_fd 仅在主线程中有效
您需要跳过它,因为只允许主解释器的主线程设置新的信号处理程序,这意味着运行在辅助线程上的 Web 服务器无法直接处理信号以进行优雅退出。
示例:aiohttp
在调用之前设置事件循环
run_app()
。
aiohttp
3.8+ 已经使用了一个新的事件循环run_app()
,所以你可以跳过这个。handle_signals=False
调用时传递run_app()
不添加信号处理程序。
asyncio.set_event_loop(asyncio.new_event_loop()) # aiohttp<3.8
web.run_app(app, handle_signals=False)
示例:龙卷风
在调用之前设置事件循环app.listen()
。
asyncio.set_event_loop(asyncio.new_event_loop())
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
推荐阅读
- javascript - React:列表项的奇怪协调结果,其内容由与列表长度相同的数组提供
- laravel - 询问有关数据透视表的建议
- python - 如何将 excel 文件连接到我的 django 网站项目?
- json - 为什么用内存读取替换文件读取不会提高我的 Spring/Junit 测试性能?
- intellij-idea - IntelliJ Idea:未检测到测试资源
- typescript - 来自 GET 与 POST 的打字稿类
- excel - 我可以使用 SharePoint 中内置的数据库在 Excel 电子表格中进行数据验证吗?
- javascript - 为 html 字段分配新值时,如何保留内部符号?
- angular - Angular 应用程序:将字符串分配给数字时没有打字稿错误
- spring - 尝试使用 elasticsearch-grails-plugin 时出错:获取 java.lang.IllegalStateException