导入Sanic程序至其他程序时触发‘context has already been set’错误求助
解决Sanic启动时的RuntimeError: context has already been set问题
环境信息
- Python版本:3.10
- Sanic-Cors版本:2.2.0
- Sanic版本:24.6.0
- 操作系统:Windows 11
问题现象
直接运行api.py无任何错误,但运行main.py调用启动函数时触发RuntimeError,错误日志如下:
Main 2024-08-15 21:58:44 +0800 INFO: Sanic v24.6.0 Main 2024-08-15 21:58:44 +0800 INFO: Goin' Fast @ http://127.0.0.1:5050 Main 2024-08-15 21:58:44 +0800 INFO: app: ip Main 2024-08-15 21:58:44 +0800 INFO: mode: production, single worker Main 2024-08-15 21:58:44 +0800 INFO: server: sanic, HTTP/1.1 Main 2024-08-15 21:58:44 +0800 INFO: python: 3.12.4 Main 2024-08-15 21:58:44 +0800 INFO: platform: Windows-11-10.0.22631-SP0 Main 2024-08-15 21:58:44 +0800 INFO: packages: sanic-routing==23.12.0 Traceback (most recent call last): File "<string>", line 1, in <module> File "xxx\Python\Python312\Lib\multiprocessing\spawn.py", line 122, in spawn_main exitcode = _main(fd, parent_sentinel) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "xxx\Python\Python312\Lib\multiprocessing\spawn.py", line 131, in _main prepare(preparation_data) File "xxx\Python\Python312\Lib\multiprocessing\spawn.py", line 246, in prepare _fixup_main_from_path(data['init_main_from_path']) File "xxx \Python\Python312\Lib\multiprocessing\spawn.py", line 297, in _fixup_main_from_path main_content = runpy.run_path(main_path, ^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen runpy>", line 286, in run_path File "<frozen runpy>", line 98, in _run_module_code File "<frozen runpy>", line 88, in _run_code File "xxx\test\main.py", line 3, in <module> api.start_server() File "xxx\test\api.py", line 16, in start_server app.run(host="127.0.0.1", port=5050) File "xxx\Python\Python312\Lib\site-packages\sanic\mixins\startup.py", line 291, in run serve(primary=self) # type: ignore ^^^^^^^^^^^^^^^^^^^ File "xxx\Python\Python312\Lib\site-packages\sanic\mixins\startup.py", line 1003, in serve cls._set_startup_method() File "xxx\Python\Python312\Lib\site-packages\sanic\mixins\startup.py", line 932, in _set_startup_method set_start_method(method, force=cls.test_mode) File "xxx\Python\Python312\Lib\multiprocessing\context.py", line 247, in set_start_method raise RuntimeError('context has already been set') RuntimeError: context has already been set
相关代码
api.py
# api.py from sanic import Sanic, json from sanic_cors import CORS app = Sanic("ip") CORS(app) @app.route("/get_proxy") async def ip_api(request): ip = "XXXXXX" return json({"ip": ip}) def start_server(): app.run(host="127.0.0.1", port=5050) if __name__ == '__main__': start_server()
main.py
# main.py import api api.start_server()
解决方案
原因分析
Windows系统下Sanic默认使用spawn方式启动子进程,当通过main.py导入api模块时,主模块(main.py)会被子进程重新导入执行,导致多进程上下文被重复设置,触发RuntimeError。
解决方法
方法1:修改main.py,将启动代码放入模块主入口块
修改后的main.py:
# main.py import api if __name__ == '__main__': api.start_server()
这种方式符合Python多进程编程规范,能避免子进程重复执行启动逻辑,从根源上解决上下文重复设置的问题。
方法2:指定Sanic以单进程模式启动
修改api.py中的start_server函数,显式指定workers=1:
def start_server(): app.run(host="127.0.0.1", port=5050, workers=1)
单进程模式下Sanic不会创建子进程,也就不会触发多进程上下文冲突,但这种方式会限制服务的并发能力,仅适合测试场景或低并发需求。
内容的提问来源于stack exchange,提问作者Autopy
相关产品推荐
相关产品推荐

