Python PyQt 回调永远不会运行——如何调试? [英] Python PyQt callback never runs - how to debug?

查看:114
本文介绍了Python PyQt 回调永远不会运行——如何调试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段相当复杂的使用 PyQt4 的代码,有时我的信号回调根本没有运行.

I have a fairly complicated piece of code using PyQt4 and sometimes my signal callbacks simply never run.

这似乎与我在哪里/何时注册回调有关,即.self.someobj.somesig.connect(self.callback).

It seems to be related to where/when I register the callbacks, ie. self.someobj.somesig.connect(self.callback).

我可以在调试器中看到回调已连接并且发出了信号.

I can see in the debugger that the callback is connected and that the signal es emitted.

代码太大,无法贴在这里,但我会尽量总结:

The code is too large to post here, but I will try to summarize:

class RC(QtCore.QObject):
  render_ready = QtCore.pyqtSignal(object)
  def __init__(self, pc, ...):
    super(RC, self).__init__()
    self.pc = pc
    self.pc.rr.new_render.connect(self.insert)
  def check(self):
    ...
    if a: self.pc.replot_request.emit()
    else: self.pc.render_request.emit()
  def insert(self, r):
    ...
    if b: self.render_ready.emit(r)
    self.check()

class RR(QtCore.QObject):
  new_render = QtCore.pyqtSignal(object)
  def __init__(self, pc, app,...):
    super(RR, self).__init__()
    self.app = app
    self.pc = pc
  def run(self):
    self.pc.replot_request.connect(self.on_replot_request)
    self.pc.render_request.connect(self.render)
  ...
  def render(self, scale):
    ...
    r = R(i)
    r.moveToThread(QtGui.QApplication.instance().thread())
    r.new_render.emit(r)

class R(QtCore.QObject):
  def __init__(self, i):
    super(R, self).__init__()
    ...
  ...

class PC(QtCore.QObject):
  render_request = QtCore.pyqtSignal(int)
  replot_request = QtCore.pyqtSignal(object)
  def __init__(self, container, app):
    super(PC, self).__init__()
    ...
    self.rr = RR(self.app)
    self.rr_thread = QtCore.QThread()
    self.rr.moveToThread(self.rr_thread)
    self.connect(self.rr_thread, QtCore.SIGNAL("started()"), self.rr.run)
    self.c = RC(self)
    ...
    self.c.render_ready.connect(self.on_nr)
  def start(self):
    self.rr_thread.start()
  def on_nr(self, r):
    print "on_nr(...)"

class App(QtCore.QObject):
  ...
  def __init__(self):
    ..
    self.pc = PC(container, app)
    ...
    self.pc.start(self)  # Last thing in constructor

X = QtGui.QApplication(sys.argv)
a = App()
sys.exit(X.exec_())

我看到 render_ready 连接到 on_nr 并且发出 render_ready .但是 on_nr 永远不会运行.信号序列很复杂,它跨线程,但有问题的信号和回调在同一个线程中.此外,事件循环显然正在运行.我怎样才能开始深入挖掘?还是我犯了一些明显的错误?谢谢.

I see render_ready being connected to on_nr and the render_ready being emitted. But on_nr never runs. The signal sequence is complicated, it goes across threads, but the signal and callback in question are in the same thread. Also, the event loop is clearly running. How could I start digging deeper? Or am I making some evident mistake? Thanks.

推荐答案

不幸的是,正如问题的评论中所建议的那样,这是一个愚蠢的错误.它与 PyQt 或信号的使用无关.我发布了问题所在以及我如何调试它,希望它仍然可以帮助某人.

Unfortunately it was a silly mistake as suggested in the comments to the question. It had nothing to do with PyQt or the use of signals. I post what the problem was and how I debugged it in hopes that it still might help somebody.

问题出在哪里

我用一个新的对象覆盖了发出信号的对象(试图重置状态),所以它的信号不再连接到回调.

I was overwriting the object that emitted the signal with a new one (an attempt to reset state), so its signal was not connected to the callback any more.

检测方式

在调试器中,当我将信号连接到它时,我注意到 a.pp.rr 的地址有一个值,而当信号发出时,它的地址是不同的.两个不同的对象.

In the debugger I noticed that the address of a.pp.rr had one value when I connected the signal to it, and when the signal was emitted, it's address was different. Two different objects.

所以代码很干净,PyQt 信号的使用是正确的.也许学到的教训是在替换实例时要小心.确保将所有信号重新连接到/来自新实例,或者在对象中创建一个方法来重置它的状态(这就是我所做的)以避免破坏原始实例.

So the code was clean and the use of PyQt signals was correct. Perhaps the lesson learned is to be careful when replacing an instance. Make sure to reconnect all signals to/from the new instance, or create a method in the object to reset it's state (this is what I did) to avoid destroying the original instance.

其他选项

关于创建最小、完整和可验证的示例,如前所述,这可能是最合适的格式化方式本论坛中的一个问题以及确定问题根源的良好练习.通过巧妙地使用调试器,同样有效,也许更适合解决更晦涩和复杂的问题.如果您将 A 编码为连接到 B 并且 A 对 B 没有影响,那么 A 可能与A"不同,或者 B 与连接"时的B"不同,或者连接在某个时候被移除.当您遗漏了某些东西时,您可能希望更清楚地了解正在发生的事情.

With regards to creating an Minimal, Complete, and Verifiable example as suggested earlier, it is perhaps the most appropriate way to format a question in this forum and a good exercise in identifying the source of problems. Equally valid, and perhaps more appropriate for more obscure and complex problems is through the skillful use of the debugger. If you are coding A to be connected to B and A is not having and impact on B, then it is possible that A is not the same "A" or B is not the same "B" as when the "connection" was made, or the connection was removed at some point. When you are missing something, perhaps you want is to gain more visibility into what is happening.

这篇关于Python PyQt 回调永远不会运行——如何调试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆