Often times, I have tasks that I need to do in a PyQt5 GUI designed in QtDesigner, that are small enough, that I want to keep all code in a single .py file. So, consider this PyQt5 example:
test3.py
:
import sys
from PyQt5 import QtCore, QtWidgets, QtGui, uic
mod_name = vars(sys.modules[__name__])['__package__'] # SO:1389044
code_exec_as = 'module named {}'.format(mod_name) if mod_name else 'script'
cmdline = "{} {}".format( sys.executable, " ".join(sys.argv) )
try: # SO:6038898
reloading
except NameError:
reloading = False # means the module is being imported
else:
reloading = True # means the module is being reloaded
print("Starting: code executed as {}; reloading {}; command line '{}'".format(code_exec_as, reloading, cmdline))
class MyCustomButton(QtWidgets.QPushButton):
def __init__(self, parent=None):
super().__init__(parent)
print("MyCustomButton init!")
class MyMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MyMainWindow, self).__init__()
uic.loadUi("test3.ui", self)
self.show()
def main():
app = QtWidgets.QApplication(sys.argv)
window = MyMainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
test3.ui
:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>382</width>
<height>232</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
<item>
<widget class="MyCustomButton" name="pushButton_2">
<property name="text">
<string>CustomPushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>382</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<customwidgets>
<customwidget>
<class>MyCustomButton</class>
<extends>QPushButton</extends>
<header>test3</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
When I run this from the command line, I get:
$ python3 test3.py
Starting: code executed as script; reloading False; command line 'C:/msys64/mingw64/bin/python3.exe test3.py'
Starting: code executed as script; reloading False; command line 'C:/msys64/mingw64/bin/python3.exe test3.py'
MyCustomButton init!
Note that the "Starting: ..." printout has run twice: apparently:
- the first time is due to the script being called normally
- the second time is due to
pushButton_2
in the.ui
being promoted to aMyCustomButton
class, which is listed as being defined intest3.py
, so that file needs to be reloaded so that theMyCustomButton
class definition is read
Can I somehow detect which time the script is being run, from within the script (more specifically, from the part of the code after the imports, but before any class definitions and __main__
calls)?
As you can see, I have already tried something in test3.py
, based on:
- how do I determine whether a python script is imported as module or run as script?
- How to tell if a Python modules I being reload()ed from within the module
... but these approaches give me the same output for both "runs" of the script, so I cannot use them to discriminate whether the script is in the first or the second run.