mask
mask

Reputation: 549

PyInstaller and FastAPI (maximum recursion depth exceeded)

I have a python service that uses fastapi as a web interface. I need to make an executable file and hence I am using PyInstaller.

I keep getting the following error:

File "..../miniconda3/lib/python3.7/site-packages/PyInstaller/lib/modulegraph/modulegraph.py", line 2912, in _load_package
    self._load_module(fqname, fp, buf, stuff)
File "..../miniconda3/lib/python3.7/site-packages/PyInstaller/lib/modulegraph/modulegraph.py", line 2093, in _load_module
    m = self._load_package(fqname, pathname, packagepath)

RecursionError: maximum recursion depth exceeded while calling a Python object

I added import sys; sys.setrecursionlimit(50000) to the original python file as well as in the spec but still getting the same problem.

The interesting thing is that I don't get that error if I don't use fastapi (It works with Flask for example). Looks like PyInstaller has some issue with fastapi.

Does anybody have any idea how to solve this issue?

This is the code in my main python function:

from fastapi import FastAPI
import uvicorn
app = FastAPI()

if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", workers=1, port=5000)

Upvotes: 5

Views: 8010

Answers (2)

Glen Thompson
Glen Thompson

Reputation: 10016

Using @UFO answer I then also updated the PyInstaller to include the hidden modules

  1. Uninstall pydantic and install from source. Hopefully this will update in the registry soon.
pip uninstall pydantic

pip install git+git://github.com/samuelcolvin/pydantic@master#egg=pydantic
# or with extras
pip install git+git://github.com/samuelcolvin/pydantic@master#egg=pydantic[email,typing_extensions]
  1. Run pyinstaller main.py

  2. Add these hidden imports to .spec file generated by pyinstaller

hiddenimports=[
                'uvicorn.logging',
                'uvicorn.loops',
                'uvicorn.loops.auto',
                'uvicorn.protocols',
                'uvicorn.protocols.http',
                'uvicorn.protocols.http.auto',
                'uvicorn.protocols.websockets',
                'uvicorn.protocols.websockets.auto',
                'uvicorn.lifespan',
                'uvicorn.lifespan.on',
            ]
  1. Run pyinstaller main.spec

Ref:

main.py

import uvicorn
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def root():
    return {"hello": "world"}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Upvotes: 5

UFO
UFO

Reputation: 71

I also encountered the same problem today, and I found that the problem was in the Pydantic module.

I reinstalled it directly from the repository:

pip uninstall pydantic

pip install git+git://github.com/samuelcolvin/pydantic@master#egg=pydantic
# or with extras
pip install git+git://github.com/samuelcolvin/pydantic@master#egg=pydantic[email,typing_extensions]

This will solve the maximum recursion depth problem, but will encounter another problem in Uvicorn:

Traceback (most recent call last):
  File "logging/config.py", line 388, in resolve
AttributeError: module 'uvicorn' has no attribute 'logging'

And I replaced Uvicorn with Hypercorn + Uvloop and it works very well now.

Here is my final code:

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


if __name__ == "__main__":
    import asyncio
    import uvloop
    from hypercorn.asyncio import serve
    from hypercorn.config import Config

    config = Config()
    config.bind = ["0.0.0.0:8000"]

    asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    loop.run_until_complete(serve(app, config))

Upvotes: 7

Related Questions