これはhereからのフォローアップの質問です。
行きたいところ
Pythonがまだ標準出力に出力できる間に、標準出力を一時ファイルに一時的にリダイレクトできるようにしたいと考えています。これには、次の手順が含まれます。
- stdout のコピーを作成します (
new
) - 一時ファイルを作成する (
tmp
) - stdout をリダイレクトする
tmp
new
stdout として使用するように Python に指示するtmp
「実際の」stdout にリダイレクトする- 「本物の」stdout を再度使用するように Python に指示します。
- 読んで閉じる
tmp
実装
上記を次の方法で実装しようとしました。
import os
import subprocess
import sys
#A function that calls an external process to print to stdout as well as
#a python print to pythons stdout.
def Func(s, p = False):
subprocess.call('echo "{0}"'.format(s), shell = True)
if p:
print "print"
sil = list() # <-- Some list to store the content of the temp files
print "0.1" # Some testing of the
Func("0.2") # functionality
new = os.dup(1) # Create a copy of stdout (new)
tmp = os.tmpfile() # Create a temp file (tmp)
os.dup2(tmp.fileno(), 1) # Redirect stdout into tmp
sys.stdout = os.fdopen(new, 'w', 0) # Tell python to use new as stdout
Func("0.3", True) # <--- This should print "0.3" to the temp file and "print" to stdout
os.dup2(new, 1) # Redirect tmp into "real" stdout
sys.stdout = os.fdopen(1, 'w', 0) # Tell python to use "real" stdout again
# Read and close tmp
tmp.flush()
tmp.seek(0, os.SEEK_SET)
sil.append(tmp.read())
tmp.close()
ここで少し休憩してまとめたいと思います。
ここまでのコンソールへの出力は次のようになります。
0.1
0.2
print
whilesil
次のようになります['0.3\n']
。したがって、ここまですべてが魔法のように機能しています。ただし、上記のスクリプトをもう一度やり直すと、次のようになります。
print "1.1" # Some testing of the
Func("1.2") # functionality
new = os.dup(1) # Create a copy of stdout (new)
tmp = os.tmpfile() # Create a temp file (tmp)
os.dup2(tmp.fileno(), 1) # Redirect stdout into tmp
sys.stdout = os.fdopen(new, 'w', 0) # Tell python to use new as stdout
# This should print "0.3" to the temp file and "print" to stdout and is the crucial point!
Func("1.3", True)
os.dup2(new, 1) # Redirect tmp into "real" stdout
sys.stdout = os.fdopen(1, 'w', 0) # Tell python to use "real" stdout again
# Read and close tmp
tmp.flush()
tmp.seek(0, os.SEEK_SET)
sil.append(tmp.read())
エラーが発生し、出力は次のようになります。
1.1
1.2
/bin/sh: line 0: echo: write error: Bad file descriptor
print
whilesil
読み取り: ['0.3\n', '']
.
つまり、2 番目Func("1.3", True)
は一時ファイルに書き込むことができません。
質問
- まず、スクリプトが動作したいように動作しない理由を知りたいです。つまり、一時ファイルへの書き込みがスクリプトの前半でしかできないのはなぜですか?
dup
との使い方にはまだ少し戸惑っていますdup2
。stdout の一時ファイルへのリダイレクトがどのように機能しているかは理解していると思いますが、なぜos.dup2(new, 1)
それが何をしているのかが完全にわかりました。おそらく、答えは、スクリプト内のすべてのdup
anddup2
s が何をしているのかについて詳しく説明できるかもしれません^^