为什么Popen函数在Python和PyGTK中表现不同?

问题描述

| 我在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)