python - open() 中的整数文件描述符 "0"

在 Python 3 中,可以 open a file object using an "integer file descriptor"使用格式:

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 和 FD 2 上的 stderr 只是一个约定。

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

回到你的问题:

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

尽管名称如此,open 在这种情况下不会打开任何内容。它从一个已经打开的低级别 FD 创建一个 Python 文件对象(带有缓冲区和所有高级内容),它实际上只是一个数字(内核中打开文件表的索引)。它有一个单独的功能:os.fdopen

更有趣的一点是,没有标准的方法可以将打开模式从读取更改为写入,并且您的程序将写入标准输入。答案是(至少在 Linux 上)这根本不会发生。正如您在 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

所以你的程序只是写入连接到终端的 FD 0。

关于python - open() 中的整数文件描述符 "0",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63866753/

相关文章:

google-cloud-platform - 接受 Google 帐户转移请求时如何解决消息 "T

python-3.x - 安装 github 子模块时,诗歌安装失败并显示 [CalledProce

linux - 用 n 步旋转文本文件中的行

python - 在使用 pyspark 和预定义的结构模式读取嵌套的 JSON 时,如何将缺失的列

python - 使用 Python 的双向方差分析

scala - 在读取 CSV 时,最后一列在 Spark、Scala 中显示为 Null

python - 无法通过 Pip 安装 TensorFlow

visual-studio - VS代码-OSS : Downloading files and f

variables - 如何在 Pyomo 模型中设置决策变量的初始值

java - 使用 Spring JPA/Hibernate 按不同值批量更新