Circular imports for Python typing annotations
Posted on February 1, 2023 (Last modified on July 2, 2024) • 1 min read • 143 wordsProblem:
# ###############################################################
# models.py
from controllers import BookController
class Book:
def get_controller(self) -> BookController:
return BookController(self)
# ###############################################################
# controllers.py
from models import Book
class BookController:
def __init__(self, book: Book) -> None:
self.book = book
Do you see it? Try it out - it will generate a “circular import” Exception.
The solution is very nicely described in Adam Johnson’s blog post (credit where credit’s due).
Copy-pasted for myself (still, please visit Adam’s page!!, he explains it much better and with more detail), this is it:
# ###############################################################
# models.py
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from controllers import BookController
class Book:
def get_controller(self) -> BookController:
return BookController(self)
# ###############################################################
# controllers.py
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from models import Book
class BookController:
def __init__(self, book: Book) -> None:
self.book = book
This fucking rocks. :))