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
特別なファイル記述子(FD)番号はありません。 FD 0のstdin、FD 1のstdout、およびFD2のstderrは単なる慣例です。
ログインすると、関連する端末デバイスがこれらのFDに「接続」されます。コマンドを実行すると、リダイレクトを行うようにシェルに指示しない限り、コマンドは記述子を継承します。ただし、プログラムが起動すると、必要に応じてclose
、dup
、またはopen
FDを実行できます。
あなたの質問に戻る:
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に書き込むだけです。
>
構文は、pythonが呼び出される前に、シェルによって処理されます。2>
がstdout
に対して行い、<
がstderr
に対して行うように、stdin
を指定されたファイルに接続します。 stdin
。
とはいえ、0
、1
、および2
は、それぞれstdout
、stderr
、およびstderr
用に予約されたファイル記述子です(そのため、2>
は__some_variable_nameをリダイレクトする構文です) 。
したがって、0
は有効なファイル記述子ですが、stdin
であり、書き込み用に再度開いています。 stdin
が書き込む予定だったので、これは端末に書き込むことになります。
ファイルハンドル0
はstdinです。リダイレクトがない場合、stdout、stderr、およびstdinはすべて端末を指しています(したがって、すべて同じように動作します)。ただし、リダイレクトを使用すると、同じではなくなるため、動作が異なります。
I.E.もしあなたがそうするなら python3 testio.py 2> testio.txt
の場合、stdoutはファイルに移動しますが、stdinは引き続き端末です。
これは、チェックなしが存在することの副産物であり、stdinのみを読み取り、stdoutとstderrのみを書き込むことを確認します。