【发布时间】:2016-05-04 07:57:10
【问题描述】:
我是面向对象编程、Python 和 GTK+3 的新手,但我对过程编程(主要是 C)有相当的了解。
我正在尝试构建一个简单的 Python + GTK+ 3 脚本以在 Linux 下运行 pkexec apt-get update。
我有一个mainWindow 类(基于Gtk.Window 类),其中包含一个名为button 的按钮对象(基于Gtk.Button 类),它触发mainWindow 中定义的new_update_window() 方法clicked 事件;
new_update_window() 方法从包含名为 label 的标签对象(基于 Gtk.Label 类)的 updateWindow 类(基于 Gtk.Window 类)初始化 updateWindow 对象并调用方法show_all()和update()定义在updateWindow中;
update() 方法应该更改 label,运行 pkexec apt-get update 并再次更改 label。
问题是无论我做什么都会出现以下情况之一:
- 如果我直接运行
subprocess.Popen(["/usr/bin/pkexec", "/usr/bin/apt-get", "update"]),会显示update.Window,但会立即将label设置为只有在pkexec apt-get update完成执行后才应设置的值; - 如果我直接运行
subprocess.call(["/usr/bin/pkexec", "/usr/bin/apt-get", "update"]),直到pkexec apt-get update执行完毕,update.Window才会显示; - 我尝试了
importingthreading,在updateWindow中定义了一个单独的run_update()方法并使用thread = threading.Thread(target=self.run_update)、thread.start()、thread.join()在单独的线程中启动该函数,但仍然取决于哪个我在run_update()(subprocess.call()或subprocess.Popen)中调用的方法显示了上述相关行为。
Tl;博士
我不知道如何完成我所追求的,即:
- 显示
updateWindow(Gtk.Window) - 在
updateWindow中更新label(Gtk.Label) - 正在运行
pkexec apt-get update - 在
updateWindow中更新label
-
subprocess.Popen():update.Window已显示,但label立即设置为只有在pkexec apt-get update完成执行后才应设置的值; -
subprocess.call():update.Window直到pkexec apt-get update完成执行后才会显示; - 将两者中的任何一个包装在函数中并在单独的线程中运行该函数不会改变任何内容。
这是代码;
不使用线程(案例1,在本例中使用subprocess.Popen()):
#!/usr/bin/python3
from gi.repository import Gtk
import subprocess
class mainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title = "Updater")
button = Gtk.Button()
button.set_label("Update")
button.connect("clicked", self.new_update_window)
self.add(button)
def new_update_window(self, button):
update = updateWindow()
update.show_all()
update.update()
class updateWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title = "Updating...")
self.label = Gtk.Label()
self.label.set_text("Idling...")
self.add(self.label)
def update(self):
self.label.set_text("Updating... Please wait.")
subprocess.call(["/usr/bin/pkexec", "/usr/bin/apt-get", "update"])
self.label.set_text("Updated.")
def run_update(self):
main = mainWindow()
main.connect("delete-event", Gtk.main_quit)
main.show_all()
Gtk.main()
使用线程(案例3,在本例中使用subprocess.Popen()):
#!/usr/bin/python3
from gi.repository import Gtk
import threading
import subprocess
class mainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title = "Updater")
button = Gtk.Button()
button.set_label("Update")
button.connect("clicked", self.new_update_window)
self.add(button)
def new_update_window(self, button):
update = updateWindow()
update.show_all()
update.update()
class updateWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title = "Updating...")
self.label = Gtk.Label()
self.label.set_text("Idling...")
self.add(self.label)
def update(self):
self.label.set_text("Updating... Please wait.")
thread = threading.Thread(target=self.run_update)
thread.start()
thread.join()
self.label.set_text("Updated.")
def run_update(self):
subprocess.Popen(["/usr/bin/pkexec", "/usr/bin/apt-get", "update"])
main = mainWindow()
main.connect("delete-event", Gtk.main_quit)
main.show_all()
Gtk.main()
【问题讨论】:
-
thread.join()将等到run_update完成,这可能不是故意的。 -
@J.J.Hakala 更新,使其更有意义。
thread.join()的重点是在触发self.label.set_text("Updated.")之前等待run_update()完成,但实际发生的是它不等待run_update()完成并继续执行 @ 987654384@(即:当pkexec apt-get update仍在运行时,我可以看到标签报告“已更新。”)。
标签: linux python-3.x subprocess gtk3