10

これは、特にその答えに関するhereからのフォローアップの質問です。


Python モジュールから、単に標準出力に出力するHello WorldHello World実行可能ファイルを呼び出しています。その出力をPythonにリダイレクトすることに興味があり、このStringIO回答に出くわしました。これにより、ほとんど解決策にたどり着きました。

この回答の重要な部分は、次のコード セグメントです。

1. def redirect_stdout():
2.     print "Redirecting stdout"
3.     sys.stdout.flush() # <--- important when redirecting to files
4.     newstdout = os.dup(1)
5.     devnull = os.open('/dev/null', os.O_WRONLY)
6.     os.dup2(devnull, 1)
7.     os.close(devnull)
8.     sys.stdout = os.fdopen(newstdout, 'w')

また、リダイレクト前の標準出力を復元したいと思います。

質問

  1. 上記の関数で正確に何が起こっているのでしょうか?
    • dupとは何dup2ですか?
    • とは/dev/null?
    • 8 行目は何をしているのですか? ( sys.stdout = os.fdopen(newstdout, 'w'))
  2. StringIOstdout をオブジェクトに保存するにはどうすればよいですか?
  3. Hello Worldプログラムを呼び出した後、stdout を復元するにはどうすればよいですか?

質問 1 の答えがわかれば、質問 2 と 3 の答えも簡単になると確信しています。とにかく投稿して、質問1の答えを自分の行きたい方向に押し進めることにしました。

4

3 に答える 3

13

redirect_stdout関数内で何が起こっているのかをより明確にするために、いくつかの追加コメントを以下に書きました。

def redirect_stdout():
    print "Redirecting stdout"
    sys.stdout.flush() # <--- important when redirecting to files

    # Duplicate stdout (file descriptor 1)
    # to a different file descriptor number
    newstdout = os.dup(1)

    # /dev/null is used just to discard what is being printed
    devnull = os.open('/dev/null', os.O_WRONLY)

    # Duplicate the file descriptor for /dev/null
    # and overwrite the value for stdout (file descriptor 1)
    os.dup2(devnull, 1)

    # Close devnull after duplication (no longer needed)
    os.close(devnull)

    # Use the original stdout to still be able
    # to print to stdout within python
    sys.stdout = os.fdopen(newstdout, 'w')

注意すべき重要な点の 1 つは、プロセスが起動時に OS から3 つの異なるファイル記述子を取得することです。

  • 標準入力: 0
  • 標準出力: 1
  • 標準エラー: 2

コメントで説明されているように、上記のコードは、stdout のファイル記述子とファイル記述子の複製関数を利用して、C コードをだまして別の stdout を使用させながら、Python コードで元の stdout への参照を維持して実行できるようにします。印刷する。

于 2012-01-10T14:47:26.547 に答える
7

/dev/nullは、ブラックホールのように書き込まれたすべてのものを飲み込む特別なデバイスファイルです(UNIXではすべてがファイルです!)。dupファイル記述子を複製します。Windowsに慣れている場合、UNIXのファイル記述子は開いているファイルを表す特別な整数であり、Windowsのファイルハンドルのようなものです。

プログラムは/dev/null書き込み用に開いており(のみ)、ファイル記述子のコピーを取り、開いているファイルを閉じています(UNIXがファイルに書き込むにはファイル記述子があれば十分なので、リソースを開いたままにする必要はありません)、次に、開いているファイルをに割り当てますsys.stdout

sysファイルシステムなど、あらゆる種類のシステム固有のリソースを表すPythonモジュールを覚えておいてください。したがって、UNIXではシステムストリームsys.stdoutを表します。/dev/stdoutSTDOUT

したがって、全体として、このコードはPythonをだまして考えさせます。/dev/null/つまり、STDOUTプログラムがステートメント(Python3の関数)を使用して書き込むたびに、実際に書き込みが行われ、結果のテキストがコンソールに表示されることはありません。 。STDOUTprint/dev/null

于 2012-01-10T14:46:31.150 に答える
-1

これらの Python 関数の基礎となる C ランタイム関数のマニュアル ページを参照してください。

基本的に、ファイル記述子を新しいファイル記述子 ( を使用dup()) または呼び出しで指定されたファイル記述子 ( を使用) に複製しますdup2()

于 2012-01-10T14:40:11.593 に答える