I’m building a Typer app with lots of commands. I want to categorize the commands into subfiles but am unsure how to resolve the dependencies.
| ├── melvil │ ├── add.json │ ├── book │ │ ├── book.py │ │ └── __init__.py │ ├── booklist │ │ ├── booklist.py │ │ └── __init__.py │ ├── helper │ │ ├── helper.py │ │ └──__init__.py │ ├── search │ │ ├── __init__.py │ │ └── search.py │ │ │ │ │ ├── __init__.py │ ├── main.py │ ├── setup.py │ └── test_input.txt
main.py
is the parent. It looks like this:
import typer from datetime import date app = typer.Typer() # Import submodules from booklist.booklist import * from book.book import * from search.search import * from helper.helper import * # App is only invoked when we run main.py directly, but not when we import it. if __name__ == "__main__": app()
So, we make a new Typer app
and import everything from the submodules. Simple enough.
Each of the submodules contains Typer commands, like booklist
:
# This file focuses on commands that affect the entire booklist. import inquirer import os import json import csv @app.command() def delete(): """ ...Irrelevant code here... """
Here’s the problem: in order to define a Typer command with the @app.command()
decorator, each submodule first needs to import app
from the parent main.py
. However, main.py
gets run in the import statement for any of the submodules, and so a circular import arises when main.py
imports whatever submodule it’s in.
How should one structure this project so that all submodules have access to app
and main.py
can also access all the submodules?
Advertisement
Answer
You could just have app
be initialized in its own separate module. Let the sub-modules import it from there and have your main
module import those sub-modules.
Something like this:
app.py
import typer app = typer.Typer()
booklist.py
from YOURTOPLEVELPACKAGE.app import app @app.command() def your_function(): ...
main.py
# All of those include `app` from booklist.booklist import * from book.book import * from search.search import * from helper.helper import * if __name__ == "__main__": app()