Integer File Descriptor “0” in open()

No file descriptor (FD) number is special. stdin on FD 0, stdout on FD 1 and stderr on FD 2 is just a convention.

When you log in, the associated terminal device will be “connected” to these FDs. When you run a command, it inherits the descriptors unless you instruct the shell to make redirections. But once the program starts, you can close, dup, or open FDs as you like.

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. 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). There was a separate function for it: 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. The answer is (at least on Linux) that this is not happening at all. As you can see with lsof, all 3 standard FDs are normally open in read/write mode (marked by trailing u), e.g.:

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.

Leave a Comment