2011-05-29 42 views
1

我在Python程序写了两行,他们工作得很好:为什么Popen()函数在Python和PyGTK中表现不同?

subprocess.Popen("./prog infile outfile >/dev/null", cwd="/path/to/prog", stdout=subprocess.PIPE, shell=True) 

output = subprocess.Popen("prog1 infile1 2>/dev/null", stdout=subprocess.PIPE, shell=True).stdout.read() 

然而这两行代码不要在我PyGTK的应用程序正常工作。我从TreeView小部件的“行激活”信号调用的处理函数调用这些行。 prog写出outfile,也不会得到输出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._f, 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, False, 0) 
     self.rbox.pack_start(self.v1sw, False, False, 0) 
     self.box = gtk.HBox(False, 0) 
     self.box.pack_start(self.tvsw, False, False, 0) 
     self.box.pack_start(self.rbox, False, False, 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", 
          stdout=subprocess.PIPE, 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 is here

+0

你确定处理程序被添加一些调试输出实际执行,例如? – 2011-05-29 12:31:34

+0

是的,处理程序被正确调用。我没有检查。 – rup 2011-05-29 12:32:43

+0

你的指示真的很奇怪。第一行使用shell将输出重定向到'/ dev/null',但是总是捕获'stdout'。不会有任何输出,它会被重定向到'/ dev/null'! – 2011-05-29 12:36:30

回答

-3

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) 
+0

不正确。 Popen需要一个字符串以及一个列表。不同之处在于'shell ='参数。 – hop 2011-05-29 16:22:58

+0

shell = True删除OSError。 – rup 2011-05-30 04:01:37

1

首先,我没有看到您等待子进程来完成。

这里可能发生的情况是,您的pygtk启动一个子进程并立即退出,python垃圾收集器销毁Popen对象。

当您在python shell或其他一些长时间运行的函数中运行相同的代码时,Popen会获得更多时间并希望子进程完成。

要快速测试这是否实际上是问题,请尝试在Popen调用后添加time.sleep(1)

你应该做的是在Popen对象上调用.communicate()来确保子进程完成它的事情并终止。

第二个,我遇到过pygtk程序暂时改变工作目录到其他东西然后改回来的情况。

若要快速测试这种情况下,尽量提供给/path/to/prog完整路径既以及INFILE,OUTFILE,重定向等

相关问题