2012-10-18 26 views
2

我写了一个Rhythmbox插件,我试图添加一些代码来异步下载一些JSON。回调注册在do_activate功能:如何从插件调用Twisted到已经运行主循环的GTK程序?

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_changed被触发下载一些内容。它目前使用urllib2同步下载内容,但这可能会在短时间内阻止用户界面。我想用Twisted来解决这个问题,但是我所见过的所有例子都使用了reactor.run(),它们会无限期地阻止。

我很新来扭曲,我想知道,有没有办法处理这种情况异步处理,而不阻止主线程?

完整的代码here

回答

2

有没有扭曲任何方式做异步HTTP请求不运行IO环(reactor.run)。运行reactor使您能够默认使用python中不存在的异步功能。但是,如果你使用twisted的唯一原因是做异步http调用,这可能是一个矫枉过正。改用简单的线程,让你的线程等待http响应。

+0

这不是“矫枉过正”。即使你想在一个线程中执行你的请求,Twisted的deferToThread提供了一个规范化的方式来处理请求和响应。 – Glyph

2

在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 

确保此功能是尽可能早地在你的程序中调用,之前别的导入的数据(尤其是扭曲的东西)。

startRunning调用挂钩反应堆直到GLib主循环,并且_simulate调用将Twisted的定时事件挂接到GLib定时器。

不幸的是,这涉及到调用一个私有函数_simulate,因此您必须小心确保新版本的Twisted不会破坏它; but as a result of this question I opened a bug to make this use-case explicitly supported.另外,除了这一个私人方法调用之外,没有关于您使用Twisted的其他内容需要很奇怪。

+1

这看起来很整齐,我得尽快尝试! – noisecapella

+0

谢谢你这么说:)。请在票6147评论您的结果!我想听听这个策略在实践中是否行得通,特别是如果你有两个插件都试图使用它。 – Glyph

相关问题