Wie kann ich eine Datei in ihrem Standardprogramm starten und dann schließen, wenn das Skript beendet ist?

Zusammenfassung

Ich habe wxPython GUI, die dem Benutzer erlaubt, Dateien zu sehen, um zu sehen. Derzeit mache ich das mit os.startfile() . Allerdings bin ich gekommen, um zu erfahren, dass dies nicht die beste Methode ist, also suche ich mich zu verbessern. Der Hauptnachteil von startfile() ist, dass ich keine Kontrolle über die Datei habe, sobald sie gestartet wurde. Dies bedeutet, dass ein Benutzer eine Datei offen lassen könnte, so dass es für einen anderen Benutzer nicht verfügbar wäre.

Was ich suche

In meiner GUI ist es möglich, Kinderfenster zu haben. Ich behalte all diese, indem ich die GUI-Objekte in einer Liste speichert, dann, wenn das Elternteil geschlossen ist, gehe ich einfach durch die Liste und schließe alle Kinder. Ich möchte das gleiche mit jeder Datei machen, die der Benutzer auswählt. Wie kann ich eine Datei starten und ein Python-Objekt beibehalten, damit ich es auf Befehl schließen kann? Danke im Voraus

Meine Träume von einer Lösung

  • Starten Sie die Datei so, dass es ein Python-Objekt gibt, das ich zwischen den Funktionen übergeben kann
  • Eine Möglichkeit, eine Datei in ihrem Standardprogramm zu starten und die PID zurückzugeben
  • Eine Möglichkeit, die PID mit dem Dateinamen abzurufen

Fortschritt so weit

Hier ist der Rahmen, den ich planen. Die wichtigen Bits sind die run() und end() Funktionen der FileThread Klasse, da hier die Lösung geht.

 import wx from wx.lib.scrolledpanel import ScrolledPanel import threading import os class GUI(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, 'Hey, a GUI!', size=(300,300)) self.panel = ScrolledPanel(parent=self, id=-1) self.panel.SetupScrolling() self.Bind(wx.EVT_CLOSE, self.OnClose) self.openFiles = [] self.openBtn = wx.Button(self.panel, -1, "Open a File") self.pollBtn = wx.Button(self.panel, -1, "Poll") self.Bind(wx.EVT_BUTTON, self.OnOpen, self.openBtn) self.Bind(wx.EVT_BUTTON, self.OnPoll, self.pollBtn) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add((20,20), 1) vbox.Add(self.openBtn) vbox.Add((20,20), 1) vbox.Add(self.pollBtn) vbox.Add((20,20), 1) hbox = wx.BoxSizer(wx.HORIZONTAL) hbox.Add(vbox, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 10) self.panel.SetSizer(hbox) self.panel.Layout() def OnOpen(self, event): fileName = "AFileIWantToOpenWithTheFullPath.txt" self.openFiles.append(FileThread(fileName)) def OnPoll(self, event): self.openFiles[0].Poll() def OnClose(self, event): for file in self.openFiles: file.end() self.openFiles.remove(file) self.Destroy() class FileThread(threading.Thread): def __init__(self, file): threading.Thread.__init__(self) self.file = file self.start() def run(self): doc = subprocess.Popen(["start", " /MAX", "/WAIT", self.file], shell=True) return doc def Poll(self): print "polling" print self.doc.poll() print self.doc.pid def end(self): try: print "killing file {}".format(self.file) except: print "file has already been killed" def main(): app = wx.PySimpleApp() gui = GUI() gui.Show() app.MainLoop() if __name__ == "__main__": main() 

Einige zusätzliche Hinweise

  • Ich bin nicht mit Portabilität beschäftigt, das wird nur auf ein paar kontrollierten Computern rund um das Büro laufen
  • Ich glaube nicht, dass das wichtig ist, aber ich pythonw die pythonw ausführbare Datei durch eine Batch-Datei

Aktualisieren

Ich spielte ein bisschen mit subprocess.Popen() , aber lief in das gleiche Problem. Ich kann das Popen Objekt mit machen

 doc = subprocess.Popen(["start", "Full\\Path\\to\\File.txt"], shell=True) 

Aber wenn ich poll() das Objekt, es immer wieder 0 . Die Docs sagen, dass A None value indicates that the process hasn't terminated yet so dass die 0 bedeutet, dass mein Prozess beendet ist. Also, versucht zu kill() es tut nichts.

Ich vermute dies, weil der Prozess abgeschlossen ist, wenn der Startbefehl beendet ist und die Datei gestartet wird. Ich möchte etwas, das auch nach dem Starten der Datei weitergehen wird, kann dies mit Popen() ?

One Solution collect form web for “Wie kann ich eine Datei in ihrem Standardprogramm starten und dann schließen, wenn das Skript beendet ist?”

Das Problem liegt in der Tatsache, dass der Prozess, der von der Popen Klasse in Ihrem Fall behandelt wird, der start Shell-Befehlsprozeß ist, der gerade nach dem Ausführen der Anwendung, die mit dem gegebenen Dateityp verknüpft ist, beendet wird. Die Lösung besteht darin, das /WAIT Flag für den /WAIT zu verwenden, so dass der start wartet, dass sein Kind beendet wird. Dann können Sie mit dem Beispiel das psutil Modul auch mit der folgenden Reihenfolge erreichen:

 >>> import psutil >>> import subprocess >>> doc = subprocess.Popen(["start", "/WAIT", "file.pdf"], shell=True) >>> doc.poll() >>> psutil.Process(doc.pid).get_children()[0].kill() >>> doc.poll() 0 >>> 

Nach der dritten Zeile erscheint Adobe Reader mit geöffneter Datei. poll gibt None , solange das Fenster dank der /WAIT Flagge geöffnet ist. Nach dem Töten des start -Kindes verschwindet das Adobe Reader-Fenster.

Andere vermutlich mögliche Lösung wäre, die Anwendung zu finden, die mit dem gegebenen Dateityp in der Registry verknüpft ist, und es ohne Verwendung von start und shell=True ausführen.

Ich habe dies auf 32-Bit-Python 2.7.5 auf 64-Bit-Windows Vista und 32-Bit-Python 2.7.2 auf 64-Bit-Windows 7 getestet. Unten ist ein Beispiel auf der letzteren laufen. Ich habe einige einfache Anpassungen an Ihren Code gemacht – mit einem Freihand roten Kreisen markiert (!).

Schritt 1Schritt 2Schritt 3Schritt 4

Auch ist es möglich, diesen Kommentar aus der Dokumentation zu betrachten :

Das Shell-Argument (das standardmäßig auf False gesetzt ist) gibt an, ob die Shell als Programm ausgeführt werden soll. Wenn Shell True ist, empfiehlt es sich, args als String und nicht als Sequenz zu übergeben.

Und führen Sie den Prozess wie folgt aus:

 subprocess.Popen("start /WAIT " + self.file, shell=True) 
  • Das Erstellen von LLVM schlägt mit leerer Fehlermeldung fehl
  • Installieren von pyaudio auf AMD64 von .exe
  • Wie kann ich auf ein Remote-Dateisystem mit Python unter Windows zugreifen?
  • Ich versuche zu verstehen, warum ich bekomme einen "Permission Denied" Fehler bei der Verwendung von paramiko 1.7.6
  • Excel-Arbeitsmappe mit Python drucken
  • Setzen Sie die Python-Terminal-Codierung unter Windows
  • Python 2.6 unter Windows: wie man subprocess.Popen mit "shell = True" Argument beenden?
  • Installieren von PygraphViz unter Windows, Python 2.6
  • Unterproikation.PIPE kann nicht auf Windows verarbeitet werden
  • Windows Scipy Install: Keine Lapack / Blas Ressourcen gefunden
  • Python - Testverzeichnis Berechtigungen
  • Python ist die beste Programmiersprache der Welt.