繁体   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