Условное использование менеджеров контекста обычно доставляет неудобства: нельзя просто разместить with внутри блока if, не заключив туда весь блок wi…
def print_whole_file(
*,
path: Optional[str] = None,
file_obj: Optional[TextIO] = None
):
assert path or file_obj
if path:
with open(path) as f:
print(f.read(), end='')
else:
print(file_obj.read(), end='')
Способ борьбы с этой проблемой — использовать ExitStack и вызывать enter_context внутри if:
def print_whole_file(
*,
path: Optional[str] = None,
file_obj: Optional[TextIO] = None
):
assert path or file_obj
with ExitStack() as stack:
if path:
file_obj = stack.enter_context(
open(path)
)
print(file_obj.read(), end='')
Однако более очевидный способ достичь того же — использовать тривиальные менеджеры контекста, которые ничего не делают, когда они не нужны, вместо «настоящих». Начиная с Python 3.7, их можно получить с помощью contextlib.nullcontext:
def print_whole_file(
*,
path: Optional[str] = None,
file_obj: Optional[TextIO] = None
):
assert path or file_obj
if path:
context = open(path)
else:
context = nullcontext(file_obj)
with context as f:
print(f.read(), end='')
👉 @BookPython