为什么 Popen() 函数在 Python 和 PyGTK 中的行为不同? [英] Why does the Popen() function behave differently in Python and PyGTK?

查看:79
本文介绍了为什么 Popen() 函数在 Python 和 PyGTK 中的行为不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Python 程序中编写了这两行,它们运行良好:

I wrote these two lines in a Python program and they worked fine :

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 的输出.

However these two lines of code do not work correctly in my PyGTK application. I invoke these lines from a handler called on the "row-activated" signal of a TreeView widget. Neither does prog write the outfile, nor do I get the output of prog1 in the output variable.

可能是什么问题?

@Sven Marnach,感谢您的投入.我在一个较小的 PyGTK 程序中复制了这种情况,其中 Popen 可以正常工作.

@Sven Marnach, thanks for your inputs. I replicated the situation in a smaller PyGTK program, where Popen works just as it should.

Popen 没有理由在 PyGTK 应用程序中具有不同的行为.

There is no reason why Popen should have a different behaviour in a PyGTK app.

这意味着我正在做的其他事情造成了问题,一旦解决我会写下来.

Which means I am doing something else that is creating the problem, which I will write down once fixed.

#!/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 程序.

推荐答案

第一,我没有看到你在等待子进程完成.

First, I don't see that you wait for the child process to complete.

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

What is likely to happen here is that your pygtk starts a child process and exits right away, the python garbage collector destroys the Popen object.

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

When you run same code in python shell or some other long-running function, Popen gets more time and hopefully child process completes.

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

To quickly test if this is in fact the problem, try adding time.sleep(1) after Popen call.

您应该做的是在 Popen 对象上调用 .communicate() 以确保子进程执行其操作并终止.

What you should be doing is calling .communicate() on Popen object to make sure child process does its thing and terminates.

第二,我遇到过pygtk程序临时将工作目录更改为其他目录然后再​​将其更改回来的情况.

Second, I have come across cases when pygtk program temporarily changes working directory to something else and then changes it back.

要快速测试此案例,请尝试提供 /path/to/prog 以及 infile、outfile、redirect 等的完整路径.

To quickly test this case, try to supply full path both to /path/to/prog as well as infile, outfile, redirect, etc.

这篇关于为什么 Popen() 函数在 Python 和 PyGTK 中的行为不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆