У меня есть следующий сценарий 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 $
В 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 ()
наконец-то выйдет.
Это объяснение, к сожалению, намного дольше, чем мой предыдущий, но это имеет добродетель правильного. Ошибки такие ...
Первый раз, когда он считает его введенным, во второй раз это для хранения!
Это происходит только при входе от Tty. Это, вероятно, из-за настроек терминала, где персонажи буферируются до тех пор, пока не введена новая линия (возврата каретки).
Скорее всего, это связано с Python в следующих проблемах Python:
Почему бы не прочитать руководство?
http://php.net/manual/en/language.oop5.autoload.php
-121--693203-Я написал об этом объяснение в своем ответе на этот вопрос.
Как захватить сигнал Control + D?
Короче говоря, Control-D на терминале просто заставляет терминал сбросить вход. Это приводит к возврату системного вызова read
. Первый раз возвращается с ненулевым значением (если вы что-то набрали). Второй раз возвращается с 0, который является кодом для «конца файла».