簡體   English   中英

為什么 Popen() function 在 Python 和 PyGTK 中的行為不同?

[英]Why does the Popen() function behave differently in Python and 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", stdout=subprocess.PIPE, shell=True).stdout.read()

然而,這兩行代碼在我的 PyGTK 應用程序中不能正常工作。 我從調用 TreeView 小部件的“行激活”信號的處理程序調用這些行。 prog也沒有寫入outfile ,我也沒有在output變量中得到prog1的 output 。

可能是什么問題呢?


@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 程序就在這里

首先,我沒有看到您等待子進程完成。

這里可能發生的是你的 pygtk 啟動一個子進程並立即退出,python 垃圾收集器破壞了 Popen object。

當您在 python shell 或其他一些長時間運行的 function 中運行相同的代碼時,Popen 會獲得更多時間並希望子進程完成。

要快速測試這是否真的是問題所在,請嘗試在 Popen 調用之后添加time.sleep(1)

您應該做的是在 Popen object 上調用 .communicate .communicate()以確保子進程執行其操作並終止。

其次,我遇到過 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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM