Search code examples
pythonpython-3.xflaskwerkzeugrelative-import

Flask Bug on Python 3.4? Development server can't run if app contains relative imports


By design, Python 3 cannot run a module that contains relative imports as a script. Attempting to do so yields the following error:

$ python mypackage/run.py
[...traceback...]
SystemError: Parent module '' not loaded, cannot perform relative import

The solution is to invoke the module with python -m mypackage.run instead of the more familiar python mypackage/run.py.

In Flask, the latter is how one normally runs the development server. However, the Flask development server immediately spawns a child process that reloads the code (and subsequently reloads code when files are changed on disk).

The result is this:

$ python -m mypackage.run
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader
[...traceback...]
SystemError: Parent module '' not loaded, cannot perform relative import

So now the server starts properly, but the child process reloads the code improperly.


Solution

  • This is probably due to the way the reloader works. It tends to mess with the Python path if you're doing something in unexpected ways, such as calling an inner module directly to run the app.

    Move run.py out of your project completely. It is only useful in development anyway, as a production deployment will use the application directly rather than the dev server.

    /my_project/
        /run.py
        /my_package/
            /__init__.py
            /my_module.py
    

    Execute run.py from the my_project directory (or otherwise put my_project on the Python path). It will be very simple, something like:

    from my_project_pkg import app
    app.run(debug=True)
    

    See this issue for more information about why the reloader has trouble with some patterns.