简体   繁体   English

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

[英]Why does the Popen() function behave differently in Python and PyGTK?

I wrote these two lines in a Python program and they worked fine:我在 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()

However these two lines of code do not work correctly in my PyGTK application.然而,这两行代码在我的 PyGTK 应用程序中不能正常工作。 I invoke these lines from a handler called on the "row-activated" signal of a TreeView widget.我从调用 TreeView 小部件的“行激活”信号的处理程序调用这些行。 Neither does prog write the outfile , nor do I get the output of prog1 in the output variable. prog也没有写入outfile ,我也没有在output变量中得到prog1的 output 。

What could be the problem?可能是什么问题呢?


@Sven Marnach, thanks for your inputs. @Sven Marnach,感谢您的投入。 I replicated the situation in a smaller PyGTK program, where Popen works just as it should.我在一个较小的 PyGTK 程序中复制了这种情况,其中 Popen 可以正常工作。

There is no reason why Popen should have a different behaviour in a PyGTK app. Popen 没有理由在 PyGTK 应用程序中具有不同的行为。

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()

Where,在哪里,

file:文件:

a cat
b bat
c mat

file1:文件1:

hello world

And the program anubadok is here . anubadok 程序就在这里

First , I don't see that you wait for the child process to complete.首先,我没有看到您等待子进程完成。

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.这里可能发生的是你的 pygtk 启动一个子进程并立即退出,python 垃圾收集器破坏了 Popen object。

When you run same code in python shell or some other long-running function, Popen gets more time and hopefully child process completes.当您在 python shell 或其他一些长时间运行的 function 中运行相同的代码时,Popen 会获得更多时间并希望子进程完成。

To quickly test if this is in fact the problem, try adding time.sleep(1) after Popen call.要快速测试这是否真的是问题所在,请尝试在 Popen 调用之后添加time.sleep(1)

What you should be doing is calling .communicate() on Popen object to make sure child process does its thing and terminates.您应该做的是在 Popen object 上调用 .communicate .communicate()以确保子进程执行其操作并终止。

Second , I have come across cases when pygtk program temporarily changes working directory to something else and then changes it back.其次,我遇到过 pygtk 程序临时将工作目录更改为其他目录然后将其更改回来的情况。

To quickly test this case, try to supply full path both to /path/to/prog as well as infile, outfile, redirect, etc.要快速测试这种情况,请尝试提供/path/to/prog以及 infile、outfile、redirect 等的完整路径。

The

OSError: [Errno 2] No such file or directory

is caused by your Popen call.是由您的 Popen 调用引起的。 Subprocess wants a list:子进程想要一个列表:

subprocess.Popen(["./prog","infile","outfile",">/dev/null"], cwd="/path/to/prog", stdout=subprocess.PIPE, shell=True)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么subprocess.popen的行为与单个语句不同? - Why does subprocess.popen behave differently as a single statement? 为什么 Python 对相同的函数(例如“sum”或“and”)表现不同? - Why does Python behave differently for the same function such as 'sum' or 'and'? 为什么 Python 3 for loop output 和行为不同? - Why does Python 3 for loop output and behave differently? 当类在函数中时,为什么类中的全局行为会有所不同? - why does global in a class behave differently when the class is within a function? 为什么 for 循环的行为与“pop” function 的 while 循环不同? - Why does the for loop behave differently than the while loop for the “pop” function? 为什么完全相同的 function 在 ipython/jupyter 中的行为不同? - Why does completely same function behave differently in ipython/jupyter? 为什么Python列表的行为会根据声明的不同而有所不同? - Why does Python list of lists behave differently depending on their declaration? 为什么Python **运算符在数组和标量上的行为不同 - Why does the Python ** operator behave differently on arrays and scalars 为什么这个argparse代码在Python 2和3之间表现不同? - Why does this argparse code behave differently between Python 2 and 3? Python 2-为什么“ with”在嵌入式C代码中表现不同? - python 2 - why does 'with' behave differently in embedded c code?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM