[解決済み] sys.stdoutをログファイルに複製する方法は?
質問
Pythonアプリが多くのシステムコールを行っているときにロギングを行うための最良の方法は何でしょうか?
私のアプリには2つのモードがあります。 インタラクティブモードでは、システムコールからの出力を含め、すべての出力を画面とログファイルに出力したいと思います。 デーモン・モードでは、すべての出力はログに送られます。 デーモン・モードは
os.dup2()
. インタラクティブモードで、すべての出力をログに出力する方法は、システムコールの一つ一つを変更することなく、見つけることができません。
言い換えれば、私はpythonアプリによって生成されたすべての出力に対して、コマンドラインの'tee'の機能が欲しいのです。 システムコール出力を含む .
明確にするために
すべての出力をリダイレクトするために、私は次のようなことを行っています。
# open our log file
so = se = open("%s.log" % self.name, 'w', 0)
# re-open stdout without buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
# redirect stdout and stderr to the log file opened above
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
これの良いところは、他のコードから特別なプリントを呼び出す必要がないことです。 このコードではいくつかのシェルコマンドも実行しているので、それらの出力も個別に処理する必要がないのは良いことです。
単純に、同じことをしたいのですが、ただし 複製 リダイレクトではなく
最初は、単純に反転させると
dup2
が動作するはずです。 なぜ、うまくいかないのでしょうか? 以下は私のテストです。
import os, sys
### my broken solution:
so = se = open("a.log", 'w', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
os.dup2(sys.stdout.fileno(), so.fileno())
os.dup2(sys.stderr.fileno(), se.fileno())
###
print("foo bar")
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
ファイル "a.log" は、画面に表示されたものと同じである必要があります。
解決するには?
コードから外部プロセスを生成することに抵抗がないのであれば、このように
tee
そのものです。 と全く同じことをするUnixのシステムコールを私は知りません。
tee
が行う。
# Note this version was written circa Python 2.6, see below for
# an updated 3.3+-compatible version.
import subprocess, os, sys
# Unbuffer output (this ensures the output is in the correct order)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
print "\nstdout"
print >>sys.stderr, "stderr"
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
をエミュレートすることもできます。
tee
を使用して
マルチプロセシング
パッケージ(または
処理
は、Python 2.5以前を使用している場合)。
更新情報
Python 3.3+対応版はこちらです。
import subprocess, os, sys
tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
# Cause tee's stdin to get a copy of our stdin/stdout (as well as that
# of any child processes we spawn)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
# The flush flag is needed to guarantee these lines are written before
# the two spawned /bin/ls processes emit any output
print("\nstdout", flush=True)
print("stderr", file=sys.stderr, flush=True)
# These child processes' stdin/stdout are
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
関連
-
[解決済み】 AttributeError: モジュール 'matplotlib' には属性 'plot' がない。
-
[解決済み】cアンダースコア式`c_`は、具体的に何をするのですか?
-
[解決済み】Pythonのロガーがログファイルに加えて標準出力にも全メッセージを出力するようにする。
-
[解決済み] プログラムの実行やシステムコマンドの呼び出しはどのように行うのですか?
-
[解決済み] リストのリストからフラットなリストを作るには?
-
[解決済み] リストが空かどうかを確認するにはどうすればよいですか?
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] Pythonでファイルやフォルダを削除する方法は?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonを使って簡単なzipファイルの解凍パスワードを手作業で解く
-
Pythonコードの可読性を向上させるツール「pycodestyle」の使い方を詳しく解説します
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】インポートエラー。モジュール名 urllib2 がない
-
[解決済み】Python Error: "ValueError: need more than 1 value to unpack" (バリューエラー:解凍に1つ以上の値が必要です
-
[解決済み】LogisticRegression: Pythonでsklearnを使用して、未知のラベルタイプ: '連続'を使用しています。
-
[解決済み】ImportError: bs4という名前のモジュールがない(BeautifulSoup)
-
[解決済み】ValueError: xとyは同じサイズでなければならない
-
[解決済み] print関数の出力をフラッシュする(pythonの出力をバッファリング解除する)にはどうすればよいですか?
-
[解決済み] 出力バッファリング無効化