Es gibt keinen direkten Weg, soweit ich weiß. Sie können jedoch ein boolesches Flag verwenden, um zu überprüfen, ob __enter__
aufgerufen wurde, bevor die tatsächlichen Methoden in den Objekten aufgerufen wurden.
class MyContextManager(object):
def __init__(self):
self.__is_context_manager = False
def __enter__(self):
print "Entered"
self.__is_context_manager = True
return self
def __exit__(self, exc_type, exc_value, traceback):
print "Exited"
def do_something(self):
if not self.__is_context_manager:
raise Exception("MyContextManager should be used only with `with`")
print "I don't know what I am doing"
Wenn Sie es mit with
verwenden,
with MyContextManager() as y:
y.do_something()
Sie
Entered
I don't know what I am doing
Exited
bekommen Aber, wenn Sie manuell ein Objekt erstellen, und rufen Sie do_something
,
x = MyContextManager()
x.do_something()
Sie
Traceback (most recent call last):
File "/home/thefourtheye/Desktop/Test.py", line 22, in <module>
x.do_something()
File "/home/thefourtheye/Desktop/Test.py", line 16, in do_something
raise Exception("MyContextManager should be used only with `with`")
Exception: MyContextManager should be used only with `with`
Hinweis bekommen: Dies ist keine feste Lösung. Jemand kann die Methode __enter__
direkt aufrufen, bevor andere Methoden aufgerufen werden, und die Methode __exit__
wird in diesem Fall möglicherweise nie aufgerufen.
Wenn Sie nicht, dass der Check in jeder Funktion wiederholen möchten, können Sie es ein Dekorateur machen, wie diese
class MyContextManager(object):
def __init__(self):
self.__is_context_manager = False
def __enter__(self):
print "Entered"
self.__is_context_manager = True
return self
def __exit__(self, exc_type, exc_value, traceback):
print "Exited"
def ensure_context_manager(func):
def inner_function(self, *args, **kwargs):
if not self.__is_context_manager:
raise Exception("This object should be used only with `with`")
return func(self, *args, **kwargs)
return inner_function
@ensure_context_manager
def do_something(self):
print "I don't know what I am doing"
Und ** warum im Himmel Name ** würden Sie jemals das tun wollen? 'x = X()', 'mit x als Ergebnis_des_Eingebens:' (Erstellen des CM und dessen Verwendung in zwei separaten Zeilen) ist plötzlich kein gültiger Usecase mehr? Was wäre, wenn ich Kontextmanager in einem Mapping speichern möchte, um sie dynamisch auszuwählen? –
Und was, wenn ich ein ['contextlib.ExitStack()'] (https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack) verwenden möchte? mehrere Kontextmanager kombinieren? Es gibt verschiedene gute Anwendungsfälle, in denen ein Kontextmanager außerhalb einer 'with'-Anweisung erstellt wird, die Sie verhindern möchten. Versuchen Sie nicht, alle möglichen Programmierfehler auf Kosten des Programmierers zu beheben, die wissen, was sie tun. –