如何在辅助线程中运行aiohttp Web应用程序
以下代码摘自aiohttp
文档 https://docs.aiohttp.org/zh/稳定/
确实有效:
The following code taken from the aiohttp
docs https://docs.aiohttp.org/en/stable/
does work:
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)])
if __name__ == '__main__':
web.run_app(app)
但是让网络服务器劫持主线程是不可接受的:网络服务器应位于单独的非主线程上,并 subservient 到主后端应用程序.
But having the webserver hijack the main thread is not acceptable: the webserver should be on a separate non-main thread and subservient to the main backend application.
我无法确定如何在辅助线程上运行webapp.这是我尝试过的:
I can not determine how to run the webapp on a secondary thread. Here is what I have tried:
- 无法在
ipython
repl中运行代码段:
- It is not possible to run the snippet of code in
ipython
repl:
我试图以这种方式运行它:
I tried to run it this way:
#if __name__ == '__main__':
web.run_app(app)
并收到有关no current event loop
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3293, in run_code
async def run_code(self, code_obj, result=None, *, async_=False):
File "<ipython-input-8-344f41746659>", line 13, in <module>
web.run_app(app)
File "/usr/local/lib/python3.8/site-packages/aiohttp/web.py", line 393, in run_app
def run_app(app: Union[Application, Awaitable[Application]], *,
File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/events.py", line 628, in get_event_loop
def get_event_loop(self):
RuntimeError: There is no current event loop in thread 'Thread-11'.
那么,.. 什么只能在main
中运行?我在这里想念东西.
So then .. what it can only be run in main
? I'm missing something here..
我尝试在另一个独立脚本中但在从属线程上运行:
I tried running in another standalone script but on a subservient thread:
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)
但这基本上给出了相同的错误:
But that gives basically the same error:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/git/bluej/experiments/python/aio_thread.py", line 12, in runWebapp
web.run_app(app)
File "/usr/local/lib/python3.8/site-packages/aiohttp/web.py", line 409, in run_app
loop = asyncio.get_event_loop()
File "/usr/local/Cellar/python@3.8/3.8.1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
那么我该如何从main
线程中删除该Web应用程序并使它与我的应用程序中的其他线程一起播放
So how do I get this webapp off the main
thread and make it play along with the other threads in my application
在这里:
import http.server
import threading
import socketserver
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
def serve_forever():
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
if __name__ == "__main__":
threading.Thread(target=serve_forever).start()
while 1:
x = input("enter a number")
print("You entered {}".format(x))
这是一个很好的聚会技巧,但对生产工作不一定有用:http.server模块的文档在文档页面顶部的红色火焰中表示不要在生产中使用它.但是,几乎所有的python网络服务器框架都可以作为WSGI服务器使用,并且无法按照您希望的方式运行:它们通常期望由gunicorn或apache之类的东西来运行.
N.B. this is a neat party trick, but not necessarily useful for production work: the documentation for the http.server module says in flaming red letters at the top of the doc page not to use it in production. But almost all python webserver frameworks operate as WSGI servers and aren't designed to work the way you seem to want them to: they generally expect to be run by something else like gunicorn or apache.
我强烈建议您是否需要HTTP服务器,例如监视正在运行的应用程序,您改而使用asyncio并对所有内容使用coros,但如果您确实愿意,可以按上述方式滚动自己的线程方案.您可以看到您仍然可以在无限输入循环中与外壳程序交互,同时还可以卷曲localhost:8000以获取包含目录列表的HTML页面.
I strongly recommend if you need an HTTP server for e.g. monitoring a running app that you use asyncio instead and use coros for everything, but you can roll your own threading scenario as above if you really want to. You can see that you can still interact with the shell in the infinite input loop while you can also curl localhost:8000 to get an HTML page containing a directory listing.
只需传入您自己创建的非默认处理程序即可执行其他操作,例如以JSON格式返回应用程序状态.
Just pass in a non-default handler of your own creation to do other stuff like return app state in JSON format.