pythonsanic

The "context has already been set" error that occurs after importing a written Sanic program into another program


Here, I must clarify that English is not my native language. If there are any grammar errors, please forgive me.

I only extracted the simplest implementation, yet it still results in a Runtime Error, the following are detailed information.

I have tried to run api.py directly, and no errors occurred. When I was running main.py directly, an error occurred:

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

There is the first code file (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()

The second python file (main.py):

# main.py
import api

api.start_server()

I have guessed the Main Module Check ran for some reason, so I delete that code, but it didn't change anything.


Solution

  • This has something to do with the fact that Sanic has to start in __main__, but the routes can be defined anywhere else.

    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()