Python 3.12.3中Quart+Hypercorn报错RuntimeError:无运行事件循环
解决Quart+Hypercorn运行时RuntimeError: no running event loop问题
问题场景
使用以下命令启动Quart+Hypercorn服务器:
pipenv run hypercorn --config=hypercorn.toml --reload src.main:app
hypercorn.toml配置内容:
accesslog = "/var/log/pythonrestapi" errorlog = "/var/log/pythonrestapi" alt_svc_headers = ["h3=\":443\"; ma=3600, h3-29=\":443\"; ma=3600"] quic_bind = "0.0.0.0:4433" bind = "0.0.0.0:4433" insecure_bind = "0.0.0.0:8080" certfile = "server.crt" keyfile = "server.key" #server_names = ["pythonrestapi"] worker_class = "trio"
启动后触发报错:
2024-05-29 13:31:33 INFO Running on https://0.0.0.0:4433 (CTRL + C to quit) 2024-05-29 13:31:33 INFO Running on http://0.0.0.0:8080 (CTRL + C to quit) 2024-05-29 13:31:34 INFO Running on https://0.0.0.0:4433 (QUIC) (CTRL + C to quit) 2024-05-29 13:33:09 ERROR Error in ASGI Framework Traceback (most recent call last): File "/home/khteh/.local/share/virtualenvs/PythonRestAPI-6TwrpjXm/lib/python3.12/site-packages/hypercorn/trio/task_group.py", line 26, in _handle await app(scope, receive, send, sync_spawn, call_soon) File "/home/khteh/.local/share/virtualenvs/PythonRestAPI-6TwrpjXm/lib/python3.12/site-packages/hypercorn/app_wrappers.py", line 34, in __call__ await self.app(scope, receive, send) File "/home/khteh/.local/share/virtualenvs/PythonRestAPI-6TwrpjXm/lib/python3.12/site-packages/quart/app.py", line 1667, in __call__ await self.asgi_app(scope, receive, send) File "/home/khteh/.local/share/virtualenvs/PythonRestAPI-6TwrpjXm/lib/python3.12/site-packages/quart/app.py", line 1693, in asgi_app await asgi_handler(receive, send) File "/home/khteh/.local/share/virtualenvs/PythonRestAPI-6TwrpjXm/lib/python3.12/site-packages/quart/asgi.py", line 48, in __call__ done, pending = await asyncio.wait( ^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/asyncio/tasks.py", line 463, in wait loop = events.get_running_loop() ^^^^^^^^^^^^^^^^^^^^^^^^^ RuntimeError: no running event loop
相关核心代码:
src/main.py:
from src.app import create_app app = create_app() app = cors(app, allow_credentials=True, allow_origin="https://localhost:4433") Healthz(app, no_log=True) csrf = CSRFProtect(app) bcrypt.init_app(app)
src/app.py:
def create_app() -> Quart: """ Create App """ # App initialization app = Quart(__name__, template_folder='view/templates', static_url_path='', static_folder='view/static') app.config.from_file("/etc/pythonrestapi_config.json", json.load) if "SQLALCHEMY_DATABASE_URI" not in app.config: app.config["SQLALCHEMY_DATABASE_URI"] = f"postgresql://{os.getenv('POSTGRESQL_USER')}:{os.getenv('POSTGRESQL_PASSWORD')}@svc-postgresql/library" app.register_blueprint(home_blueprint, url_prefix="/") app.register_blueprint(fibonacci_blueprint, url_prefix="/fibonacci") app.register_blueprint(auth_blueprint, url_prefix="/auth") app.register_blueprint(user_blueprint, url_prefix="/users") app.register_blueprint(author_blueprint, url_prefix="/authors") app.register_blueprint(book_blueprint, url_prefix="/books") db.init_app(app) return app
问题原因
配置中指定worker_class = "trio",Hypercorn会使用trio异步框架运行服务,但Quart默认基于asyncio,在trio环境中调用asyncio.wait时,找不到asyncio的事件循环,因此触发RuntimeError。
解决方案
方案1:切换到asyncio worker
修改hypercorn.toml中的worker_class配置,改用默认的asyncio worker:
# 注释或删除原trio配置,或者显式指定asyncio # worker_class = "trio" worker_class = "asyncio"
方案2:启用Quart的trio兼容模式
如果必须使用trio,需要让Quart适配trio环境:
- 安装quart-trio依赖:
pipenv install quart-trio
- 修改src/app.py中Quart的初始化代码,指定
async_mode="trio":
def create_app() -> Quart: """ Create App """ # App initialization - 添加async_mode参数 app = Quart( __name__, template_folder='view/templates', static_url_path='', static_folder='view/static', async_mode="trio" # 新增该行 ) app.config.from_file("/etc/pythonrestapi_config.json", json.load) if "SQLALCHEMY_DATABASE_URI" not in app.config: app.config["SQLALCHEMY_DATABASE_URI"] = f"postgresql://{os.getenv('POSTGRESQL_USER')}:{os.getenv('POSTGRESQL_PASSWORD')}@svc-postgresql/library" app.register_blueprint(home_blueprint, url_prefix="/") app.register_blueprint(fibonacci_blueprint, url_prefix="/fibonacci") app.register_blueprint(auth_blueprint, url_prefix="/auth") app.register_blueprint(user_blueprint, url_prefix="/users") app.register_blueprint(author_blueprint, url_prefix="/authors") app.register_blueprint(book_blueprint, url_prefix="/books") db.init_app(app) return app
内容的提问来源于stack exchange,提问作者khteh
相关产品推荐
相关产品推荐

