简体   繁体   English

open() 中的整数文件描述符“0”

[英]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.但是一旦程序启动,您可以根据需要closedupopen 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 ).所有这一切, 012是分别为stdinstdoutstderr保留的文件描述符(这就是为什么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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM