Python 如何将Twisted从插件调用到已经运行主循环的GTK程序?

Python 如何将Twisted从插件调用到已经运行主循环的GTK程序?,python,asynchronous,twisted,rhythmbox,Python,Asynchronous,Twisted,Rhythmbox,我编写了一个Rhythmbox插件,并尝试添加一些代码以异步下载一些JSON。回调在do\u activate功能中注册: def do_activate(self): shell = self.object sp = shell.props.shell_player self.db = shell.get_property('db') self.qm = RB.RhythmDBQueryModel.new_empty(self.db) self.pec_

我编写了一个Rhythmbox插件,并尝试添加一些代码以异步下载一些JSON。回调在
do\u activate
功能中注册:

def do_activate(self):
    shell = self.object
    sp = shell.props.shell_player
    self.db = shell.get_property('db')
    self.qm = RB.RhythmDBQueryModel.new_empty(self.db)
    self.pec_id = sp.connect('playing-song-changed', self.playing_entry_changed)
    self.pc_id = sp.connect('playing-changed', self.playing_changed)
    self.sc_id = sp.connect('playing-source-changed', self.source_changed)
    self.current_entry = None

    ...
当触发
playing\u changed
时,我试图下载一些内容。它目前使用
urllib2
同步下载内容,但这可能会在短时间内阻塞UI。我想使用Twisted来解决这个问题,但我看到的所有示例都使用
reactor.run()
,它会无限期地阻塞

我是Twisted的新手,我想知道,有没有什么方法可以在不阻塞主线程的情况下异步处理这种情况


完整的代码是

在twisted中,没有任何方法可以在不运行IO循环的情况下执行异步http请求(
reactor.run
)。运行
reactor
可以使用默认情况下python中不存在的异步特性。然而,如果您使用twisted的唯一原因是进行异步http调用,那么这可能是一种过激行为。改用简单线程,让线程等待http响应。

twisted中没有任何方法可以在不运行IO循环的情况下执行异步http请求(
reactor.run
)。运行
reactor
可以使用默认情况下python中不存在的异步特性。然而,如果您使用twisted的唯一原因是进行异步http调用,那么这可能是一种过激行为。改用简单线程,让线程等待http响应。

在Rhythmbox插件的上下文中,您可能需要处理GTK主循环已经运行的事实。这是Twisted原则上支持的一种情况,但在主循环上协同初始化反应器(可能有,也可能没有)所支持的API是很棘手的

您可以使用如下函数来解决此问题:

def maybeInstallReactor():
    import sys
    if 'twisted.internet.reactor' not in sys:
        from twisted.internet import gtk2reactor # s/2/3 if you're using gtk3
        reactor = gtk2reactor.install()
        reactor.startRunning()
        reactor._simulate()
    else:
        from twisted.internet import reactor
    return reactor
确保在导入任何其他内容(尤其是来自Twisted的内容)之前,尽早在程序中调用此函数

startRunning
调用将反应堆连接到GLib主回路,而
\u simulate
调用将Twisted的定时事件连接到GLib定时器


不幸的是,这确实涉及到调用一个私有函数,
\u simulate
,因此您必须小心确保Twisted的新版本不会破坏它;另外,除了这一个私有方法调用之外,关于Twisted的使用没有什么需要奇怪的。

在RhythmathBox插件的上下文中,您可能需要处理GTK主循环已经运行的事实。这是Twisted原则上支持的一种情况,但在主循环上协同初始化反应器(可能有,也可能没有)所支持的API是很棘手的

您可以使用如下函数来解决此问题:

def maybeInstallReactor():
    import sys
    if 'twisted.internet.reactor' not in sys:
        from twisted.internet import gtk2reactor # s/2/3 if you're using gtk3
        reactor = gtk2reactor.install()
        reactor.startRunning()
        reactor._simulate()
    else:
        from twisted.internet import reactor
    return reactor
确保在导入任何其他内容(尤其是来自Twisted的内容)之前,尽早在程序中调用此函数

startRunning
调用将反应堆连接到GLib主回路,而
\u simulate
调用将Twisted的定时事件连接到GLib定时器


不幸的是,这确实涉及到调用一个私有函数,
\u simulate
,因此您必须小心确保Twisted的新版本不会破坏它;另外,除了这一个私有方法调用之外,关于Twisted的使用没有什么奇怪的。

这并不是“过度使用”。即使您希望在线程中执行请求,Twisted的
deferToThread
也提供了一种处理请求和响应的规范化方法。这不是“过度杀戮”。即使您希望在线程中执行请求,Twisted的
deferToThread
也提供了一种处理请求和响应的规范化方法。这看起来非常简洁,我必须尽快尝试!谢谢你这么说:)。请用您的结果评论6147号机票!我想听听这个策略在实践中是否有效,特别是如果你有两个插件都尝试使用它。这看起来很不错,我很快就要尝试了!谢谢你这么说:)。请用您的结果评论6147号机票!我想听听这个策略在实践中是否有效,特别是如果您有两个插件都尝试使用它。