前書き
何の気なしにPythonのドキュメントを眺めていると、次のような記述があった。
try 文は、ひとまとめの文に対して、例外処理および/またはクリーンアップコードを指定します ...[中略]... 例外が as target を使って代入されたとき、それは except 節の終わりに消去されます。これはちょうど、以下のコード:
except E as N:
foo
> が、以下のコードに翻訳されたかのようなものです:
> ```python
except E as N:
try:
foo
finally:
del N
引用元:Python 言語リファレンス » 複合文 » try 文 、太字は引用者。
試してみる
実際に試してみると、なるほど確かにeが削除されているのが分かる。
>>> try:
... raise Exception('spam')
... except Exception as e:
... print(e)
...
spam
>>> print(e)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'e' is not defined
一方、with文ではそのような挙動を見せないので、なんとも解し難い。
>>> with open(r'./spam.txt') as fin:
... pass
...
>>> fin.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.
リソースのクローズを伴うので、同じように削除してくれた方が扱いやすいような...
ハマるとしたら
知っておいて得な挙動でもないが、ともすれば次のようなハマり方をするかもしれない。
>>> e = 42
>>> try:
... raise Exception('spam')
... except Exception as e:
... print(e)
...
spam
>>> print(e)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'e' is not defined
変数名を被らせた本人が悪いのは言うまでもないが、
勝手にオブジェクトが消されてしまうのは見落としがちなような気もする。