首页 新闻 会员 周边 捐助

将编写的Sanic程序导入另一个程序后发生的“上下文已设置”错误

0
悬赏园豆:20 [待解决问题]
  • python version: 3.10
  • Sanic-Cors version: 2.2.0
  • sanic version: 24.6.0
  • OS: Win 11
    首先我尝试直接运行了api.py,没有发生任何错误,但是当我再尝试运行main.py的时候,发生了:
PS E:\project>python main.py
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

这是第一个python文件 (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()

这是第二个python文件 (main.py):

# main.py
import api

api.start_server()

感谢您提供的帮助。

我原本怀疑时主模块检查因为某些原因自己运行了,于是删除了那段代码,但并没有任何效果。

EOF_break的主页 EOF_break | 初学一级 | 园豆:184
提问于:2024-08-15 22:22
< >
分享
所有回答(3)
0

来自AI:
这个错误发生的原因是因为在主程序(main.py)中导入了另一个程序(api.py),而在api.py中调用了多进程模块(multiprocessing)的相关方法。由于多进程模块只能在主程序中使用一次,所以在主程序中再次调用会出现上下文已设置的错误。
为了解决这个问题,你可以尝试在主程序导入api.py之前将多进程相关的代码放在一个函数中,并使用if name == 'main'来限制只有在作为主程序运行时才会执行这部分代码。这样可以避免多进程的上下文冲突。
下面是修改后的代码示例:
python

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)

main.py

if name == 'main':
import api
api.start_server()
通过将api.py中的代码放在if name == 'main'的条件判断下,可以确保在api.py被导入时不会执行启动服务器的代码,避免了多进程上下文冲突的问题。希望这可以帮助到你!

Technologyforgood | 园豆:7775 (大侠五级) | 2024-08-16 07:58

感谢您的回答,我参照您的方法修改了代码,但是出现了新的报错:

Main  2024-08-16 11:21:52 +0800 INFO: Sanic v24.6.0
Main  2024-08-16 11:21:52 +0800 INFO: Goin' Fast @ http://127.0.0.1:5050
Main  2024-08-16 11:21:52 +0800 INFO: app: ip
Main  2024-08-16 11:21:52 +0800 INFO: mode: production, single worker
Main  2024-08-16 11:21:52 +0800 INFO: server: sanic, HTTP/1.1
Main  2024-08-16 11:21:52 +0800 INFO: python: 3.12.4
Main  2024-08-16 11:21:52 +0800 INFO: platform: Windows-11-10.0.22631-SP0
Main  2024-08-16 11:21:52 +0800 INFO: packages: sanic-routing==23.12.0
Sanic app name 'ip' not found.
App instantiation must occur outside if __name__ == '__main__' block or by using an AppLoader.
See https://sanic.dev/en/guide/deployment/app-loader.html for more details.
Traceback (most recent call last):
  File "xxx\Python\Python312\Lib\site-packages\sanic\app.py", line 2233, in get_app
    return cls._app_registry[name]
           ~~~~~~~~~~~~~~~~~^^^^^^
KeyError: 'ip'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "xxx\Python\Python312\Lib\site-packages\sanic\worker\serve.py", line 56, in worker_serve
    app = app_loader.load()
          ^^^^^^^^^^^^^^^^^
  File "xxx\Python\Python312\Lib\site-packages\sanic\worker\loader.py", line 75, in load
    return self.factory()
           ^^^^^^^^^^^^^^
  File "xxx\Python\Python312\Lib\site-packages\sanic\app.py", line 2239, in get_app
    raise SanicException(
sanic.exceptions.SanicException: Sanic app name 'ip' not found.
App instantiation must occur outside if __name__ == '__main__' block or by using an AppLoader.
See https://sanic.dev/en/guide/deployment/app-loader.html for more details.
Main  2024-08-16 11:21:52 +0800 ERROR: Not all workers acknowledged a successful startup. Shutting down.

One of your worker processes terminated before startup was completed. Please solve any errors experienced during startup. If you do not see an exception traceback in your error logs, try running Sanic in a single process using --single-process or single_process=True. Once you are confident that the server is able to start without errors you can switch back to multiprocess mode.
Main  2024-08-16 11:21:52 +0800 INFO: Killing Sanic-Server-0-0 [25260]
Main  2024-08-16 11:21:52 +0800 INFO: Server Stopped
Main  2024-08-16 11:22:03 +0800 WARNING: Worker shutdown timed out. Some processes may still be running.

Process finished with exit code 1
支持(0) 反对(0) EOF_break | 园豆:184 (初学一级) | 2024-08-16 11:25
0

深度好文!

飞离地平线 | 园豆:18 (初学一级) | 2024-08-19 17:48
0

感谢各位,本贴已于 Stackoverflow 上解决,这是解决方法,希望能帮助到更多朋友。
This has something to do with the fact that Sanic has to start in main, but the routes can be defined anywhere else.
Sanic 必须在__main__中启动,因为Sanic需要在其中做一些事情,但是相关路由可以定义在任何地方。
This works:
这样做就可以正常运行了:

# 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})

if __name__ == '__main__':
    app.run(host="127.0.0.1", port=5050)

Or try this:
或者试试这样做:

# main.py
from api import start_server

if __name__ == "__main__":
    start_server()
EOF_break | 园豆:184 (初学一级) | 2024-10-22 11:00
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册