Целочисленный дескриптор файла "0" в open () - Python 3 - PullRequest
0 голосов
/ 22 декабря 2018

В 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>», который перенаправляется?

Python 3.6.5
Bash 3.2

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018

Дескриптор файла 0 является стандартным.Без перенаправления stdout, stderr и stdin все указывают на терминал (поэтому все будут действовать одинаково).Однако при использовании перенаправления они будут вести себя по-разному, поскольку они больше не будут одинаковыми.

IE Если вы выполните python3 testio.py 2> testio.txt, тогда stdout переходит в файл, но stdin по-прежнему является терминалом.

Это всего лишь побочный продукт того, что нет проверки , чтобы увидеть, что вы читаете только stdin, пишете только stdout и stderr.

0 голосов
/ 22 декабря 2018

Номер дескриптора файла (FD) не является специальным.stdin на FD 0, stdout на FD 1 и stderr на FD 2. это просто соглашение.

При входе в систему соответствующее оконечное устройство будет «подключено» к этим FD.Когда вы запускаете команду, она наследует дескрипторы, если вы не указали оболочке выполнить перенаправление.Но как только программа запустится, вы можете close, dup или open FD, как вам нравится.

Вернуться к вашему вопросу:

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

Несмотря на название, open ничего не открывает в этом случае.Он создает файловый объект Python (с буферами и всем высокоуровневым содержимым) из уже открытого низкоуровневого FD, который на самом деле является просто числом (индексом таблицы открытых файлов в ядре).Для него была отдельная функция: 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который подключен к терминалу.

0 голосов
/ 22 декабря 2018
Синтаксис

> обрабатывается оболочкой до вызова Python.Он соединяет stdout с данным файлом, как 2> для stderr и < для stdin.

Все, что сказано, 0, 1 и 2 являются файловыми дескрипторами, зарезервированными для stdin, stdout и stderr соответственно (именно поэтому 2> является синтаксисом для перенаправления stderr).

Так что 0 является допустимым файломдескриптор, но это ваш stdin, который вы снова открываете для записи.Это завершает запись в терминал, как кажется, поскольку именно здесь stdin собирался писать.

...