Python 整数文件描述符";0“;公开的

Python 整数文件描述符";0“;公开的,python,python-3.x,bash,stdout,python-internals,Python,Python 3.x,Bash,Stdout,Python Internals,在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.

在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
这看起来就像是标准的代码。然而

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”)
due到底是什么?这个被重定向的“0>”流是什么

Python 3.6.5

bash3.2

语法在调用python之前由shell处理。它将
stdout
连接到给定的文件,就像
2>
stderr
是重定向
stderr
的语法)


所以
0
是一个有效的文件描述符,但它是您的
stdin
,您将再次打开它进行编写。这似乎最终会写入终端,因为
stdin
将在那里写入。

文件句柄
0
是stdin。在没有重定向的情况下,stdout、stderr和stdin都指向终端(因此它们的行为都是相同的)。但是,当使用重定向时,它们的行为将不同,因为它们将不再相同

也就是说,如果您执行了
python3 testio.py 2>testio.txt
,则stdout将转到该文件,但stdin仍然是终端

这只是一个bi产品,它没有检查,只读取stdin,只写入stdout和stderr

没有特殊的文件描述符(FD)编号。FD 0上的stdin、FD 1上的stdout和FD 2上的stderr只是一种约定

登录时,关联的终端设备将“连接”到这些FD。运行命令时,除非指示shell进行重定向,否则它将继承描述符。但一旦程序启动,您可以根据需要
关闭
dup
打开
FDs

回到你的问题:

stdout = open(0, "w")
stdout.write("Hello World") # Prints Hello World
stdout.close()
尽管名称不同,
open
在本例中不会打开任何内容。它从一个已经打开的低级FD创建一个Python文件对象(带有缓冲区和所有高级内容),这个FD实际上只是一个数字(内核中打开的文件表的索引)。它有一个单独的功能:

更有趣的是,没有标准的方法将开放模式从读改为写,并且程序将写入std输入。答案是(至少在Linux上)根本没有发生这种情况。正如您在
lsof
中所看到的,所有3个标准FD在读/写模式下都是常开的(以尾随
u
标记),例如:

cmd 32154用户0u CHR 136,7 0t0 10/dev/pts/7 cmd 32154用户1u CHR 136,7 0t0 10/dev/pts/7 cmd 32154用户2u CHR 136,7 0t0 10/dev/pts/7
因此,您的程序只是写入连接到终端的FD 0。

提示:除了
stdout
stderr
之外,还会有什么流?可能通常用于不同的数据方向?如何使用
lsof
访问此信息?我不知道
lsof
能做到这一点。@TheMatt有很多方法可以运行lsof(列出打开的文件)。例如,
lsof-c lsof
将启动一个
lsof
过程,并将检查所有正在运行的
lsof
命令,也就是说,很可能只是它本身。如果要将输出仅限于这3个FD:
lsof-c lsof-a-d 0-2
。 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