微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python 问题:无法在单独的线程或事件循环中运行连接 aiohttp 服务器

如何解决Python 问题:无法在单独的线程或事件循环中运行连接 aiohttp 服务器

我一直无法在后台使用 aiohttp 获取连接服务器,因此在启动网络服务器时主线程不会挂起。

我想我可能可以通过使用 asyncio 并为其他所有内容创建一个任务,但是我正在编写一个可供其他人和公司重用的库,而我没有能力执行那种设计模式单方面通用。

我已经开始工作了(来自 https://newbedev.com/how-to-run-an-aiohttp-server-in-a-thread):

import asyncio
import threading
from aiohttp import web


def aiohttp_server():
    def say_hello(request):
        return web.Response(text='Hello,world')

    app = web.Application(debug=True)
    app.add_routes([web.get('/',say_hello)])
    handler = app.make_handler()
    return handler


def run_server(handler):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    server = loop.create_server(handler,host='127.0.0.1',port=8089)
    loop.run_until_complete(server)
    loop.run_forever()


t = threading.Thread(target=run_server,args=(aiohttp_server(),))
t.start()

for i in range(50000):
   print('Hi from Main Thread')
   time.sleep(5)

这会使服务器保持运行状态,然后允许主线程继续运行。

但是,当我尝试使用此代码并使用以下代码启动连接服务器时,我无法启动并运行,我在第 2 天,我必须开始行动.我希望有人看到我做过或误解的愚蠢的事情,并能告诉我如何解决它。

def initializeServertest():

    app = connexion.AioHttpApp(__name__,port=8080,specification_dir='openAPISpecs/',# https://github.com/OpenAPITools/openapi-generator/issues/1322
        only_one_api=True
        )
   
    app.add_api('openAPISpec.json',arguments={'title': 'Instrument and HUB API'},pythonic_params=True,validate_responses=True
        )

    # Configure default CORS settings.
    cors = aiohttp_cors.setup(app.app,defaults={
            "*": aiohttp_cors.ResourceOptions(allow_credentials=True,expose_headers="*",allow_headers="*",allow_methods=["GET","POST","PUT"]
                                            )
    })

    # Configure CORS on every route
    for route in list(app.app.router.routes()):
        cors.add(route)
    
    # Now create a runner we will start later
    runner = web.AppRunner(app.create_app())

    return runner

def run_server(runner):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(runner.setup())
    site = web.Tcpsite(runner,'localhost',8080)
    loop.run_until_complete(site.start())
    loop.run_forever()

def StartServerInBackground():
    t = threading.Thread(target=run_server,args=(initializeServertest(),))
    t.start()

当我执行此操作时,我恢复了主线程,但 Web 服务器不响应任何请求。

任何帮助将不胜感激

解决方法

好的,这是我想出的解决方案:

import connexion
from aiohttp import web
from aiohttp_cors
import threading

app = {}
apprunner = {}

def _initializeServer():

    # use module level app
    global app

    app = connexion.AioHttpApp(__name__,port=8080,specification_dir='openAPISpecs/',# https://github.com/OpenAPITools/openapi-generator/issues/1322
        only_one_api=True
        )

    app.add_api('openAPISpec.json',arguments={'title': 'Analyzer and HUB API'},pythonic_params=True,validate_responses=True,# doesn't always work with JSON bodies: https://github.com/zalando/connexion/issues/837
        strict_validation=True
        )

    # Configure default CORS settings.
    cors = aiohttp_cors.setup(app.app,defaults={
            "*": aiohttp_cors.ResourceOptions(allow_credentials=True,expose_headers="*",allow_headers="*",allow_methods=["GET","POST","PUT","DELETE"]
                                        )
    })

    # Configure CORS on every route
    for route in list(app.app.router.routes()):
        cors.add(route)

def _startServer_NonBlocking(runner):
    #store runner at module level for use later
    global apprunner
    apprunner = runner

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(runner.setup())

    site = web.TCPSite(runner,'localhost',8080)
    loop.run_until_complete(site.start())
    loop.run_forever()

def startServer_NonBlocking():
    # grab module level serverRunning for comparison in next line
    global serverRunning

    # if the server isn't already running
    if(serverRunning == False):
        # configure new thread and start it
        newThread = threading.Thread(target=_startServer_NonBlocking,args=(_initializeServer_NonBlocking(),))
        newThread.start()

        # set flag that the server is running so we don't ever try to start it again
        serverRunning = True

秘诀在于发现您必须使用 app.app 来获取运行程序,然后您可以稍后使用它来按照连接文档中的食谱进行设置。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?