以下のクラスは、print(正確には sys.stdout)に送られてくる文字列を別 IO に取り込むクラスです。クラスは __enter__() と __exit__() のみから成り、with文で使われることが前提となっています。
import sys import io class PrintHack(object): def __enter__(self): # sys.stdoutをio.StringIOに置き換え self.__sio = io.StringIO() self.__tmp, sys.stdout = sys.stdout, self.__sio return self.__sio def __exit__(self, exc_type, exc_value, traceback): # sys.stdoutを元に戻す sys.stdout = self.__tmp
使い方は以下のようになります。
まず with文で PrintHack クラスを呼び出します。すると、with のスコープの中で呼ばれた print の内容は、標準出力には出力されず、PrintHack が持つ IO に取り込まれるようになります。取り込まれた内容は、IO の getvalue() で確認することができます。
このクラスの主な使い道は、テストプログラムにおいて標準出力の内容を確認する、となるはずです。
# with文でPrintHackを呼び出す >>> with PrintHack() as hack: ... print('Hello hack') ... >>> # ここではprintされない # with内のprintの内容を確認 >>> hack.getvalue() 'Hello hack\n' # with外では通常のprint >>> print('Not hacked') Not hacked
sys.stdout は文字通り標準の出力ですので、基本的にはデフォルトから変更を加えたくないものです。sys.stdout に加えた変更が間違って残ってしまうと、プログラムの他の箇所で予期せぬ問題が発生する恐れがあります。
with文専用のクラスを作ることで、影響範囲を with スコープの中に限定することができました。これは堅牢性の観点から非常に重要です。
また、仮にこのクラスが with文以外で呼ばれた場合、このクラスは何の動作もしません。with文以外では動作しないようにすることで、間違った使い方を未然に防ぐことができます。
0 件のコメント:
コメントを投稿