В компьютерном программировании , стандартные потоки соединяются между собой входной и выходной каналы связи [1] между компьютерной программой и ее окружением , когда она начинает выполнение. Три соединения ввода / вывода (I / O) называются стандартным вводом ( stdin ), стандартным выводом ( stdout ) и стандартной ошибкой ( stderr ). Первоначально ввод-вывод происходил через физически подключенную системную консоль (ввод с клавиатуры, вывод через монитор), но стандартные потоки абстрагируются от этого. Когда команда выполняется через интерактивную оболочку, потоки обычно подключаются к текстовому терминалу, на котором запущена оболочка, но их можно изменить с помощью перенаправления или конвейера . В более общем смысле дочерний процесс наследует стандартные потоки своего родительского процесса .
Заявление [ править ]
Обычно пользователи знают стандартные потоки как каналы ввода и вывода, которые обрабатывают данные, поступающие от устройства ввода, или записывают данные из приложения. Данные могут быть текстовыми с любой кодировкой или двоичными данными . Во многих современных системах стандартный поток ошибок программы перенаправляется в файл журнала, обычно для целей анализа ошибок.
Потоки могут использоваться для объединения приложений в цепочку, что означает, что выходной поток одной программы может быть перенаправлен в качестве входного потока в другое приложение. Во многих операционных системах это выражается перечислением имен приложений, разделенных вертикальной чертой, по этой причине часто называемой символом конвейера . Хорошо известным примером является использование приложения разбиения на страницы , такого как more , предоставляющего пользователю контроль над отображением выходного потока на дисплее.
Фон [ править ]
В большинстве операционных систем, предшествующих Unix , программы должны были явно подключаться к соответствующим устройствам ввода и вывода. Из-за специфических особенностей ОС это была утомительная задача программирования. Во многих системах необходимо было получить контроль над настройками среды, получить доступ к локальной таблице файлов, определить предполагаемый набор данных и правильно обращаться с оборудованием в случае устройства чтения перфокарт , накопителя на магнитной ленте , дисковода , линейного принтера , перфорации карт. , или интерактивный терминал.
Одним из нескольких новаторских достижений Unix были абстрактные устройства , которые избавили программу от необходимости знать или заботиться о том, с какими устройствами она взаимодействует [ необходима цитата ] . Старые операционные системы навязывали программисту структуру записи и часто неортогональную семантику данных и управление устройством. Unix устранил эту сложность с помощью концепции потока данных: упорядоченной последовательности байтов данных, которые могут быть прочитаны до конца файла . Программа также может записывать байты по желанию и без необходимости, и не может легко объявить их количество или группировку.
Еще одним прорывом в Unix было автоматическое связывание ввода и вывода с клавиатурой терминала и дисплеем терминала, соответственно, по умолчанию [ необходима цитата ] - программа (и программист) не делали абсолютно ничего, чтобы установить ввод и вывод для типичной программы ввода-процесса-вывода ( если он не выбрал другую парадигму). Напротив, предыдущие операционные системы обычно требовали некоторого - часто сложного - языка управления заданиями для установления соединений, или аналогичная нагрузка должна была быть организована программой. [ необходима цитата ]
Поскольку Unix предоставляет стандартные потоки, среда выполнения Unix C также обязана поддерживать их. В результате большинство сред выполнения C (и потомков C ), независимо от операционной системы, обеспечивают эквивалентную функциональность.
Стандартный ввод (stdin) [ править ]
Стандартный ввод - это поток, из которого программа считывает свои входные данные. Программа запрашивает передачу данных с помощью операции чтения . Не все программы требуют потокового ввода. Например, программы dir и ls (которые отображают имена файлов, содержащихся в каталоге) могут принимать аргументы командной строки , но выполнять свои операции без ввода каких-либо потоковых данных.
Если не перенаправить , стандартный ввод наследуется от родительского процесса. В случае интерактивной оболочки это обычно связано с клавиатурой .
Дескриптор файла для стандартного ввода равен 0 (ноль); POSIX <unistd.h> определение STDIN_FILENO
; соответствующая переменная C <stdio.h>FILE* stdin
: аналогично, переменная C ++ <iostream> имеет вид std::cin
.
Стандартный вывод (stdout) [ править ]
Стандартный вывод - это поток, в который программа записывает свои выходные данные. Программа запрашивает передачу данных с операцией записи . Не все программы генерируют выходные данные. Например, команда переименования файла (называемая по-разному mv , move или ren ) не сообщает об успехе.
Если не перенаправить , стандартный вывод наследуется от родительского процесса. В случае интерактивной оболочки это обычно текстовый терминал, запускающий программу.
Дескриптор файла для стандартного вывода составляет 1 (один); POSIX <unistd.h> определение STDOUT_FILENO
; соответствующая переменная C <stdio.h>FILE* stdout
: аналогично, переменная C ++ <iostream> имеет вид std::cout
.
Стандартная ошибка (stderr) [ править ]
Стандартная ошибка - это еще один поток вывода, обычно используемый программами для вывода сообщений об ошибках или диагностики. Это поток, независимый от стандартного вывода, и его можно перенаправить отдельно. Это решает проблему полупредиката , позволяя различать выходные данные и ошибки, и аналогично функции, возвращающей пару значений - см. Проблема полупредиката: многозначный возврат . Обычным местом назначения является текстовый терминал, который запустил программу, чтобы обеспечить максимальную вероятность быть увиденным, даже если стандартный вывод перенаправлен (что не всегда наблюдается). Например, вывод программы в конвейере перенаправляется на ввод следующей программы, но ошибки каждой программы по-прежнему попадают непосредственно в текстовый терминал.
Допустимо и нормально направлять стандартный вывод и стандартную ошибку в одно и то же место назначения, например, в текстовый терминал. Сообщения появляются в том же порядке, в котором их записывает программа, если не используется буферизация . Например, в обычных ситуациях стандартный поток ошибок не буферизуется, но стандартный выходной поток буферизуется по строкам; в этом случае текст, записанный в стандартную ошибку позже, может появиться на терминале раньше, если буфер стандартного потока вывода еще не заполнен.
Дескриптор файла для стандартной ошибки определяется POSIX как 2 (два); <unistd.h> Заголовочный файл содержит символ STDERR_FILENO
; [2] соответствующая переменная C <stdio.h>FILE* stderr
. Стандартный заголовок C ++ <iostream> предоставляет две переменные, связанные с этим потоком: std::cerr
и std::clog
, первая из которых не буферизуется, а вторая использует тот же механизм буферизации, что и все другие потоки C ++.
Оболочки в стиле Борна позволяют перенаправлять стандартную ошибку в то же место назначения, на которое направляется стандартный вывод.
2> & 1
Оболочки в стиле csh позволяют перенаправлять стандартную ошибку в то же место назначения, на которое направляется стандартный вывод.
> &
Стандартная ошибка была добавлена в Unix в 1970-х годах после того, как несколько потраченных впустую запусков фотонабора закончились набором сообщений об ошибках, а не отображением на пользовательском терминале. [3]
Хронология [ править ]
1950-е: Фортран [ править ]
Fortran имеет эквивалент файловых дескрипторов Unix: по соглашению, многие реализации Fortran используют номера единиц UNIT=5
для stdin, UNIT=6
для stdout и UNIT=0
для stderr. В Fortran-2003, характеристическая ISO_FORTRAN_ENV
модуль был стандартизирован включать именованные константы INPUT_UNIT
, OUTPUT_UNIT
и ERROR_UNIT
в переносимых указать номера блока.
! Пример FORTRAN 77 ПРОГРАММА MAIN INTEGER NUMBER READ ( UNIT = 5 , * ) NUMBER WRITE ( UNIT = 6 , '(A, I3)' ) 'NUMBER IS:' , NUMBER END
! Пример программы Fortran 2003, основное использование iso_fortran_env неявное none integer :: number read ( unit = INPUT_UNIT , * ) number write ( unit = OUTPUT_UNIT , '(a, i3)' ) 'Number is:' , number end program
1960: АЛГОЛ 60 [ править ]
Алгол 60 критиковали за отсутствие стандартного доступа к файлам. [ необходима цитата ]
1968: АЛГОЛ 68 [ править ]
Средства ввода и вывода в АЛГОЛе 68 в совокупности назывались передачей. [4] Костер скоординированы определение transput стандарта. Модель включала три стандартных канала: stand in
, stand out
и stand back
.
# Пример АЛГОЛА 68 #основной:( Настоящий номер; getf (стоять, ($ g $, number)); printf (($ "Число:" g (6,4) "ИЛИ" $, число)); # ИЛИ ЖЕ # putf (выделиться, ($ "Число:" g (6,4) "!" $, число)); новая строка (выделяться)) | |
Вход: | Выход: |
---|---|
3,14159 | Номер: +3,142 ИЛИ Номер: +3,142! |
1970-е: C и Unix [ править ]
В языке программирования C стандартные потоки ввода, вывода и ошибок присоединяются к существующим файловым дескрипторам Unix 0, 1 и 2 соответственно. [5] В среде POSIX вместо магических чисел следует использовать определения < unistd.h > STDIN_FILENO , STDOUT_FILENO или STDERR_FILENO . Также предоставляются указатели на файлы stdin , stdout и stderr .
Кен Томпсон (разработчик и разработчик исходной операционной системы Unix) модифицировал sort в версии 5 Unix, чтобы принимать «-» как стандартный ввод, который распространился на другие утилиты и стал частью операционной системы в виде специального файла в версии 8 . Диагностика была частью стандартного вывода до Версии 6 , после чего Деннис М. Ричи создал концепцию стандартной ошибки. [6]
1995: Java [ править ]
В Java стандартные потоки называются System.in
(для stdin), System.out
(для stdout) и System.err
(для stderr). [7]
public static void main ( String args [] ) { попробуйте { BufferedReader br = new BufferedReader ( новый InputStreamReader ( System . in )); Строка s = br . readLine (); двойное число = Двойное . parseDouble ( s ); Система . из . println ( "Число:" + число); } catch ( Исключение e ) { System . эээ . println ( "Ошибка:" + е . getMessage ()); } }
2000-е: .NET [ править ]
В C # и других языках .NET стандартные потоки называются System.Console.In
(для stdin), System.Console.Out
(для stdout) и System.Console.Error
(для stderr). [8] Базовые возможности чтения и записи для потоков stdin и stdout также доступны напрямую через класс System.Console
(например, System.Console.WriteLine()
могут использоваться вместо System.Console.Out.WriteLine()
).
System.Console.In
, System.Console.Out
и System.Console.Error
являются объектами System.IO.TextReader
(stdin) и System.IO.TextWriter
(stdout, stderr), которые разрешают доступ только к базовым стандартным потокам на текстовой основе. Полный двоичный доступ к стандартным потокам должен осуществляться через System.IO.Stream
объекты, возвращаемые System.Console.OpenStandardInput()
, System.Console.OpenStandardOutput()
и System.Console.OpenStandardError()
соответственно.
// Пример C # public static int Main ( string [] args ) { try { string s = System . Консоль . В . ReadLine (); двойное число = двойное . Разбор ( ы ); Система . Консоль . Out . WriteLine ( "Число: {0: F3}" , число ); возврат 0 ; // Если Parse () сгенерировал исключение } catch ( ArgumentNullException ) { System . Консоль . Ошибка . WriteLine ( «Номер не введен!» ); } catch ( FormatException ) { System . Консоль . Ошибка . WriteLine ( «Указанное значение не является допустимым числом!» ); } catch ( OverflowException ) { System . Консоль . Ошибка .WriteLine ( «Указанное число слишком велико!» ); } возврат - 1 ; }
'Пример Visual Basic .NETОткрытая функция Main () As Integer Попробуйте Dim s As String = System . Консоль . [ В ] . ReadLine () Dim number As Double = Double . Разбор ( ы ) системы . Консоль . Out . WriteLine ( "Число: {0: F3}" , число ) Вернуть 0 'Если Parse () выдал исключение Catch ex As System . ArgumentNullException Система . Консоль . [ Ошибка ] . WriteLine ( «Номер не введен!» ) Catch ex2 As System . FormatException System . Консоль . [ Ошибка ] . WriteLine ( «Указанное значение не является допустимым числом!» ) Catch ex3 As System . Система OverflowException . Консоль . [ Ошибка ] . WriteLine ( «Указанное число слишком велико!» ) Конец Попытки Возврат - 1 конечная функция
При применении System.Diagnostics.Process
класса можно использовать экземпляр свойство StandardInput
, StandardOutput
и StandardError
из этого класса доступа стандартных потоков процесса.
Python [ править ]
Python предоставляет файловые объекты, представляющие stdin, stdout и stderr. Мы можем показать, как мы можем использовать эти объекты для работы с вводом и выводом нашей программы.
sys.stdin [ править ]
Модуль Python sys предоставляет нам все три файловых объекта для stdin, stdout и stderr. В качестве объекта входного файла мы используем sys.stdin. Это похоже на файл, где его можно открывать и закрывать, как и любой другой файл.
вот базовый пример:
программа stdin.py
import sysstdin_fileno = sys . стандартный ввод# Продолжает чтение из stdin и завершает работу, только если есть слово 'exit' # Этот цикл по умолчанию не завершается, так как stdin открыт для строки в stdin_fileno : # Удалите завершающие символы новой строки с помощью strip () if "exit" == линия . strip (): print ( "Найден выход. Завершение программы" ) exit ( 0 ) else : print ( "Сообщение от sys.stdin: ---> {} <---" . format ( line ))
Применение:
$ printf "это \ n разные \ n слова" | python stdin.py Сообщение от sys.stdin: ---> эти <--- <br> Сообщение от sys.stdin: ---> разные <--- <br> Сообщение от sys.stdin: --- > слова <--- <br>
Приведенный выше фрагмент продолжает считывать ввод со стандартного ввода и выводит сообщение в консоль (стандартный вывод) до тех пор, пока не встретится слово exit. ПРИМЕЧАНИЕ. Обычно мы не закрываем объект файла stdin по умолчанию, хотя это разрешено. Итак, stdin_fileno.close () - действительный код Python. Теперь, когда мы немного знаем о stdin, перейдем к stdout.
sys.stdout [ править ]
В качестве объекта выходного файла мы используем sys.stdout. Он похож на sys.stdin, но напрямую отображает все, что написано в нем, в консоли.
В приведенном ниже фрагменте показано, что мы получаем вывод в консоль, если пишем в sys.stdout.
программа stdout.py
import sysstdout_fileno = sys . стандартный выводsample_input = [ «Привет» , «Привет из Python» , «выход» ]для ip в sample_input : # Печатает в stdout stdout_fileno . написать ( ip + " \ n " )
Для выполнения:
python stdout.py
Вывод:
Привет,
привет из
выхода Python
sys.stderr [ править ]
Это похоже на sys.stdout, потому что он также выводится непосредственно в консоль. Но разница в том, что их можно использовать для печати сообщений об исключениях и ошибках, а также информационных / отладочных комментариев. (Вот почему это называется стандартной ошибкой). Это может быть очень полезно, когда вместо этого для записи данных используется стандартный вывод. Вот пример.
программа stderr.py
import sysstdout_fileno = sys . stdout stderr_fileno = sys . stderrsample_input = [ «Привет» , «Привет из Python» , «выход» ]for ip in sample_input : # Печатает в stdout # Пытается добавить целое число со строкой. Вызывает исключение try : stdout_fileno . write ( ip + " \ n " ) # Перехватить исключения, кроме : stderr_fileno . write ( "Произошло исключение! \ n " ) stderr_fileno . напишите ( "ip =" + ip ) попробуйте : ip = ip + 100 # Перехватить все исключения, кроме : stderr_fileno . write ( "Произошло исключение! ip =" + ip + " \ n " )
Для выполнения: python stderr.py
Вывод:
Привет,
исключение! ip = Привет,
привет от Python.
Произошла исключительная ситуация! ф = Привет из Python
выхода
Exception Происходил! ip = выход
Как вы можете заметить, для всех входных строк мы пытаемся добавить к целому числу, что вызовет исключение. Мы перехватываем все такие исключения и выводим еще одно сообщение отладки с помощью sys.stderr.
Перенаправление в файл
Мы можем перенаправить дескрипторы файлов stdout, а также stderr в любой другой файл (дескриптор файла). Это может быть полезно, если вы хотите записывать события в файл без использования какого-либо другого модуля, такого как Ведение журнала.
Приведенный ниже фрагмент перенаправляет вывод (stdout) в файл с именем Output.txt.
Итак, мы не увидим ничего, напечатанного в консоли, потому что теперь оно печатается в самом файле! В этом суть перенаправления вывода. Вы «перенаправляете» вывод в другое место. (На этот раз в Output.txt, а не в Консоль)
import sys # Сохраняем текущий stdout, чтобы мы могли вернуть sys.stdout после # завершения перенаправления stdout_fileno = sys . стандартный вывод sample_input = [ «Привет» , «Привет из Python» , «выход» ] # Перенаправить sys.stdout в файл sys . stdout = open ( "Output.txt" , "w" ) для ip в sample_input : # Печатает в перенаправленный stdout (Output.txt) sys . стандартный вывод . write ( ip + ' \ n ' ) # Печатает в фактический сохраненный обработчик stdout stdout_fileno . написать ( ip + ' \ n ' ) # Закройте файл sys . стандартный вывод . close () # Восстановить sys.stdout в наш старый сохраненный обработчик файлов sys . stdout = stdout_fileno
Выход:
$ root @ ubuntu: ~ # python3 output_redirection.py Привет, привет, выход из Python $ root @ ubuntu: ~ # cat Output.txt Привет, привет, выход из Python
Как видите, мы распечатали вывод как в Консоль, так и в Output.txt. Сначала мы сохраняем исходный объект обработчика файла sys.stdout в другую переменную. Нам это нужно не только для восстановления sys.stdout в старом обработчике (указывающем на консоль), но мы также можем печатать на консоль, используя эту переменную! Обратите внимание, что после записи в файл мы закрываем его, аналогично тому, как мы закрываем файл, потому что этот файл все еще был открыт. Наконец, мы восстанавливаем обработчик sys.stdout в консоли, используя переменную stdout_fileno. Аналогичный процесс можно выполнить для перенаправления ввода и ошибок, заменив sys.stdout на sys.stdin или sys.stderr и работая с входами и исключениями вместо вывода. Здесь было описано использование stdin, stdout и stderr в Python с использованием модуля sys.А также как управлять соответствующими обработчиками файлов для перенаправления в / из файла.
GUI [ править ]
Графические пользовательские интерфейсы (GUI) не всегда используют стандартные потоки; они работают, когда графические интерфейсы являются оболочками для базовых сценариев и / или консольных программ, например, графического интерфейса диспетчера пакетов Synaptic , который обертывает команды apt в Debian и / или Ubuntu. Графические интерфейсы, созданные с помощью инструментов сценариев, таких как Zenity и KDialog в рамках проекта KDE [9], используют stdin, stdout и stderr и основаны на простых сценариях, а не на полном графическом интерфейсе, запрограммированном и скомпилированном на C / C ++ с использованием Qt , GTK или других эквивалентная проприетарная структура виджетов.
Меню Услуги , как это реализовано на NeXTSTEP и Mac OS X , также аналогично стандартным потокам. В этих операционных системах графические приложения могут предоставлять функциональные возможности через общесистемное меню, которое работает с текущим выбором в графическом интерфейсе, независимо от того, в каком приложении.
Некоторые программы с графическим интерфейсом пользователя, в основном в Unix, по-прежнему записывают отладочную информацию в стандартную ошибку. Другие (например, многие медиаплееры Unix) могут читать файлы со стандартного ввода. Популярными программами Windows, открывающими отдельное окно консоли в дополнение к окнам графического интерфейса пользователя, являются эмуляторы pSX и DOSBox .
GTK-сервер может использовать stdin в качестве интерфейса связи с интерпретируемой программой для реализации графического интерфейса.
В Common Lisp Interface Менеджер парадигмы «представляет» GUI элементы отправлены в расширенный выходной поток.
См. Также [ править ]
- Перенаправление (вычисления)
- Stream (вычисления)
- Ввод, вывод
- Ввод / вывод файла C
- SYSIN и SYSOUT
- Стандартные потоки в OpenVMS
Ссылки [ править ]
- ^ DM Ричи, "Система ввода-вывода потока" , Технический журнал AT&T Bell Laboratories, 68 (8), октябрь 1984 г.
- ^ "<unistd.h>" . Открытая группа Базовые характеристики Выпуск 6-IEEE Std 1003.1, 2004 Edition , . Открытая группа. 2004 г.
- ^ Джонсон, Стив (2013-12-11). «[TUHS] Graphic Systems C / A / T photosetter» (Список рассылки). Архивировано 25 сентября 2020 года . Проверено 7 ноября 2020 .
- ^ Пересмотренный отчет по алгоритмическому языку Algol 68, отредактированный A. van Wijngaarden, BJ Mailloux, JEL Peck, CHA Koster, M. Sintzoff, CH Lindsey, LGLT Meertens и RG Fisker, http://www.softwarepreservation.org/projects /ALGOL/report/Algol68_revised_report-AB.pdf , раздел 10.3
- ^ http://linux.die.net/man/3/stdin
- Перейти ↑ McIlroy, MD (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (технический отчет). CSTR. Bell Labs. 139.
- ^ «Система (Java Platform SE 7)» . Проверено 20 июля 2012 года .
- ^ "Справочный источник C #, .NET Framework 4.7.1, mscorlib, класс консоли" . linksource.microsoft.com . Проверено 10 декабря 2017 .
- ^ Кисслинг, Kristian (2009). «Добавление графических элементов в ваши скрипты с помощью Zenity и KDialog» . Журнал Linux . Проверено 11 апреля 2021 .
Источники [ править ]
- « Стандартные потоки », библиотека GNU C
- Справочное руководство KRONOS 2.1 , Control Data Corporation, номер по каталогу 60407000, 1974
- NOS Version 1 Applications Programmer's Instant , Control Data Corporation, номер по каталогу 60436000, 1978
- Уровень 68 Введение в программирование на MULTICS , Корпорация Honeywell, 1981 г.
- Эволюция операционной системы MVS , корпорация IBM, 1981 г.
- Комментарий Льва к шестому изданию UNIX , Джон Лайонс, ISBN 1-57398-013-7 , 1977
- Консольный класс, библиотека классов .NET Framework , корпорация Microsoft, 2008 г.
Внешние ссылки [ править ]
- Стандартное определение ввода - от Linux Information Project
- Стандартное определение вывода - от Linux Information Project
- Стандартное определение ошибки - от Linux Information Project