[英]Integer File Descriptor "0" in open()
In Python 3, it is possible to open a file object using an "integer file descriptor" with the format:在 Python 3 中,可以使用以下格式的“整数文件描述符”打开文件对象:
stdout = open(1, "w")
stdout.write("Hello World") # Prints Hello World
stdout.close()
Though, interestingly, I found that 0
is also a valid stream.不过,有趣的是,我发现
0
也是一个有效的流。
If I put this in the file testio.py
:如果我把它放在文件
testio.py
:
stdout = open(0, "w")
stdout.write("Foo Bar\n")
stdout.close()
And then run that code the output is:然后运行该代码,输出为:
bash-3.2$ python3 testio.py
Foo Bar
Which seems just like stdout
.这似乎就像
stdout
。 However...然而...
bash-3.2$ python3 testio.py > testio.txt
Foo Bar
bash-3.2$ cat testio.txt
So it seems that this is actually not stdout
, but something else.所以看起来这实际上不是
stdout
,而是别的东西。 And it does not appear to be stderr
either:它似乎也不是
stderr
:
bash-3.2$ python3 testio.py 2> testio.txt
Foo Bar
bash-3.2$ cat testio.txt
However, I did find that the output can be redirected using 0>
:但是,我确实发现可以使用
0>
重定向输出:
bash-3.2$ python3 testio.py 0> testio.txt
bash-3.2$ cat testio.txt
Foo Bar
So my question is, what exactly does open(0, "w")
due?所以我的问题是,
open(0, "w")
到底到期了什么? And what is this "0>" stream that is being redirected?正在重定向的“0>”流是什么?
Python 3.6.5蟒蛇 3.6.5
Bash 3.2重击 3.2
No file descriptor (FD) number is special.没有文件描述符 (FD) 编号是特殊的。 stdin on FD 0, stdout on FD 1 and stderr on FD 2 is just a convention.
FD 0 上的 stdin、FD 1 上的 stdout 和 FD 2 上的 stderr 只是一个约定。
When you log in, the associated terminal device will be "connected" to these FDs.当您登录时,关联的终端设备将“连接”到这些 FD。 When you run a command, it inherits the descriptors unless you instruct the shell to make redirections.
当您运行命令时,它会继承描述符,除非您指示 shell 进行重定向。 But once the program starts, you can
close
, dup
, or open
FDs as you like.但是一旦程序启动,您可以根据需要
close
、 dup
或open
FD。
Back to your question:回到你的问题:
stdout = open(0, "w")
stdout.write("Hello World") # Prints Hello World
stdout.close()
Despite the name, open
does not open anything in this case.尽管有这个名字,但在这种情况下
open
不会打开任何东西。 It creates a Python file object (with buffers and all high level stuff) from an already open low-level FD which is really just a number (an index to a table of open files in the kernel).它从一个已经打开的低级 FD 创建一个 Python 文件对象(带有缓冲区和所有高级别的东西),它实际上只是一个数字(内核中打开文件表的索引)。 There was a separate function for it: os.fdopen
有一个单独的函数: os.fdopen
Little bit more interesting is that there is no standard way to change the open mode from read to write and your program writes to std input.更有趣的是,没有标准方法可以将打开模式从读取更改为写入,并且您的程序写入 std 输入。 The answer is (at least on Linux) that this is not happening at all.
答案是(至少在 Linux 上)这根本没有发生。 As you can see with
lsof
, all 3 standard FDs are normally open in read/write mode (marked by trailing u
), eg:正如您在
lsof
中看到的那样,所有 3 个标准 FD 通常都以读/写模式打开(由尾随u
标记),例如:
cmd 32154 user 0u CHR 136,7 0t0 10 /dev/pts/7 cmd 32154 user 1u CHR 136,7 0t0 10 /dev/pts/7 cmd 32154 user 2u CHR 136,7 0t0 10 /dev/pts/7
So your program just writes to the FD 0 which is connected to the terminal.所以你的程序只是写入连接到终端的 FD 0。
>
syntax is handled by the shell before python is invoked. >
语法在调用 python 之前由 shell 处理。 It connects stdout
to the given file, as 2>
does for stderr
and <
does for stdin
.它将
stdout
连接到给定的文件,就像2>
对stderr
和<
对stdin
。
All that said, 0
, 1
, and 2
are file descriptors reserved for stdin
, stdout
, and stderr
respectively (which is why 2>
is the syntax to redirect stderr
).所有这一切,
0
、 1
和2
是分别为stdin
、 stdout
和stderr
保留的文件描述符(这就是为什么2>
是重定向stderr
的语法)。
So 0
is a valid file descriptor, but one that is your stdin
, which you're opening again for writing.所以
0
是一个有效的文件描述符,但它是你的stdin
,你再次打开它进行写入。 This ends up writing to the terminal it seems, since that's where stdin
was going to write.这似乎最终会写入终端,因为那是
stdin
将要写入的地方。
File handle 0
is stdin.文件句柄
0
是标准输入。 Without redirection stdout, stderr, and stdin are all pointing to the terminal (so will all act the same).如果没有重定向,stdout、stderr 和 stdin 都指向终端(因此它们的行为都相同)。 However when redirection is used, they will behave differently, because they will no longer be the same.
然而,当使用重定向时,它们的行为会有所不同,因为它们将不再相同。
IE If you do python3 testio.py 2> testio.txt
, then stdout goes to the file, but stdin is still the terminal. IE 如果您执行
python3 testio.py 2> testio.txt
,则 stdout 转到文件,但 stdin 仍然是终端。
This is just a bi-product of there being no checking to see that you only read stdin, and only write stdout, and stderr.这只是没有检查您是否只读取 stdin、只写入 stdout 和 stderr 的副产品。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.