Python、Quickly 和 Glade,如何在 TextView 中显示 stdout
我花了很长时间寻找解决办法,但到现在为止还没有找到。 :(
我想为我做的一个小命令行程序制作一个图形界面,所以我觉得使用Ubuntu的“Quickly”是最简单的办法。基本上,它似乎是用Glade来制作图形界面的。我知道我需要在一个子进程中运行我的命令行程序,然后把输出和错误信息发送到一个文本视图中。但我就是搞不懂该怎么做。
这是Glade/Quickly为我想要显示输出的对话框生成的代码:
from gi.repository import Gtk # pylint: disable=E0611
from onice_lib.helpers import get_builder
import gettext
from gettext import gettext as _
gettext.textdomain('onice')
class BackupDialog(Gtk.Dialog):
__gtype_name__ = "BackupDialog"
def __new__(cls):
"""Special static method that's automatically called by Python when
constructing a new instance of this class.
Returns a fully instantiated BackupDialog object.
"""
builder = get_builder('BackupDialog')
new_object = builder.get_object('backup_dialog')
new_object.finish_initializing(builder)
return new_object
def finish_initializing(self, builder):
"""Called when we're finished initializing.
finish_initalizing should be called after parsing the ui definition
and creating a BackupDialog object with it in order to
finish initializing the start of the new BackupDialog
instance.
"""
# Get a reference to the builder and set up the signals.
self.builder = builder
self.ui = builder.get_ui(self)
self.test = False
def on_btn_cancel_now_clicked(self, widget, data=None):
# TODO: Send SIGTERM to the subprocess
self.destroy()
if __name__ == "__main__":
dialog = BackupDialog()
dialog.show()
Gtk.main()
如果我把这个放在finish_initializing函数里
backend_process = subprocess.Popen(["python", <path to backend>], stdout=subprocess.PIPE, shell=False)
那么这个进程就会作为另一个PID启动并运行,这正是我想要的,但现在我该怎么把backend_process.stdout发送到文本视图呢?我可以用下面的代码写入文本视图:
BackupDialog.ui.backup_output.get_buffer().insert_at_cursor("TEXT")
但我只需要知道如何在每次有新的输出行时调用这个。
1 个回答
0
但是我只想知道每次有新的输出行时,怎么能让这个被调用。
你可以使用 GObject.io_add_watch
来监控子进程的输出,或者创建一个单独的线程来读取子进程的内容。
# read from subprocess
def read_data(source, condition):
line = source.readline() # might block
if not line:
source.close()
return False # stop reading
# update text
label.set_text('Subprocess output: %r' % (line.strip(),))
return True # continue reading
io_id = GObject.io_add_watch(proc.stdout, GObject.IO_IN, read_data)
或者使用线程:
# read from subprocess in a separate thread
def reader_thread(proc, update_text):
with closing(proc.stdout) as file:
for line in iter(file.readline, b''):
# execute update_text() in GUI thread
GObject.idle_add(update_text, 'Subprocess output: %r' % (
line.strip(),))
t = Thread(target=reader_thread, args=[proc, label.set_text])
t.daemon = True # exit with the program
t.start()