with文とは
Pythonのwith文とは、
コードが 特別なcontext下で 実行されていることを示すのに使われてます。
良く使う例
ファイルを開いてデータを書き込む例。
with open('file.txt', 'w') as handle:
handle.write('some data')
ファイルにデータを書き込んだ後(withブロックを抜けた後)で、
ファイルのHanlderを閉じてくれます。
try/finally 構成でやると、こうなイメージになります。
try:
hanlder = open('file.txt', 'w')
handle.write('some data')
finally:
handler.close()
with構文をネスト
with open("sample1.txt", "r") as f1:
with open("sample2.txt", "w") as f2:
f2.write(f1.read())
with構文に対応したクラスを作ってみよう
with構文が使えるクラスを作成するには、
enter()メソッドと exit()メソッドの両方を定義しなければなりません。
# My with sample class
class MyWithSampleClass:
def __enter__(self):
print('START')
return self
def myfunc(self):
print('Do something...')
def __exit__(self, exception_type, exception_value, traceback):
print('END')
with MyWithSampleClass() as c:
c.myfunc()
with構文に対応した関数を作ってみよう
-
__enter__
と__exit__
を書きたくない - クラスを作りたくない
そうな時には、 contextlibモジュール の contextmanager デコレータを使います。
例えば、あるフォルダーに入り処理を行ったあとにまた入る前のディレクトリに切り替えたい
ユースケースがあるとします。
cwd = os.getcwd()
os.chdir('/tmp/foo')
try:
run() # 何か処理
finally:
os.chdir(cwd)
withで使えるように次のようなcdを実装して:
@contextlib.contextmanager
def cd(target_dir):
cwd = os.getcwd()
try:
os.chdir(target_dir)
yield
finally:
os.chdir(cwd)
以下のように使えます:
with cd('/tmp/foo'):
run() # 何か処理
まとめ
- 定型処理にwithを使うことでコードが簡潔化
- ネストも可能で複雑な処理がさらに見やすくなる
- with構文に対応したクラスも関数も