2015-05-24 8 views
6

Verwendung Wenn mit geöffneten Dateien handelt, hat Python die with Syntax, die die Datei stellt sicher schließt, wenn der Block verlassen - unabhängig von Ausnahmen usw.Ausnahmebehandlung, wenn Python subprocess.Popen

with open('foo.txt') as f: 
    foo = f.read() 

Da Prozesse Ressourcen sind auch Ich frage mich: Ist etwas Ähnliches möglich oder empfohlen, wenn Popen verwendet wird? Zum Beispiel, sollte Popen.kill(); Popen.communicate() in einem finally -Klausel ausgeführt werden - vorausgesetzt, dass es mir nichts ausmacht zu blockieren, bis der Prozess abgeschlossen ist?

+1

Wenn Sie eine Version vor Python 3.2 ausgeführt wurden. Sie könnten einfach eine Klasse mit den magischen Methoden '__enter__' und' __exit__' definieren, um 'with' zu verwenden. –

Antwort

6

Ab Python 3.2 Popen ist ein Kontextmanager.

vom docs:

Popen Objekte werden als Kontext-Manager über die mit Aussage unterstützt: beim Beenden, Standarddateibeschreibungen sind geschlossen, und der Prozess gewartet.

Dies sollte ziemlich genau das tun, was Sie wollen.

Dies ist der relevante Teil von subprocess.py aus dem Standard-lib in Python 3.4:

def __enter__(self): 
    return self 

def __exit__(self, type, value, traceback): 
    if self.stdout: 
     self.stdout.close() 
    if self.stderr: 
     self.stderr.close() 
    if self.stdin: 
     self.stdin.close() 
    # Wait for the process to terminate, to avoid zombies. 
    self.wait() 

Jetzt sind Sie in Python tun 2,7

from subprocess import Popen 

class MyPopen(Popen): 

    def __enter__(self): 
     return self 

    def __exit__(self, type, value, traceback): 
     if self.stdout: 
      self.stdout.close() 
     if self.stderr: 
      self.stderr.close() 
     if self.stdin: 
      self.stdin.close() 
     # Wait for the process to terminate, to avoid zombies. 
     self.wait() 

if __name__ == '__main__': 
    with MyPopen(['ls']) as p: 
     print(p) 
+0

OK, cool. Es klingt also, als wäre es keine schlechte Idee, es auch in Python 2.7 zu machen, indem ich "try ... finally" verwende. – z0r

+0

Ich habe eine Python 2.7-Version hinzugefügt, indem ich den Code von Python 3.4 kopiert habe. Brauche vielleicht einige Tests. ;) –

+1

@ z0r: es gibt 'subprocess32' Modul, das Sie auf Python 2.7 installieren können (es bietet auch andere Verbesserungen. Obwohl es möglicherweise nicht auf Nicht-POSIX-Systemen funktioniert). – jfs

2

Sie können einen nur zwei benutzerdefinierte Methoden hinzufügen Klasse zur Implementierung der Comptability mit with Anweisung.

class CustomObject(object): 
    def __enter__(self): 
     """ This method execudes when entering block. """ 
     return thing_you_want_to_use 

    def __exit__(self, type, value, traceback): 
     """ This method execudes on block exit. """ 
     # Tear things down. 
3

Für 2.7 können Sie auch die @contextlib.contextmanager verwenden:

import contextlib 

@contextlib.contextmanager 
def manage_process(process): 
    try: 
     yield process 
    finally: 
     for stream in [process.stdout, process.stdin, process.stderr]: 
      if stream: 
       stream.close() 
     process.wait() 

z:

with manage_process(Popen(['ls'])) as p: 
    print(p) 
Verwandte Themen