Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В компьютерном программировании , стандартные потоки соединяются между собой входной и выходной каналы связи [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.

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

Ссылки [ править ]

  1. ^ DM Ричи, "Система ввода-вывода потока" , Технический журнал AT&T Bell Laboratories, 68 (8), октябрь 1984 г.
  2. ^ "<unistd.h>" . Открытая группа Базовые характеристики Выпуск 6-IEEE Std 1003.1, 2004 Edition , . Открытая группа. 2004 г.
  3. ^ Джонсон, Стив (2013-12-11). «[TUHS] Graphic Systems C / A / T photosetter» (Список рассылки). Архивировано 25 сентября 2020 года . Проверено 7 ноября 2020 .
  4. ^ Пересмотренный отчет по алгоритмическому языку 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
  5. ^ http://linux.die.net/man/3/stdin
  6. Перейти ↑ McIlroy, MD (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (технический отчет). CSTR. Bell Labs. 139.
  7. ^ «Система (Java Platform SE 7)» . Проверено 20 июля 2012 года .
  8. ^ "Справочный источник C #, .NET Framework 4.7.1, mscorlib, класс консоли" . linksource.microsoft.com . Проверено 10 декабря 2017 .
  9. ^ Кисслинг, 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