[英]Using threads in PyGObject with GTK3 in python3
So I am trying to use threads to implement a blocking operation in a Python3 based application. 因此,我试图使用线程在基于Python3的应用程序中实现阻止操作。
#!/usr/bin/env python3
import gi, os, threading, Skype4Py
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, GObject
skype = Skype4Py.Skype()
def ConnectSkype():
skype.Attach()
class Contacts_Listbox_Row(Gtk.ListBoxRow):
def __init__(self, name):
# super is not a good idea, needs replacement.
super(Gtk.ListBoxRow, self).__init__()
self.names = name
self.add(Gtk.Label(label=name))
class MainInterfaceWindow(Gtk.Window):
"""The Main User UI"""
def __init__(self):
Gtk.Window.__init__(self, title="Python-GTK-Frontend")
# Set up Grid object
main_grid = Gtk.Grid()
self.add(main_grid)
# Create a listbox which will contain selectable contacts
contacts_listbox = Gtk.ListBox()
for handle, name in self.GetContactTuples():
GLib.idle_add(contacts_listbox.add, Contacts_Listbox_Row(name))
GLib.idle_add(main_grid.add, contacts_listbox)
# Test label for debug
label = Gtk.Label()
label.set_text("Test")
GLib.idle_add(main_grid.attach_next_to, label, contacts_listbox, Gtk.PositionType.TOP, 2, 1)
def GetContactTuples(self):
"""
Returns a list of tuples in the form: (username, display name).
Return -1 if failure.
"""
print([(user.Handle, user.FullName) for user in skype.Friends]) # debug
return [(user.Handle, user.FullName) for user in skype.Friends]
if __name__ == '__main__':
threads = []
thread = threading.Thread(target=ConnectSkype) # potentially blocking operation
thread.start()
threads.append(thread)
main_window = MainInterfaceWindow()
main_window.connect("delete-event", Gtk.main_quit)
main_window.show_all()
print('Calling Gtk.main')
Gtk.main()
The basic idea is this simple program should fetch a list of contacts from the Skype API, and build a list of tuples. 基本思想是,这个简单的程序应该从Skype API中获取联系人列表,并构建一个元组列表。 The GetContactTuples
function succeeds in its design, the print call I placed verifies that. GetContactTuples
函数在其设计中成功,我放置的打印调用验证了这一点。 However, the program hangs indefinitely, and never renders an interface. 但是,该程序会无限期挂起,并且永远不会呈现接口。 Sometimes, it will yield random errors involving threads and/or resource availability. 有时,它会产生涉及线程和/或资源可用性的随机错误。 Once such error is 一旦这样的错误是
(example.py:31248): Gdk-WARNING **: example.py: Fatal IO error 11 (Resource temporarily unavailable) on X server :1.
I know it is related to the use of threads, but based on the documentation here , it seems like just adding GLib.idle_add
calls before interface updates should be sufficient. 我知道它与线程的使用有关,但是根据这里的文档,似乎只是在接口更新之前添加GLib.idle_add
调用就足够了。 So the questions are, why does this not work, and how could I correct the above sample? 所以问题是,为什么这不起作用,我怎么能纠正上面的样本?
UPDATE: If GLib.idle_add
is prepended to every line that interacts with GTK that it can be, I get a different error. 更新:如果GLib.idle_add
被添加到与GTK交互的每一行,它会得到一个不同的错误。 [xcb] Unknown request in queue while dequeuing [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. python: xcb_io.c:179: dequeue_pending_request: Assertion '!xcb_xlib_unknown_req_in_deq' failed. Aborted (core dumped)
Depending on your library version (this was no longer necessary in Gobject
3.10.2) you might need to actually need to explicitly initialize your threads using GObject.threads_init()
as below: 根据您的库版本(在Gobject
3.10.2中不再需要),您可能需要使用GObject.threads_init()
实际需要显式初始化线程,如下所示:
if __name__ == '__main__':
threads = []
thread = threading.Thread(target=ConnectSkype) # potentially blocking operation
thread.start()
threads.append(thread)
main_window = MainInterfaceWindow()
main_window.connect("delete-event", Gtk.main_quit)
GObject.threads_init()
main_window.show_all()
print('Calling Gtk.main')
Gtk.main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.