Почему функция Popen () ведет себя по-разному в Python и PyGTK? - PullRequest
1 голос
/ 29 мая 2011

Я написал эти две строки в программе на 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 также не записывает выходной файл , и я не получаю вывод prog1 в переменную output .

В чем может быть проблема?


@ Свен Марнах, спасибо за ваш вклад.Я повторил ситуацию в меньшей программе 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()

Где,

file:

a cat
b bat
c mat

file1:

hello world

И программа anubadok здесь .

Ответы [ 2 ]

1 голос
/ 27 октября 2012

Сначала , я не вижу, чтобы вы ожидали завершения дочернего процесса.

Вероятно, здесь произойдет следующее: ваш pygtk запускает дочерний процесс и сразу же завершается, сборщик мусора python уничтожает объект Popen.

Когда вы запускаете тот же код в оболочке Python или другой длительной функции, Popen получает больше времени и, надеюсь, дочерний процесс завершается.

Чтобы быстро проверить, действительно ли это является проблемой, попробуйте добавить time.sleep(1) после вызова Popen.

То, что вы должны сделать, это вызвать .communicate() для объекта Popen, чтобы убедиться, что дочерний процесс выполняет свою работу и завершается.

Второй , я сталкивался со случаями, когда программа pygtk временно меняет рабочий каталог на что-то другое, а затем снова его меняет.

Чтобы быстро проверить этот случай, попробуйте указать полный путь как к /path/to/prog, так и к infile, outfile, redirect и т. Д.

0 голосов
/ 29 мая 2011

The

OSError: [Errno 2] No such file or directory

вызвано вашим звонком в Попен. Подпроцесс хочет список:

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