2011-05-29 41 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,重定向等

相關問題