Reputation: 608
I'm facing an annoying problem with a circular import error and I don't understand what I am doing wrong. Here the code:
main.py
import uvicorn
import app.config.config as config
app = config.load_config()
CONFIG = config.read_config()
if __name__ == "__main__":
uvicorn.run(app, host=CONFIG["APPLICATION"]["HOST"], port=CONFIG["APPLICATION"]["PORT"])
config.py
import os
import toml
import logging
import app.api.routing as routing
from fastapi import FastAPI
BASE_DIR = os.getcwd()
def read_config():
try:
CONFIG = toml.load(BASE_DIR + "/config.toml")
return CONFIG
except FileNotFoundError as err:
logging.error(f"Unable to read configuration file: {err}")
return None
def load_config():
app = FastAPI()
app.include_router(routing.router)
return app
database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker
import app.config.config as config
CONFIG = config.read_config()
USERNAME = CONFIG["POSTGRES"]["USERNAME"]
PASSWORD = CONFIG["POSTGRES"]["PASSWORD"]
HOSTNAME = CONFIG["POSTGRES"]["HOSTNAME"]
DATABASE = CONFIG["POSTGRES"]["DATABASE"]
PORT = CONFIG["POSTGRES"]["PORT"]
SQLALCHEMY_DATABASE_URI = f"postgresql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
engine = create_engine(SQLALCHEMY_DATABASE_URI)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
ERROR:
CONFIG = config.read_config()
AttributeError: partially initialized module 'app.config.config' has no attribute 'read_config' (most likely due to a circular import)
I'm using FastAPI framework with Python 3.9.
In the code, I have imported "app.config.config" 2 times (main.py and database.py) and I need to import this config file to use the function read_config()
contained in it.
Anyone can help please? Thanks
THE PROJECT STRUCTURE:
.
├── app
│ ├── api
│ │ ├── __init__.py
│ │ └── routing.py
│ ├── config
│ │ ├── config.py
│ │ ├── __init__.py
│ │ └── settings.py
│ ├── database
│ │ ├── database.py
│ │ └── __init__.py
│ ├── __init__.py
│ ├── main.py
│ ├── models
│ │ ├── __init__.py
│ │ └── placesModel.py
│ └── service
│ ├── crud.py
│ ├── __init__.py
Upvotes: 2
Views: 961
Reputation: 896
I suspect that app.api.routing
try to import database
.
First try to refactor your code and split routing
so it doesn't require database
Otherwise, make call to read_config
in database
just-in-time. There are various solutions to differ call to read_config
.
def _get_session_local():
NFIG = config.read_config()
...
return sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
if get_db._get_session_local is None:
get_db._session_local = _get_session_local()
try:
yield get_db._session_local()
finally:
db.close()
get_db._session_local = None
More generally, the execution of code during import is to be avoided.
Upvotes: 2