The Python standard library contextlib.ExitStack class allows you to manage multiple context managers [^ cm] at once. The advantages of the ExitStack class are listed below.
--Since the ExitStack class is also a context manager, you can specify the scope with with statement.
--Register the context manager included in the instance variable of the class with the __init__
method. Can be managed collectively.
--You can control the call of the __enter__
method by properly using the push
method and the ʻenter_context` method.
push
method and ʻenter_context` methodThe push
method does not call the managed __enter__
method, and the ʻenter_context method calls the managed
enter method. Normally, using the ʻenter_context
method is fine.
from contextlib import ExitStack
class TestClass:
def __init__(self):
print("TestClass.__init__()")
def __enter__(self):
print("TestClass.__enter__()")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("TestClass.__exit__()")
with ExitStack() as stack:
stack.push(TestClass())
# TestClass.__init__()
# TestClass.__exit__()
with ExitStack() as stack:
stack.enter_context(TestClass())
# TestClass.__init__()
# TestClass.__enter__()
# TestClass.__exit__()
built-in function and manage them with ʻExitStack
.It is not overused due to the problem of handle resource management, but you can open and manage the files in the directory at once by combining the ʻExitStack and
with` statements.
import os
from contextlib import ExitStack
from typing import List, BinaryIO
#Create / start an ExitStack object with the with statement.
with ExitStack() as stack:
#Get the path of the file in the current directory.
#Exclude directories as the open built-in function fails.
paths: List[str] = [path for path in os.listdir(".") if os.path.isfile(path)]
#Open while adding the file to ExitStack.
files: List[BinaryIO] = [stack.enter_context(open(path, "rb")) for path in paths]
#Process the opened file appropriately.
file: BinaryIO
for file in files:
print(",".join([hex(byte).ljust(2, "0") for byte in file.read(5)]))
#The context manager registered in the ExitStack object (stack)
#Released at the end of the with statement.
--You can use the release process for asynchronous context manager in contextlib.AsyncExitStack
class.
[^ cm]: Context manager: An object that implements the __enter__
and __exit__
methods. Reference: Official documentation.
Recommended Posts