Nuitka: PySide6 QTimer.timeout.connect does not work within QMainWidget, but in QApplication
Hi,
I’ve made a PySide6 GUI application with several QTimer objects within widgets.
If I execute the application with python, everything is fine. Also deployed with cx_freeze.
Now I’ve tried nuitka with following command:
python.exe -m nuitka --mingw64 --standalone test.py --plugin-enable=pyside6 --plugin-enable=pylint-warnings --follow-imports
The result does not work, since the methods connected to the timers are not executed. I’ve made 2 small examples you can find at the end.
-
Nuitka version, full Python version and Platform (Windows, OSX, Linux …)
python -m nuitka --version
0.6.16.4
Python: 3.9.4 (tags/v3.9.4:1f2e308, Apr 6 2021, 13:40:21) [MSC v.1928 64 bit (AMD64)]
Executable: C:\Users\Bad\AppData\Local\Programs\Python\Python39\python.exe
OS: Windows
Arch: x86_64
- How did you install Nuitka and Python
installed via pip. No venv
- The specific PyPI names and versions
python -m pip freeze
PySide6==6.1.3
- Also supply a Short, Self Contained, Correct, Example Not Working Example QTimer within Widget:
#%%
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import QTimer
class MainWidget(QMainWindow):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.timer = QTimer(self) #self
self.timer.timeout.connect(self.update)
self.timer.start(1000)
self.count = 0
def update(self):
self.count += 1
print ("update ",self.count)
if self.count >5:
self.timer.stop()
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
mymain = MainWidget()
mymain.show()
sys.exit(app.exec())
Expected output:
>test.exe
update 1
update 2
update 3
update 4
update 5
update 6
Working Example - QTimer within QApplication:
#%%
import sys
from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QTimer
class MainApp(QApplication):
def __init__(self, parent=None):
super(MainApp, self).__init__(parent)
self.timer = QTimer(self) #self
self.timer.timeout.connect(self.update)
self.timer.start(1000)
self.count = 0
def update(self):
self.count += 1
print ("update",self.count)
if self.count >5:
self.timer.stop()
self.exit()
if __name__ == "__main__":
app = MainApp(sys.argv)
sys.exit(app.exec())
Any idea?
Best regards Bastian
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 22 (14 by maintainers)
Thanks for your report, this is fixed on the factory branch, which is a development version under rapid development. You can try it out by going here: https://nuitka.net/doc/factory.html
Feedback if this is working is very welcome, just please do not share plans of doing it, but rather confirmations or denials of it working.
I am not sure, if this should feel like a risky change or not, the overload nature of a function on the Python level is not affected by
__name__changes, since it’s in the class dict by the name used during class creation and it remains that way. There may be adverse effects outside of traceback change too. I wonder if we could make a wrapper function, but those will give even uglier tracebacks, and not give us anything really than avoiding to modify the original function.We now have a workaround for reference losses in connecting the slots with methods, that’s another bug in PySide6 there.
And just doing this, workarounds this bug.
I wish there was a way to know if a function name causes the issue. But for now, your example works when I add that out of the box.
I also can do this I guess
That will affect tracebacks, but it will make PySide6 definitely not consider the signature of a base method.
Well, that’s of course not right. I am not sure it’s a bug of yours, I am pretty sure it’s one of ours, Nuitka and/or PySide6 here, but at least you now have a workaround. I cannot work on this right away, but it seems important, and so this will be dealt with eventually.
However, thanks for the good report, and sticking with me on this. 😃
This does it for me, thank you, but I am totally confused as to what the difference could be. But once I know the bug, maybe I can tell why it was working for me with the other example.
I spend the time, because I can see you are a diligent reporter, but if this wouldn’t work, I think I should know. I was also using 3.9 like you are. Maybe you are having a hello world issue of some sorts, maybe you can use a git clone and run this:
python3.9 bin/compare_with_cpython Mini.pyand provide the output? That is my script used for testing, and it makes sure to compare outputs and use the same Python, etc.
Waste of time, or incomplete report, this works for me under Windows and Linux. With and without standalone mode. And it even worked with PySide 6.1.1 and PySide 6.1.3, so even before the callbacks were fixed for 6.1.2, this one always worked it seems. Please provide more information in case I am mistaken, but it seems you are potentially not looking at the correct thing? And for good measure, I also tried 0.6.15.5 as well as develop…