[英]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.