Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does importing a Python class instantiate it?

A somewhat cut down example here from some PyTest unit tests that never exit. If I stick a break point on DataListener.__init__ I see it getting called from the from controller import Controller statement in test_controller.py which was a bit of a suprise to me; Why does importing a class from a module instantiate an instance of it?

data_listener.py

class DataListener:

    def __init__(self, port, host='localhost'):
        self._stop_monitor = Event()
        self._monitor = Thread(target=self.check_last_message)
        self._monitor.start()

    def __del__(self):
        self.stop()

    def stop(self):
        self._stop_monitor.set()
        self._monitor.join()

    def check_last_message(self):
        while not self._stop_monitor.is_set():
            # Code to check for a heartbeat here
            pass

controller.py

from data_listener import DataListener

class Controller:
    def __init__(
        self,
        subscriber=DataListener(port=DEFAULT_SUBSCRIBER_PORT),
        publisher=JsonPublisher(DEFAULT_PUBLISHER_PORT)):

        pass

test_controller.py

from controller import Controller

def test_controller_work_loop():
    # ARRANGE
    controller = Controller(subscriber=None, publisher=None)

    # Some actual tests here
    # This test passes and finishes but the test suite never exits

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Default arguments are evaluated when the class is loaded.

from data_listener import DataListener

class Controller:
    def __init__(
        self,
        subscriber=DataListener(port=DEFAULT_SUBSCRIBER_PORT),  # These are run!
        publisher=JsonPublisher(DEFAULT_PUBLISHER_PORT)):

        pass

You need to update your Controller class to initialize them lazily in your initializer

from data_listener import DataListener

class Controller:
    def __init__(self, subscriber=None, publisher=None):
        self.subscriber = subscriber or DataListener(port=DEFAULT_SUBSCRIBER_PORT)
        self.publisher = publisher or JsonPublisher(DEFAULT_PUBLISHER_PORT)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading