Heim >Backend-Entwicklung >Python-Tutorial >Ausführliche Erklärung der Verwendung des Schlüsselworts with in Python
In diesem Artikel werden hauptsächlich relevante Informationen zur detaillierten Verwendung des Schlüsselworts with in Python vorgestellt. In Python ist das Schlüsselwort with eine gute Möglichkeit, die Implementierung von Kontextprotokollobjekten für Sie zu verwalten it Sie können auf Folgendes verweisen ">
In Python 2.5 wurde das Schlüsselwort with hinzugefügt. Es macht das häufig verwendete Muster try ... außer ... endlich ... Sehr praktisch Wiederverwendung. Schauen Sie sich das klassischste Beispiel an:
In diesem Code wird die Datei unabhängig davon, was während der Ausführung des Codeblocks passiert, irgendwann geschlossen Bei der Ausführung schließt das Programm die geöffnete Datei, bevor die Ausnahme ausgelöst wird. Sehen Sie sich vor dem Initiieren einer Datenbank einen ähnlichen Code an:with open('file.txt') as f: content = f.read()Wenn der Vorgang zum Initiieren einer Transaktionsanforderung geändert wird, um das Schlüsselwort with zu unterstützen, reicht ein Code wie dieser aus:
Der Ausführungsprozess von with wird ausführlich erläutert und der obige Code wird implementiert auf zwei gängige Arten.
db.begin() try: # do some actions except: db.rollback() raise finally: db.commit()
Der allgemeine Ausführungsprozess von with
with transaction(db): # do some actionsEin grundlegender mit
Ausdruck
, seine Struktur ist wie folgt:wobei: EXPR ein beliebiger Ausdruck sein kann; da VAR für seine allgemeine Ausführung optional ist. Der Prozess ist wie folgt:
Berechnen Sie EXPR und erhalten Sie einen Kontextmanager
with EXPR as VAR: BLOCKDie Methode „exit()“ des Kontextmanagers wird gespeichert.
Dieser Prozess hat mehrere Details:
mgr = (EXPR) exit = type(mgr).exit # 这里没有执行 value = type(mgr).enter(mgr) exc = True try: try: VAR = value # 如果有 as VAR BLOCK except: exc = False if not exit(mgr, *sys.exc_info()): raise finally: if exc: exit(mgr, None, None, None)Attribute
db und die für den Kontextmanager erforderlichen Methoden enter() und exit enthält () .
Nachdem man den Ausführungsprozess von with verstanden hat, ist diese Implementierung leicht zu verstehen. Die unten vorgestellte Implementierungsmethode ist viel komplizierter zu verstehen.
Generatoren
DekoratorenIn der Standardbibliothek von Python gibt es einen Dekorator, der über einen Generator einen Kontextmanager erhalten kann. Der Implementierungsprozess mithilfe des Generator-Dekorators ist wie folgt:
class transaction(object): def init(self, db): self.db = db def enter(self): self.db.begin() def exit(self, type, value, traceback): if type is None: db.commit() else: db.rollback()
Auf den ersten Blick ist diese Implementierung einfacher, ihr Mechanismus ist jedoch komplexer. Werfen wir einen Blick auf den Ausführungsprozess:
Nachdem der Python-Interpreter das Schlüsselwort yield erkennt, erstellt def eine Generator-Funktion , um die reguläre Funktion zu ersetzen (im (Klassendefinition: Ich verwende gerne Funktionen anstelle von Methoden).
from contextlib import contextmanager @contextmanager def transaction(db): db.begin() try: yield db except: db.rollback() raise else: db.commit()Der Decorator-Kontextmanager wird aufgerufen und gibt eine Hilfsmethode zurück, die nach dem Aufruf eine GeneratorContextManager-Instanz generiert. Schließlich ruft der EXPR im with-Ausdruck die vom Contentmanager-Dekorator zurückgegebene Hilfsfunktion auf. Der
with 表达式调用实例对象的上下文管理器的 enter() 方法。
enter() 方法中会调用这个生成器的 next() 方法。这时候,生成器方法会执行到 yield db 处停止,并将 db 作为 next() 的返回值。如果有 as VAR ,那么它将会被赋值给 VAR 。
with 中的 BLOCK 被执行。
BLOCK 执行结束后,调用上下文管理器的 exit() 方法。 exit() 方法会再次调用生成器的 next() 方法。如果发生 StopIteration 异常,则 pass 。
如果没有发生异常生成器方法将会执行 db.commit() ,否则会执行 db.rollback() 。
再次看看上述过程的代码大致实现:
def contextmanager(func): def helper(*args, **kwargs): return GeneratorContextManager(func(*args, **kwargs)) return helper class GeneratorContextManager(object): def init(self, gen): self.gen = gen def enter(self): try: return self.gen.next() except StopIteration: raise RuntimeError("generator didn't yield") def exit(self, type, value, traceback): if type is None: try: self.gen.next() except StopIteration: pass else: raise RuntimeError("generator didn't stop") else: try: self.gen.throw(type, value, traceback) raise RuntimeError("generator didn't stop after throw()") except StopIteration: return True except: if sys.exc_info()[1] is not value: raise
总结
Python的 with 表达式包含了很多Python特性。花点时间吃透 with 是一件非常值得的事情。
一些其他的例子
锁机制
@contextmanager def locked(lock): lock.acquired() try: yield finally: lock.release()
标准输出重定向
@contextmanager def stdout_redirect(new_stdout): old_stdout = sys.stdout sys.stdout = new_stdout try: yield finally: sys.stdout = old_stdout with open("file.txt", "w") as f: with stdout_redirect(f): print "hello world"
Das obige ist der detaillierte Inhalt vonAusführliche Erklärung der Verwendung des Schlüsselworts with in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!