1. ホーム
  2. python

[解決済み] with open(...)`と`sys.stdout`の両方をうまく扱うには?

2022-10-21 19:22:58

質問

しばしば、データをファイルに出力したり、ファイルが指定されていない場合は標準出力に出力する必要があります。私は以下のスニペットを使用しています。

if target:
    with open(target, 'w') as h:
        h.write(content)
else:
    sys.stdout.write(content)

これを書き換えて、両方のターゲットを一律に扱いたい。

理想的な場合はそうなります。

with open(target, 'w') as h:
    h.write(content)

から離れるときに sys.stdout が閉じられるので、これはうまくいきません。 with ブロックから出るときにsys.stdoutが閉じられてしまうからです。私は

stdout = open(target, 'w')
...

というのは、元の標準出力に戻すのを忘れないようにする必要があるからです。

関連する

編集

を折り返すことができることは知っています。 target をラップしたり、別の関数を定義したり、あるいは コンテキストマネージャ . 私は5行以上を必要としない、シンプルでエレガントで慣用的なソリューションフィッティングを探しています。

どのように解決するのですか?

既成概念にとらわれない発想で、カスタムな open() メソッドはどうでしょうか?

import sys
import contextlib

@contextlib.contextmanager
def smart_open(filename=None):
    if filename and filename != '-':
        fh = open(filename, 'w')
    else:
        fh = sys.stdout

    try:
        yield fh
    finally:
        if fh is not sys.stdout:
            fh.close()

このように使います。

# For Python 2 you need this line
from __future__ import print_function

# writes to some_file
with smart_open('some_file') as fh:
    print('some output', file=fh)

# writes to stdout
with smart_open() as fh:
    print('some output', file=fh)

# writes to stdout
with smart_open('-') as fh:
    print('some output', file=fh)