Python標準出力sys.stdoutリダイレクト
8266 ワード
本環境:Python 2.7
print(obj)ではなくprint objを使用する
いくつかの背景
sys.stdoutとprint
Pythonで印刷オブジェクトがprint objを呼び出すと、実際にsysが呼び出されます.stdout.write(obj+'')
printは必要な内容をコンソールに印刷し、改行を追加しました.
printはsysを呼び出すstdoutのwriteメソッド
次の2行は事実上等価です.
sys.stdinとraw_input
raw_を使うとInput('Input promption:')では、実際にプロンプト情報を出力し、入力をキャプチャします
次の2つのグループは事実上等価です.
コンソールからファイルにリダイレクト
元のsys.stdout指向コンソール
ファイルのオブジェクトの参照をsysに割り当てると.stdout、printが呼び出すのはファイルオブジェクトのwriteメソッドです
コンソールで何かを印刷したい場合は、元のコンソールオブジェクトリファレンスを保存し、ファイルに印刷してからsysを復元したほうがいいことを覚えておいてください.stdout
コンソールとファイルにリダイレクト
印刷したコンテンツをコンソールに出力し、ファイルをログとして保存したい場合は、どうすればいいですか?
印刷するとbufferがリフレッシュを解放するのではなく、印刷された内容をメモリに保持します.文字列領域に配置するとどうなりますか?
OK、上記のコードは正常に動作しません
エラーは明らかです.上で強調したようにsysを呼び出してみました.stdout.write()のとき、writeメソッドがないことに気づきました
また、ここで関数が見つからないのではなくattribute errorを提示するのは、pythonがオブジェクト/クラスの関数ポインタをオブジェクト/クラスの属性として記録しているためだと思いますが、関数のエントリアドレスが残っているだけです
それなら、リダイレクトしたオブジェクトにwriteメソッドを実装する必要があります.
同じだstderr, sys.stdinも複数のアドレスにリダイレクトできるので、一反三のことは自分で実践しましょう
print(obj)ではなくprint objを使用する
いくつかの背景
sys.stdoutとprint
Pythonで印刷オブジェクトがprint objを呼び出すと、実際にsysが呼び出されます.stdout.write(obj+'')
printは必要な内容をコンソールに印刷し、改行を追加しました.
printはsysを呼び出すstdoutのwriteメソッド
次の2行は事実上等価です.
sys.stdout.write('hello'+'
')
print 'hello'
sys.stdinとraw_input
raw_を使うとInput('Input promption:')では、実際にプロンプト情報を出力し、入力をキャプチャします
次の2つのグループは事実上等価です.
hi=raw_input('hello? ')
print 'hello? ', #comma to stay in the same line
hi=sys.stdin.readline()[:-1] # -1 to discard the '
' in input stream
コンソールからファイルにリダイレクト
元のsys.stdout指向コンソール
ファイルのオブジェクトの参照をsysに割り当てると.stdout、printが呼び出すのはファイルオブジェクトのwriteメソッドです
f_handler=open('out.log', 'w')
sys.stdout=f_handler
print 'hello'
# this hello can't be viewed on concole
# this hello is in file out.log
コンソールで何かを印刷したい場合は、元のコンソールオブジェクトリファレンスを保存し、ファイルに印刷してからsysを復元したほうがいいことを覚えておいてください.stdout
__console__=sys.stdout
# redirection start
# ...
# redirection end
sys.stdout=__console__
コンソールとファイルにリダイレクト
印刷したコンテンツをコンソールに出力し、ファイルをログとして保存したい場合は、どうすればいいですか?
印刷するとbufferがリフレッシュを解放するのではなく、印刷された内容をメモリに保持します.文字列領域に配置するとどうなりますか?
a=''
sys.stdout=a
print 'hello'
OK、上記のコードは正常に動作しません
Traceback (most recent call last):
File ".\hello.py", line xx, in <module>
print 'hello'
AttributeError: 'str' object has no attribute 'write'
エラーは明らかです.上で強調したようにsysを呼び出してみました.stdout.write()のとき、writeメソッドがないことに気づきました
また、ここで関数が見つからないのではなくattribute errorを提示するのは、pythonがオブジェクト/クラスの関数ポインタをオブジェクト/クラスの属性として記録しているためだと思いますが、関数のエントリアドレスが残っているだけです
それなら、リダイレクトしたオブジェクトにwriteメソッドを実装する必要があります.
import sys
class __redirection__:
def __init__(self):
self.buff=''
self.__console__=sys.stdout
def write(self, output_stream):
self.buff+=output_stream
def to_console(self):
sys.stdout=self.__console__
print self.buff
def to_file(self, file_path):
f=open(file_path,'w')
sys.stdout=f
print self.buff
f.close()
def flush(self):
self.buff=''
def reset(self):
sys.stdout=self.__console__
if __name__=="__main__":
# redirection
r_obj=__redirection__()
sys.stdout=r_obj
# get output stream
print 'hello'
print 'there'
# redirect to console
r_obj.to_console()
# redirect to file
r_obj.to_file('out.log')
# flush buffer
r_obj.flush()
# reset
r_obj.reset()
同じだstderr, sys.stdinも複数のアドレスにリダイレクトできるので、一反三のことは自分で実践しましょう