Avoid circular import when accessing instance value from main.py

Question:

I´m new to Python and programming in general. So maybe there is an easy solution for more experienced programmers.
I already read a lot of question regarding circular imports, but unfortunately there was nothing there that I can apply to my situation if I dont want to move all the code in one file.

I created an userinterface with pyqt (qt creator) and converted the mainwindow.ui to mainwindow.py.
My plan is to split the code into 3 modules. A main module to start the application, an ui module with the class of the main window and a buttons module with classes for the buttons.

My problem is that the functions within the button classes should change a label value of the main window instance. I learned to create the main window instance in the main module. As a result of this I need to import the instance from the main module into the buttons module to change the intended value and that leads to an circular import.

How do I have to organize/structure my code to avoid this?

Here is a short and simplified example for better understanding:

main.py

import sys
from qtpy import QtWidgets
from ui import MainWindow

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

ui.py

from qtpy import QtWidgets
from userinterface.mainwindow import Ui_MainWindow
import buttons

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.button_0 = buttons.NumberButton(0)
        self.button_1 = buttons.NumberButton(1)

        self.ui.btn_0.clicked.connect(self.button_0.button_clicked)
        self.ui.btn_1.clicked.connect(self.button_1.button_clicked)

buttons.py

from main import window

class NumberButton:
    def __init__(self, number):
        self.number = str(number)

    def button_clicked(self):
        window.ui.lb_result.setText(self.number)
Asked By: Tireg

||

Answers:

If you only import the module python should automatically avoid circular imports. So do import ui and import buttons

Answered By: Ed Vraz

Your design problem is that your NumberButton class calls one specific window instance. Your have to let your buttons know to which window they belong. Try the following: remove the import statement from buttons.py and add a new parameter window to the __init__ method:

class NumberButton:
    def __init__(self, window, number):
        self.window = window
        self.number = str(number)

    def button_clicked(self):
        self.window.ui.lb_result.setText(self.number)

Then instantiate in NumberButton like:

...
self.button_0 = buttons.NumberButton(self, 0)
...
Answered By: MaxPowers
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.