Python入門から応用までの学習サイト


コンテキストマネージャ

Pythonではwith文で前処理、後処理を行えるようにする場合、そのオブジェクトはコンテキストマネージャである必要があります。

次のように特殊メソッド「__enter__」「__exit__」を実装すれば、そればすでにコンテキストマネージャです。 「__enter__」の処理、「with」ブロックの処理、「__exit__」の処理が順に実行されます。

# -*- coding: utf-8 -*- 


class ContextManagerTest:

    def __enter__(self):
        print '__enter__'

    def __exit__(self, exc_type, exc_value, traceback):
        print '__exit__'


with ContextManagerTest():
    print 'with'

--実行結果--

__enter__
with
__exit__


「__exit__」の引数で渡される情報は例外発生時に活用できます。 ここでは「__exit__」の戻り値としてTrueを返していますが、この場合は例外が発生しても処理がストップすることはありません。そのまま処理を継続します。 Falseを返した場合は無視できないエラーとして、通常の例外のように処理がそこでストップします。

# -*- coding: utf-8 -*- 


class ContextManagerTest:

    def __enter__(self):
        print '__enter__'

    def __exit__(self, exc_type, exc_value, traceback):
        print '__exit__'
        print exc_type
        print exc_value
        print traceback
        return True


with ContextManagerTest():
    val = int('abc')

--実行結果--

__enter__
__exit__
<type 'exceptions.ValueError'>
invalid literal for int() with base 10: 'abc'
<traceback object at 0x0000000002A7E6C8>


asで渡されるオブジェクトは「__enter__」の戻り値で指定することができます。

# -*- coding: utf-8 -*- 


class ContextManagerTest:

    def __enter__(self):
        print '__enter__'
        return 'as obj'

    def __exit__(self, exc_type, exc_value, traceback):
        print '__exit__'


with ContextManagerTest() as as_obj:
    print as_obj

--実行結果--

__enter__
as obj
__exit__



こちらはデコレータを使用するやり方です。 より簡単にコンテキストマネージャを作成することができ、クラスだけではなく関数もコンテキストマネージャとすることができます。

# -*- coding: utf-8 -*- 

from contextlib import contextmanager


@contextmanager
def context_manager_test():
    print 'enter'
    yield
    print 'exit'


with context_manager_test():
    print 'with'

--実行結果--

enter
with
exit


asで渡されるオブジェクトは「yield」で指定することができます。

# -*- coding: utf-8 -*- 

from contextlib import contextmanager


@contextmanager
def context_manager_test():
    print 'enter'
    yield 'as_obj'
    print 'exit'


with context_manager_test() as as_obj:
    print as_obj

--実行結果--

__enter__
as obj
__exit__




Python
スタートブック


入門 Python 3


Effective
Python


退屈なことは
Pythonにやらせよう

 
 
 

関数で定義?デコレータで定義?

▶応用編:プロパティ



確かな力が身につく
Python「超」入門




P  R