问题描述
|
我在Python程序中编写了这两行,它们运行良好:
subprocess.Popen(\"./prog infile outfile >/dev/null\",cwd=\"/path/to/prog\",stdout=subprocess.PIPE,shell=True)
output = subprocess.Popen(\"prog1 infile1 2>/dev/null\",shell=True).stdout.read()
但是,这两行代码在我的PyGTK应用程序中无法正常工作。我从在TreeView小部件的“行激活”信号上调用的处理程序调用这些行。 prog既不写输出文件,也没有在输出变量中获取prog1的输出。
可能是什么问题呢 ?
@sven Marnach,谢谢您的投入。我在一个较小的PyGTK程序中复制了这种情况,Popen在其中正常运行。
没有理由为什么Popen在PyGTK应用程序中应具有不同的行为。
这意味着我正在做其他导致问题的事情,一旦解决,我将写下来。
#!/usr/bin/env python
import pygtk,sys,gtk,os,subprocess
class C:
def main(self,argv=None):
gtk.main()
def __init__(self):
# Main window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_border_width(2)
self.window.set_position(gtk.WIN_POS_CENTER)
self.window.connect(\"destroy\",self._destroy_window)
# TextView
self.v = gtk.TextView()
self.v.set_name(\"v\")
self.vsw = gtk.ScrolledWindow()
self.vsw.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
self.vsw.add(self.v)
# TextView
self.v1 = gtk.TextView()
self.v1.set_name(\"v1\")
self.v1sw = gtk.ScrolledWindow()
self.v1sw.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
self.v1sw.add(self.v1)
# TreeView
self.model = gtk.ListStore(str,str)
self.tv = gtk.TreeView(self.model)
self.tv.connect(\"row-activated\",self._f,self.v)
self.tv.connect(\"row-activated\",self.v1)
self.c = gtk.CellRendererText()
self.c1 = gtk.CellRendererText()
self.col = gtk.TreeViewColumn(\"C\",self.c,text=0)
self.col1 = gtk.TreeViewColumn(\"C1\",self.c1,text=1)
self.tv.append_column(self.col)
self.tv.append_column(self.col1)
self.tvsw = gtk.ScrolledWindow()
self.tvsw.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
self.tvsw.add(self.tv)
self.fill_model(self.model)
# Layout
self.rBox = gtk.VBox(False,0)
self.rBox.pack_start(self.vsw,False,0)
self.rBox.pack_start(self.v1sw,0)
self.Box = gtk.HBox(False,0)
self.Box.pack_start(self.tvsw,0)
self.Box.pack_start(self.rBox,0)
self.window.add(self.Box)
self.window.show_all()
def fill_model(self,model):
self.dbg(\"fill_model()\")
model.clear()
fd = open(\"file\",\"r\"); rows = fd.readlines(); fd.close()
for l in rows:
a = l.split()
model.append([l[0],l[1]])
return
def _f(self,tview,path,column,textview):
self.dbg(\"_f()\")
tsel = tview.get_selection()
model,iter = tsel.get_selected()
buf = textview.get_buffer()
buf.set_text(\"\")
if(textview.get_name() == \"v\"):
self.dbg(\"_f():v\")
buf.set_text(\"hello\")
elif(textview.get_name() == \"v1\"):
self.dbg(\"_f():v1\")
t = self.g()
buf.set_text(t)
return
def g(self):
self.dbg(\"g()\")
t = subprocess.Popen(\"anubadok file1 2>/dev/null\",shell=True).stdout.read()
self.dbg(\"g(): t = \" + t)
return t
def _destroy_window(self,widget,data = None):
self.dbg(\"_destroy_window()\")
gtk.main_quit()
return
def dbg(self,msg):
sys.stderr.write(\"dbg: %s\\n\" % msg)
if __name__ == \"__main__\":
ui = C()
ui.main()
哪里,
文件:
a cat
b bat
c mat
文件1:
hello world
程序anubadok在这里。
解决方法
首先,我看不到您等待子进程完成。
这里可能发生的是,您的pygtk启动了一个子进程并立即退出,python垃圾回收器破坏了Popen对象。
当您在python shell或其他长时间运行的函数中运行相同的代码时,Popen将获得更多时间,并希望子进程完成。
要快速测试这是否确实是问题所在,请尝试在Popen调用后添加ѭ4。
您应该做的是在Popen对象上调用ѭ5,以确保子进程执行该操作并终止。
其次,我遇到了pygtk程序将工作目录临时更改为其他目录然后又将其更改回的情况。
为了快速测试这种情况,请尝试提供完整的路径到
/path/to/prog
以及infile,outfile,redirect等。
, 的
OSError: [Errno 2] No such file or directory
是由您的Popen通话引起的。子进程需要一个列表:
subprocess.Popen([\"./prog\",\"infile\",\"outfile\",\">/dev/null\"],cwd=\"/path/to/prog\",stdout=subprocess.PIPE,shell=True)