I faced the dreaded circular import issue when doing some simple research. I tried the “import ” solution but doesn’t seem to work. What is the solution to make it work?
Example code (all 3 files are located in the same directory, no other files present in there):
my_subject.py:
from abc import ABC, abstractmethod
from random import randrange
import my_observer
class Subject(ABC):
@abstractmethod
def attach(self, observer: my_observer.Observer) -> None:
pass
@abstractmethod
def detach(self, observer: my_observer.Observer) -> None:
pass
@abstractmethod
def notify(self) -> None:
pass
class ConcreteSubject(Subject):
_state: int = None
_observers: list[my_observer.Observer] = []
def attach(self, observer: my_observer.Observer) -> None:
print("Subject: Attached an observer.")
self._observers.append(observer)
def detach(self, observer: my_observer.Observer) -> None:
self._observers.remove(observer)
def notify(self) -> None:
print("Subject: Notifying observers...")
for observer in self._observers:
observer.update(self)
def some_business_logic(self) -> None:
print("nSubject: I'm doing something important.")
self._state = randrange(0, 10)
print(f"Subject: My state has just changed to: {self._state}")
self.notify()
my_observer.py:
from abc import ABC, abstractmethod
import my_subject
class Observer(ABC):
@abstractmethod
def update(self, subject: my_subject.Subject) -> None:
pass
class ConcreteObserverA(Observer):
def update(self, subject: my_subject.Subject) -> None:
if subject._state < 3:
print("ConcreteObserverA: Reacted to the event")
class ConcreteObserverB(Observer):
def update(self, subject: my_subject.Subject) -> None:
if subject._state == 0 or subject._state >= 2:
print("ConcreteObserverB: Reacted to the event")
observer_main.py:
import my_subject
import my_observer
if __name__ == "__main__":
# The client code.
subject = my_subject.ConcreteSubject()
observer_a = my_observer.ConcreteObserverA()
subject.attach(observer_a)
observer_b = my_observer.ConcreteObserverB()
subject.attach(observer_b)
subject.some_business_logic()
subject.some_business_logic()
subject.detach(observer_a)
subject.some_business_logic()
terminal output when running observer_main.py:
Traceback (most recent call last):
File "/home/samprass/dev/python/practising/design_patterns/observer/observer_main.py", line 1, in <module>
import my_subject
File "/home/samprass/dev/python/practising/design_patterns/observer/my_subject.py", line 3, in <module>
import my_observer
File "/home/samprass/dev/python/practising/design_patterns/observer/my_observer.py", line 18, in <module>
class Observer(ABC):
File "/home/samprass/dev/python/practising/design_patterns/observer/my_observer.py", line 20, in Observer
def update(self, subject: my_subject.Subject) -> None:
AttributeError: partially initialized module 'my_subject' has no attribute 'Subject' (most likely due to a circular import)
I tried to use simple “import ” instead of “from import “
New contributor
MRSMPRSS is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
3