我正在开发一个项目,我想在python pygtk GUI中使用命令行实用程序cdparanoia。我正在使用Glade进行UI开发。我尝试过导入子进程并使用subprocess.Popen。它工作正常,但它会在进程执行时冻结我的GUI(甚至不允许重新绘制窗口)。对用户来说不是一个非常好的交互。我该如何防止这种行为?我想在窗口上放一个取消按钮,但这可以工作,因为它“冻结”程序。最后,我想捕获stderr(如下所示,音频信息通过stdout传送到sox)并将其作为一个gtk.Expander显示,当它安装一个具有用户能力的程序时,它与Synaptic具有相似的外观事情发生在实时。另外,我想使用进度指示器中的文本(如下所示)来构建真正的进度指示器小部件。如何让shell实时将信息传递回python而不是一旦完成该过程(当它将所有内容作为一个大的信息转储时)?
需要捕获的实时信息:
Working on me - me - DISK 01.flac
cdparanoia III release 10.2 (September 11, 2008)
Ripping from sector 0 (track 1 [0:00.00])
to sector 325195 (track 15 [1:56.70])
outputting to stdout
(== PROGRESS == [> | 004727 00 ] == :-) O ==)
这是我到目前为止使用的代码:
quick = " -Z" if self.quick == True else ""
command = "cdparanoia -w%s 1- -| sox -t wav - \"%s - %s - DISK %s%s.flac\"" %\
(
quick,
self.book_name.replace(" ", "_"),
self.author_name.replace(" ", "_"),
"0" if disc < 10 else "",
disc
)
print command
shell = subprocess.Popen(command, shell=True, executable="/bin/bash",
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
data, err = shell.communicate(command)
谢谢, Narnie
答案 0 :(得分:2)
我写了一次Python shell实现,它确实运行了wget
和具有全功能输出的实际Python控制台。
您需要使用subprocess.Popen
并直接写入sys.stdout
:
process = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
complete = False
while True:
output = process.stdout.read(1)
if output == '' and process.poll() != None:
break
if output != '':
sys.stdout.write(output)
sys.stdout.flush()
答案 1 :(得分:1)
如果编写一个从文件句柄读取的GUI程序,则有两个使用调度程序将文件描述符事件集成到GUI事件循环中。可以在Wikipedia找到事件循环的一般描述。有关Gtk +的具体说明,请参阅reference。
解决您的问题:使用函数g_io_add_watch
将您的操作集成到主事件循环中。 Here是C中的一个例子.Python应该是类似的。
答案 2 :(得分:0)
是的,这里有2个问题。 首先,您需要指定读取超时,以便 在子流程完成之前,您不会阻止。 第二,可能存在缓冲,这是不可取的。
解决第一个问题,并异步读取子进程 你可以尝试我的subProcess模块,超时: http://www.pixelbeat.org/libs/subProcess.py 注意这很简单,但也只是旧的和Linux。 它被用作新python子进程模块的基础, 如果你需要便携性,那么你最好还是选择它。
要了解/控制可能发生的任何其他缓冲,请参阅: http://www.pixelbeat.org/programming/stdio_buffering/