Вручную вызывающий ошибку памяти PyQt / PySide?

#python #pyqt #pyqt5

#python #pyqt #pyqt5

Вопрос:

Предыстория

Я создаю приложение PyQt5 и столкнулся с проблемой

Internal c Object Already Deleted

которая вызвана ошибкой, описанной на этой странице:

Если QObject выпадает из области видимости в Python, он будет удален.

Итак, я смог избежать этой проблемы, используя необязательный parent = параметр или сохранив ссылки на объекты, из-за которых у меня возникла проблема

Вопрос

В целях тестирования я хотел бы знать, возможно ли вручную вызвать эту проблему ( Internal c Object Already Deleted )

Это периодически возникающая проблема, поэтому, чтобы иметь возможность протестировать это, мне нужен какой-то надежный способ ее воспроизведения

(Я не хочу хранить ссылки на все объекты, а сохраняю ссылки только тогда, когда они необходимы)


Я использую PyQt5.15 и Python 3.8

Ответ №1:

Предыдущее примечание: Сообщения об ошибках различаются в зависимости от привязки:

  • PyQt5

     RuntimeError: wrapped C/C   object of type <QtClass> has been deleted
      
  • PySide2

     RuntimeError: Internal C   object (PySide2.<QtModule>.<QtClass>) already deleted.
      

Проблема вызвана тем, что объект C , который управляет объектом python, был удален, и, следовательно, желание изменить какое-либо свойство объекта C с помощью объекта python, очевидно, не может быть выполнено.

Если вы хотите воспроизвести ту же проблему, просто удалите объект C , используя метод удаления sip или shiboken, в зависимости от того, используете ли вы PyQt5 или PySide2 соответственно.

  • PyQt5

     from PyQt5 import QtCore
    import sip
    
    o = QtCore.QObject()
    o.setProperty("foo", "bar")
    sip.delete(o)
    o.setProperty("foo", "bar")
      
  • PySide2

     from PySide2 import QtCore
    import shiboken2
    
    o = QtCore.QObject()
    o.setProperty("foo", "bar")
    shiboken2.delete(o)
    o.setProperty("foo", "bar")
      

Комментарии:

1. Спасибо вам за вашу помощь! — Я все еще не уверен, что понимаю базовую архитектуру, но возможно ли запустить что-то вроде (глобальной) сборки мусора. В IIRC c этого нет, так что, я полагаю, это было бы на уровне Python? (Я действительно пробовал использовать Python gc.collect() , но это не вызвало ни одной из проблем, которые я видел). — Я предполагаю, что я спрашиваю вот о чем: возможно ли сделать что-то подобное тому, что вы описываете, но глобально для всех объектов? С точки зрения практического тестирования сложно добавить свой код для всех объектов (есть риск, что я могу что-то пропустить).