Consider the two modules (in the same folder):
firstly, person.py
from typing import List
from .pet import Pet
class Person:
def __init__(self, name: str):
self.name = name
self.pets: List[Pet] = []
def adopt_a_pet(self, pet_name: str):
self.pets.append(Pet(pet_name, self))
and then pet.py
from .person import Person
class Pet:
def __init__(self, name: str, owner: Person):
self.name = name
self.owner = owner
the code above will not work, because of circular dependency. You'll get an error:
ImportError: cannot import name 'Person'
Some ways to make it work:
e.g. just have:
class Pet:
def __init__(self, name: str, owner):
I see some drawback in all the options I've listed so far.
Is there another way? One that allows me to
Or: is there very good reason to instead follow one of the solutions I've already listed?
The easiest way to fix this is to move the path import to the end of the node module. Save this answer.
To reduce or eliminate circular dependencies, architects must implement loose component coupling and isolate failures. One approach is to use abstraction to break the dependency chain. To do this, you introduce an abstracted service interface that delivers underlying functionality without direct component coupling.
If the error occurs due to a circular dependency, it can be resolved by moving the imported classes to a third file and importing them from this file. If the error occurs due to a misspelled name, the name of the class in the Python file should be verified and corrected.
I ran into similar problems recently and solved it by using the following method:
import typing
if typing.TYPE_CHECKING:
from .person import Person
class Pet:
def __init__(self, name: str, owner: 'Person'):
self.name = name
self.owner = owner
There is a second solution described here, which requires Python >= 3.7 && < 3.10.
from __future__ import annotations # <-- Additional import.
import typing
if typing.TYPE_CHECKING:
from .person import Person
class Pet:
def __init__(self, name: str, owner: Person): # <-- No more quotes.
self.name = name
self.owner = owner
As of Python 3.10, the __future__
import will no longer be required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With