いろいろ備忘録日記

主に .NET とか Java とか Python絡みのメモを公開しています。

Pythonメモ-64 (contextlib.redirect_stdout) (stdoutの矛先を一時的に変更する, redirect_stderr)

概要

以前、contextlib.suppress についてメモしたのですが

devlights.hatenablog.com

contextlibモジュールさんには、他にも便利な関数が用意されていまして

結構個人的に利用しているのが、以下です。

contextlib.redirect_stdout

29.6. contextlib — with 文コンテキスト用ユーティリティ — Python 3.6.3 ドキュメント

この関数は何をしてくれるかというと、名前の通り一時的に標準出力つまり、sys.stdoutの出力先を変更してくれるコンテキストマネージャを返してくれます。

例えば、pythonでちょっとしたコマンドみたいなのを作っているとき、コマンドなので出力は標準出力にしておきたいのですが、それだとテストする際にちょっと面倒なので、テスト時はこの関数を使って出力値を StringIO などに変更しておくとあとで確認が簡単だという感じです。

使い方はめっちゃ簡単で、普通に

f = io.StringIO()
with contextlib.redirect_stdout(f):
    help(pow)

print(f.getvalue())

というふうに使います。上の例だと、help()は標準出力に結果を出力するので、そのまま呼び出すとコンソールに結果がその場で出力されるのですが、それを一時的に io.StringIOに入れているといった感じです。

サンプル

以下、サンプルです。

"""
contextlib モジュールについてのサンプルです。
contextlib.redirect_stdout について記載しています。
"""
import io
from contextlib import redirect_stdout

from trypython.common.commoncls import SampleBase
from trypython.common.commonfunc import pr


class Sample(SampleBase):
    def exec(self):
        """
        contextlib.redirect_stdout についてのサンプルを実行します。
        :return: なし
        """
        # ----------------------------------------------------------------------
        # contextlib.redirect_stdout(new_target)
        #
        # 一時的にsys.stdoutを指定した矛先に向けてくれるコンテキストマネージャ
        # 兄弟関数として、contextlib.redirect_stderr がある。こちらは sys.stderr用
        # ----------------------------------------------------------------------

        # 以下のprint関数は結果をprint関数で出力しているので
        # 通常だと、標準出力に出力されるが redirect_stdout で矛先を変更している
        f = io.StringIO()
        with redirect_stdout(f):
            Sample.tekito()

        pr('f', f.getvalue())

        # 同様に help() は、通常 stdout に結果を出力するが
        # redirect_stdout することで結果を StringIO に格納
        f.seek(io.SEEK_SET)
        with redirect_stdout(f):
            help(sum)
        pr('f', f.getvalue())

    @staticmethod
    def tekito(begin=0, end=10):
        for i in range(begin, end):
            print(i, end=',')


def go():
    """
    サンプルを実行します。
    :return: なし
    """
    obj = Sample()
    obj.exec()


if __name__ == '__main__':
    go()

try-python/contextlib02.py at master · devlights/try-python · GitHub

結果は以下のようになります。

f='0,1,2,3,4,5,6,7,8,9,'
f=('Help on built-in function sum in module builtins:\n'
 '\n'
 'sum(iterable, start=0, /)\n'
 "    Return the sum of a 'start' value (default: 0) plus an iterable of "
 'numbers\n'
 '    \n'
 '    When the iterable is empty, return the start value.\n'
 '    This function is intended specifically for use with numeric values and '
 'may\n'
 '    reject non-numeric types.\n'
 '\n')

過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。