簡體   English   中英

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

[英]Integer File Descriptor "0" in open()

在 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

這似乎就像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>”流是什么?

蟒蛇 3.6.5
重擊 3.2

沒有文件描述符 (FD) 編號是特殊的。 FD 0 上的 stdin、FD 1 上的 stdout 和 FD 2 上的 stderr 只是一個約定。

當您登錄時,關聯的終端設備將“連接”到這些 FD。 當您運行命令時,它會繼承描述符,除非您指示 shell 進行重定向。 但是一旦程序啟動,您可以根據需要closedupopen FD。

回到你的問題:

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

盡管有這個名字,但在這種情況下open不會打開任何東西。 它從一個已經打開的低級 FD 創建一個 Python 文件對象(帶有緩沖區和所有高級別的東西),它實際上只是一個數字(內核中打開文件表的索引)。 有一個單獨的函數: os.fdopen

更有趣的是,沒有標准方法可以將打開模式從讀取更改為寫入,並且您的程序寫入 std 輸入。 答案是(至少在 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 之前由 shell 處理。 它將stdout連接到給定的文件,就像2>stderr<stdin

所有這一切, 012是分別為stdinstdoutstderr保留的文件描述符(這就是為什么2>是重定向stderr的語法)。

所以0是一個有效的文件描述符,但它是你的stdin ,你再次打開它進行寫入。 這似乎最終會寫入終端,因為那是stdin將要寫入的地方。

文件句柄0是標准輸入。 如果沒有重定向,stdout、stderr 和 stdin 都指向終端(因此它們的行為都相同)。 然而,當使用重定向時,它們的行為會有所不同,因為它們將不再相同。

IE 如果您執行python3 testio.py 2> testio.txt ,則 stdout 轉到文件,但 stdin 仍然是終端。

這只是沒有檢查您是否只讀取 stdin、只寫入 stdout 和 stderr 的副產品。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM