Почему я должен нажать Ctrl+D дважды для закрытия stdin?

У меня есть следующий сценарий Python, который читает числа и производит ошибку, если вход не является числом.

import fileinput
import sys
for line in (txt.strip() for txt in fileinput.input()):
    if not line.isdigit():
        sys.stderr.write("ERROR: not a number: %s\n" % line)

Если я получаю вход от stdin, я должен нажать Ctrl + D дважды для окончания программы. Почему?

Я только должен нажать Ctrl + D однажды, когда я выполняю интерпретатор Python отдельно.

bash $ python test.py
1
2
foo
4
5
<Ctrl+D>
ERROR: not a number: foo
<Ctrl+D>
bash $
13
задан Peter Mortensen 30 September 2013 в 21:00
поделиться

4 ответа

В Python 3 это было связано с ошибкой в ​​стандартной библиотеке ввода / вывода Python . Ошибка была закреплена в Python 3.3.


В терминале Unix, набрав Ctrl + D, на самом деле не закрывает STDIN процесса. Но набрав либо ввод или Ctrl + D, вызывает чтение ОС , чтобы вернуться сразу. Так:

>>> sys.stdin.read(100)
xyzzy                       (I press Enter here)
                            (I press Ctrl+D once)
'xyzzy\n'
>>>

Sys.Stdin.read (100) делегирован на Sys.Stdin.Buffer.read , который вызывает читающую систему () в цикле до тех пор, пока он не накапливает полный запрос количество данных; или система чтения () возвращает 0 байтов; или возникает ошибка. (Документы) (Источник)

Нажатие Enter После первой строки вызвало чтение системы (), чтобы вернуть 6 байтов. SYS.STDIN.BUFFER.READ снова называется READ (), чтобы попытаться получить больше ввода. Затем я нажал Ctrl + D, вызывая чтение (), чтобы вернуть 0 байтов. На данный момент SYSSTDIN.BUFFER.READ сдался и вернулся только в 6 байтах, которые он собрал ранее.

Обратите внимание, что процесс все еще имеет мой терминал на stdin, и я все еще могу вводить вещи.

>>> sys.stdin.read()        (note I can still type stuff to python)
xyzzy                       (I press Enter)
                            (Press Ctrl+D again)
'xyzzy\n'

Хорошо. Это часть, которая была разорена, когда этот вопрос был первоначально спросин. Это работает сейчас. Но до Python 3.3 была ошибка.

Ошибка была немного сложной --- в основном проблема заключалась в том, что два отдельных слоя делают ту же работу. BUFFEREDREADER.READ () был написан на вызов Self.Raw.read () , пока не вернется 0 байтов. Тем не менее, сырой метод, Fileio.read () , выполнил петлю до-нулевого байта самостоятельно. Итак, в первый раз, когда вы нажимаете Ctrl + D в Python с этой ошибкой, это вызвало бы fileio.read () , чтобы вернуть 6 байт в bufferedReader.read () , что бы тогда Сразу позвоните self.raw.read () снова. Второй Ctrl + D будет вызывать , что , чтобы вернуть 0 байтов, а затем bufferedReader.read () наконец-то выйдет.

Это объяснение, к сожалению, намного дольше, чем мой предыдущий, но это имеет добродетель правильного. Ошибки такие ...

14
ответ дан 1 December 2019 в 21:12
поделиться

Первый раз, когда он считает его введенным, во второй раз это для хранения!

Это происходит только при входе от Tty. Это, вероятно, из-за настроек терминала, где персонажи буферируются до тех пор, пока не введена новая линия (возврата каретки).

0
ответ дан 1 December 2019 в 21:12
поделиться

Скорее всего, это связано с Python в следующих проблемах Python:

  • 5505 : Sys.Stdin.read () не возвращается после первого EOF на Windows, а
  • 1633941 : для линии в Sys.Stdin: не замечает eof первый раз.
9
ответ дан 1 December 2019 в 21:12
поделиться

Почему бы не прочитать руководство?

http://php.net/manual/en/language.oop5.autoload.php

-121--693203-

Я написал об этом объяснение в своем ответе на этот вопрос.

Как захватить сигнал Control + D?

Короче говоря, Control-D на терминале просто заставляет терминал сбросить вход. Это приводит к возврату системного вызова read . Первый раз возвращается с ненулевым значением (если вы что-то набрали). Второй раз возвращается с 0, который является кодом для «конца файла».

4
ответ дан 1 December 2019 в 21:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: