web-dev-qa-db-ja.com

open()の整数ファイル記述子 "0"-Python 3

Python 3では、次の形式で 「整数ファイル記述子」を使用してファイルオブジェクトを開く ことが可能です。

_stdout = open(1, "w")
stdout.write("Hello World") # Prints Hello World
stdout.close()
_

興味深いことに、_0_も有効なストリームであることがわかりました。

これをファイル_testio.py_に入れると:

_stdout = open(0, "w")
stdout.write("Foo Bar\n")
stdout.close()
_

そして、そのコードを実行すると、出力は次のようになります。

_bash-3.2$ python3 testio.py
Foo Bar
_

これはstdoutのように見えます。しかしながら...

_bash-3.2$ python3 testio.py > testio.txt
Foo Bar
bash-3.2$ cat testio.txt
_

したがって、これは実際にはstdoutではなく、別のもののようです。また、stderrでもないようです。

_bash-3.2$ python3 testio.py 2> testio.txt
Foo Bar
bash-3.2$ cat testio.txt
_

ただし、出力は_0>_を使用してリダイレクトできることがわかりました。

_bash-3.2$ python3 testio.py 0> testio.txt
bash-3.2$ cat testio.txt
Foo Bar
_

だから私の質問は、open(0, "w")の期限は正確には何ですか?そして、リダイレクトされているこの「0>」ストリームは何ですか?

Python 3.6.5
Bash 3.2

8
The Matt

特別なファイル記述子(FD)番号はありません。 FD 0のstdin、FD 1のstdout、およびFD2のstderrは単なる慣例です。

ログインすると、関連する端末デバイスがこれらのFDに「接続」されます。コマンドを実行すると、リダイレクトを行うようにシェルに指示しない限り、コマンドは記述子を継承します。ただし、プログラムが起動すると、必要に応じてclosedup、またはopenFDを実行できます。

あなたの質問に戻る:

stdout = open(0, "w")
stdout.write("Hello World") # Prints Hello World
stdout.close()

名前にもかかわらず、この場合、openは何も開きません。すでに開いている低レベルのFDからPythonファイルオブジェクト(バッファーとすべての高レベルのものを含む)を作成します。これは実際には単なる数値です(カーネルで開いているファイルのテーブルへのインデックス) )。別の関数がありました: os.fdopen

もう少し興味深いのは、オープンモードを読み取りから書き込みに変更する標準的な方法がなく、プログラムがstd入力に書き込むことです。答えは(少なくともLinuxでは)これはまったく起こっていないということです。 lsofでわかるように、3つの標準FDはすべて、通常、読み取り/書き込みモードで開いています(末尾にuでマークされています)。例:

 cmd32154ユーザー0uCHR 136,7 0t0 10 /dev/pts/7
cmd32154ユーザー1uCHR 136,7 0t0 10 /dev/pts/7
cmd32154ユーザー2u CHR 136,7 0t0 10 /dev/pts/7

したがって、プログラムは端末に接続されているFD0に書き込むだけです。

3
VPfB

>構文は、pythonが呼び出される前に、シェルによって処理されます。2>stdoutに対して行い、<stderrに対して行うように、stdinを指定されたファイルに接続します。 stdin

とはいえ、01、および2は、それぞれstdoutstderr、およびstderr用に予約されたファイル記述子です(そのため、2>は__some_variable_nameをリダイレクトする構文です) 。

したがって、0は有効なファイル記述子ですが、stdinであり、書き込み用に再度開いています。 stdinが書き込む予定だったので、これは端末に書き込むことになります。

2
Eric Renouf

ファイルハンドル0はstdinです。リダイレクトがない場合、stdout、stderr、およびstdinはすべて端末を指しています(したがって、すべて同じように動作します)。ただし、リダイレクトを使用すると、同じではなくなるため、動作が異なります。

I.E.もしあなたがそうするなら python3 testio.py 2> testio.txtの場合、stdoutはファイルに移動しますが、stdinは引き続き端末です。

これは、チェックなしが存在することの副産物であり、stdinのみを読み取り、stdoutとstderrのみを書き込むことを確認します。

1
ctrl-alt-delor