[PyQt] New exception in Python 3.7.4 when bad code tries to PyQt5.uic.loadUi()
Phil Thompson
phil at riverbankcomputing.com
Wed Aug 7 18:50:17 BST 2019
On 07/08/2019 18:06, Kyle Altendorf wrote:
> On 2019-08-07 12:50, Phil Thompson wrote:
>> On 07/08/2019 16:54, Kyle Altendorf wrote:
>>> On 2019-08-07 07:13, Phil Thompson wrote:
>>>> On 05/08/2019 18:25, Kyle Altendorf wrote:
>>>>> On 2019-08-03 14:38, Kyle Altendorf wrote:
>>>>>> I have many custom widgets with pyqtProperty's and GUI elements
>>>>>> loaded
>>>>>> from .ui files. In various ways, my existing code tries to access
>>>>>> not-yet-present attributes in pyqtProperty's while the .ui is
>>>>>> being
>>>>>> loaded. This is obviously bad and I plan to fix my code. I share
>>>>>> this example because I already finished it and because this is an
>>>>>> odd
>>>>>> change of behavior from a micro version bump of Python. Also, it
>>>>>> is
>>>>>> odd that each first time my code raises an exception there is not
>>>>>> necessarily a Qt failure. For example, WidgetB must be
>>>>>> constructed
>>>>>> twice to get the traceback. I understand that this may well not
>>>>>> get
>>>>>> 'fixed' since it probably never should have worked to begin with.
>>>>>>
>>>>>> Code and output from 3.7.3/3.7.4 on Linux/Windows are attached and
>>>>>> also available at:
>>>>>>
>>>>>> https://gist.github.com/altendky/f15f8d180269a4080c25dec83cf556a0
>>>>>>
>>>>>> Here is the basic traceback:
>>>>>>
>>>>>> AttributeError: __getattribute__
>>>>>>
>>>>>> The above exception was the direct cause of the following
>>>>>> exception:
>>>>>>
>>>>>> Traceback (most recent call last):
>>>>>> File "bad.py", line 146, in main
>>>>>> widgets.append(WidgetA(broken=True))
>>>>>> File "bad.py", line 53, in __init__
>>>>>> PyQt5.uic.loadUi(io.StringIO(ui_text), self)
>>>>>> File
>>>>>> "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\__init__.py",
>>>>>> line
>>>>>> 227, in loadUi
>>>>>> return DynamicUILoader(package).loadUi(uifile,
>>>>>> baseinstance,
>>>>>> resource_suffix)
>>>>>> File
>>>>>> "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\Loader\loader.py",
>>>>>> line 72, in loadUi
>>>>>> return self.parse(filename, resource_suffix, basedir)
>>>>>> File
>>>>>> "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\uiparser.py",
>>>>>> line
>>>>>> 1030, in parse
>>>>>> actor(elem)
>>>>>> File
>>>>>> "C:\epc\bug\venv3.7-32\lib\site-packages\PyQt5\uic\uiparser.py",
>>>>>> line
>>>>>> 942, in createConnections
>>>>>> QtCore.QMetaObject.connectSlotsByName(self.toplevelWidget)
>>>>>> SystemError: <built-in function connectSlotsByName> returned a
>>>>>> result with an error set
>>>>>
>>>>> I read briefly about this SystemError and it seems that while yes,
>>>>> my
>>>>> code was raising an exception and shouldn't really have worked
>>>>> ever...
>>>>> this error indicates that connectSlotsByName() isn't properly
>>>>> propagating the exception and is instead returning a value as if no
>>>>> exception occurred. As such it seems that there is an error in the
>>>>> PyQt connectSlotsByName() wrapper in addition to my code. Though I
>>>>> admittedly don't know my way around SIP nor the C-API much.
>>>>
>>>> It could also be that an exception is being correctly ignored, but
>>>> not
>>>> cleared with PyErr_Clear().
>>>
>>> Why would it be correct to ignore my code raising an exception? It
>>> seems bad that my code has been seemingly silently raising these
>>> exceptions for a few years and I was unaware of it. I guess it could
>>> be argued that it would be handy for PyQt to add an exception
>>> ignoring
>>> feature and let connectSlotsByName() continue with it's work despite
>>> Python code failing. But this isn't the direction I would personally
>>> default. Mostly unhandled exceptions should be seen I would think.
>>
>> I wasn't referring to your code but to the implementation of
>> connectSlotsByName().
>
> That's what I was responding to. It doesn't seem like
> connectSlotsByName() should be silencing exceptions raised by my code
> that it calls. Or maybe something else is calling my code and this is
> just a delayed error. Regardless, I would think that if my code
> raises an exception the default behavior ought to be to fail and show
> that error, not continue silently. I know my code is bad in this
> regard and neither before nor at Python 3.7.4 is there a message about
> the exception my code raises.
As I said, I wasn’t referring to exceptions raised by your code.
> Anyways, I think we may have agreed that something somewhere, other
> than my code raising an exception, isn't quite right?
Yes (although I don’t get a traceback with v3.8).
Phil
More information about the PyQt
mailing list