2002年01月03日(木) 2002年だ
■ 会社
- 17:55 わーい。今年は午年。牛ではない。
- おれの席の左の壁に掛かっている時計が指している時刻がおかしい。もう電池が無いのであろう。
- たまっていたメイルは186通。一番はやっぱりJavaHouse Brewersで67通。たいしたことないね。
- SFAのバックアップはちゃんととれているようだ。よかったよかった。
- 本所に行ってこようかな。
- 18:40 本所から帰ってきた。本所のロビーには横綱の酒樽みたいのが置いてあるのだ。
- Netscape4.7ではURLに「Javascript:」を指定するとJavascript Consoleが表示されるのね。fj.comp.lang.javascriptより。これすぐ忘れるのでメモ。
- CFSETTINGを使えば余分な空白の出力を抑制できるんじゃん。
- encript()を使えば暗号化ができるんじゃん。暗号化のアルゴリズムは不明だ。CFusion_Encrypt()というのもあるらしい。よーわからん。
- 20:05 メイル読み終わった。えらくたくさんメモってしまった。
- 22:20 CLIEの設定をしていたらえらい時間をくってしまった。まだジョクダイアルの使い方がよくわからない。PiloWebを使うかPalmscapeを使うか悩むな。早く帰らないと。
■ [soft][unix] The Advanced Maryland Automatic Network Disk Archiver
テープによる集中バックアップをサポートするツールらしいAMANDA。fj.os.bsd.freebsdより。よくわからないけど。
■ [link] 週刊ファッション情報
ファッションに関するページ。
■ 中途半端なスキルでは必ず失敗する
おれはスキル無いから転職は難しいな。ちぇ。PCDN News Letterより。
■ テレビ
- 気分は上々の総集編みたいなやつ。郷ひろみが南原勝俣YOUと温泉へ行くやつとか。YOU楽しくて好きかも。でも60点だな。
2004年01月03日(土)
2023年01月03日(火)
■ [python] with文とコンテキストマネージャとcontextlib
Pythonのコンテキストマネージャはすぐにわからなくなってしまうのでメモ。コンテキストマネージャをうまく使えばある種のコードが簡潔に書けるようになる。
なお、関連してasync withや非同期コンテキストマネージャもあるがここでは触れない。
with文
with文を使うことで、そこで指定したコンテキストマネージャの __enter__() と __exit__() を暗黙的に呼び出すことができる。
次のドキュメントできちんと説明されているので、わからなくなったらここを読むのがいい。
- 8.5. with 文 (docs.python.org)
class C: def __enter__(self): print("enter") def __exit__(self, exc_type, exc_value, exc_tb): print("exit") with C(): print("hello") raise RuntimeError()
enter hello exit Traceback (most recent call last): File "/home/kenichi/work/python/context_manager.py", line 10, in <module> raise RuntimeError() RuntimeError
with文のブロック内で例外が投げられたときに C.__exit__() が呼ばれることが重要だ。同じことはtry/finallyで実現できるが、with文を使うとより簡潔に書けるようになる。
コンテキストマネージャ
上述のCクラスのように __enter__() と __exit__() を持つクラスがコンテキストマネージャだ。
- コンテキストマネージャ型 (docs.python.org)
__enter__()は戻り値を返すことができ、それはwith文のas節で受け取ることができる。
__exit__()の方は例外を意識する必要がある。
- 戻り値で真を返すとwith文のブロック内で投げられた例外がwith文の外へ伝播しなくなる。
- with文のブロックで例外が投げられると、その情報を引数のexc_type, exc_value, exc_tbで受け取る。
contextlib
contextlibモジュールにてwith文用のユーティリティが提供されている。
@contextmanager
@contextmanagerはコンテキストマネージャを関数で定義できるようになるデコレータだ。先の例と同じものを次のように書くことができる。
import contextlib from collections.abc import Iterator @contextlib.contextmanager def f() -> Iterator[None]: print("enter") try: yield finally: print("exit") with f(): print("hello") raise RuntimeError()
f()には型ヒントを付けたが、@contextmanagerで修飾する関数はIteratorを返す必要がある。yieldで渡した値がwith文のas節に渡される(上の例には無いけど)。
また、@contextmanagerで作ったコンテキストマネージャは自動的にデコレータにもなり、次のように使えるようになる。
@f() def g(): print("world") g()
enter world exit
組み込みのコンテキストマネージャ
contextlibでは色々なコンテキストマネージャを用意してくれている。
- closing
- 指定したオブジェクトのclose()を自動的に呼び出してくれる。
- nullcontext
- 何もしないコンテキストマネージャ?
- suppress
- 指定した例外を捨てる。
- redirect_stdout
- 標準出力を一時的に指定先へリダイレクトする。
- redirect_stderr
- 標準エラー出力を一時的に指定先へリダイレクトする。
- chdir
- カレントディレクトリを一時的に変更する。
- ExitStack
- コンテキストマネージャや関数を登録することで複数の後処理を行えるようにする。