Ich glaube, dies wurde bereits von anderen Benutzern vor mir beantwortet, daher füge ich es der Vollständigkeit halber hinzu: Die with
Anweisung vereinfacht die Ausnahmebehandlung, indem sie allgemeine Vorbereitungs- und Bereinigungsaufgaben in sogenannten Kontextmanagern kapselt . Weitere Details finden Sie in PEP 343 . Beispielsweise ist die open
Anweisung ein eigenständiger Kontextmanager, mit dem Sie eine Datei öffnen, geöffnet lassen können, solange sich die Ausführung im Kontext der with
Anweisung befindet, in der Sie sie verwendet haben, und sie schließen können, sobald Sie den Kontext verlassen. egal ob Sie es aufgrund einer Ausnahme oder während des regulären Kontrollflusses verlassen haben. Die with
Anweisung kann daher auf ähnliche Weise wie das RAII-Muster in C ++ verwendet werden: Einige Ressourcen werden von derwith
Anweisung und freigegeben, wenn Sie den with
Kontext verlassen .
Einige Beispiele sind: Öffnen von Dateien mit with open(filename) as fp:
, Erfassen von Sperren mit with lock:
(wo lock
ist eine Instanz von threading.Lock
). Sie können auch Ihre eigenen Kontextmanager mit dem contextmanager
Dekorator von erstellen contextlib
. Zum Beispiel benutze ich dies oft, wenn ich das aktuelle Verzeichnis vorübergehend ändern und dann dorthin zurückkehren muss, wo ich war:
from contextlib import contextmanager
import os
@contextmanager
def working_directory(path):
current_dir = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(current_dir)
with working_directory("data/stuff"):
# do something within data/stuff
# here I am back again in the original working directory
Hier ist ein weiteres Beispiel , das vorübergehend umleitet sys.stdin
, sys.stdout
und sys.stderr
zu einem anderen Datei - Handle und stellt sie wieder her später:
from contextlib import contextmanager
import sys
@contextmanager
def redirected(**kwds):
stream_names = ["stdin", "stdout", "stderr"]
old_streams = {}
try:
for sname in stream_names:
stream = kwds.get(sname, None)
if stream is not None and stream != getattr(sys, sname):
old_streams[sname] = getattr(sys, sname)
setattr(sys, sname, stream)
yield
finally:
for sname, stream in old_streams.iteritems():
setattr(sys, sname, stream)
with redirected(stdout=open("/tmp/log.txt", "w")):
# these print statements will go to /tmp/log.txt
print "Test entry 1"
print "Test entry 2"
# back to the normal stdout
print "Back to normal stdout again"
Und schließlich ein weiteres Beispiel, das einen temporären Ordner erstellt und beim Verlassen des Kontexts bereinigt:
from tempfile import mkdtemp
from shutil import rmtree
@contextmanager
def temporary_dir(*args, **kwds):
name = mkdtemp(*args, **kwds)
try:
yield name
finally:
shutil.rmtree(name)
with temporary_dir() as dirname:
# do whatever you want
with
in der Python 3-Dokumentation.