Стандартные потоки

редактировать

В компьютерном программировании, стандартные потоки связаны между собой ввод и вывод связь каналы между компьютерной программой и ее средой, когда она начинает выполнение. Три соединения ввода / вывода (I / O) называются стандартный ввод (stdin ), стандартный вывод (stdout ) и стандартная ошибка (stderr ). Первоначально ввод-вывод происходил через физически подключенную системную консоль (ввод с клавиатуры, вывод через монитор), но стандартные потоки абстрагируются от этого. Когда команда выполняется через интерактивную оболочку, потоки обычно подключаются к текстовому терминалу, на котором запущена оболочка, но их можно изменить с помощью перенаправления или трубопровод. В более общем смысле, дочерний процесс наследует стандартные потоки своего родительского процесса.

Содержание

  • 1 Приложение
  • 2 Фон
  • 3 Стандартный ввод (stdin)
  • 4 Стандартный вывод (stdout)
  • 5 Стандартная ошибка (stderr)
  • 6 Временная шкала
    • 6.1 1950-е: Fortran
    • 6.2 1960: ALGOL 60
    • 6.3 1968: ALGOL 68
    • 6.4 1970-е: C и Unix
    • 6.5 1995: Java
    • 6.6 2000-е:.NET
    • 6.7 Python
      • 6.7.1 sys.stdin
      • 6.7.2 sys.stdout
      • 6.7.3 sys.stderr
    • 6.8 GUI
  • 7 См. Также
  • 8 Ссылки
  • 9 Источники
  • 10 Внешние ссылки

Приложение

Стандартные потоки для ввода, вывода и ошибок

Обычно пользователи знают стандартные потоки как каналы ввода и вывода, которые обрабатывают данные, поступающие от устройства ввода, или записывают данные из приложения. Данные могут быть текстом с любой кодировкой или двоичными данными. Во многих современных системах стандартный поток ошибок программы перенаправляется в файл журнала, как правило, для целей анализа ошибок.

Потоки могут использоваться для цепочки приложений, что означает, что выходной поток одной программы может быть перенаправлен как входной поток в другое приложение. Во многих операционных системах это выражается перечислением имен приложений, разделенных символом вертикальной черты, по этой причине часто называемым символом конвейера. Хорошо известным примером является использование приложения разбивки на страницы, такого как more, обеспечивающего пользователю контроль над отображением выходного потока на дисплее.

Предпосылки

В большинстве операционных систем, предшествующих Unix, программы должны были явно подключаться к соответствующим устройствам ввода и вывода. Из-за специфических особенностей ОС это была утомительная задача программирования. Во многих системах необходимо было получить контроль над настройками среды, получить доступ к локальной таблице файлов, определить предполагаемый набор данных и правильно обращаться с оборудованием в случае устройства чтения перфокарт ,, магнитной ленты., дисковод, строчный принтер, перфорация карт или интерактивный терминал.

Одним из нескольких революционных достижений Unix были абстрактные устройства, которые избавили программу от необходимости знать или заботиться о том, с какими устройствами она взаимодействует. Старые операционные системы навязывали программисту структуру записи и часто неортогональную семантику данных и управление устройством. Unix устранил эту сложность с помощью концепции потока данных: упорядоченной последовательности байтов данных, которая может быть прочитана до конца файла. Программа также может записывать байты по желанию и без необходимости, и не может легко объявить их количество или группировку.

Другим прорывом Unix было автоматическое связывание ввода и вывода с клавиатурой терминала и дисплеем терминала, соответственно, по умолчанию - программа (и программист) абсолютно ничего не делала, чтобы установить ввод и вывод для типичного ввода-процесса-вывода. программа (если она не выбрала другую парадигму). Напротив, предыдущие операционные системы обычно требовали некоторого - часто сложного - языка управления заданиями для установления соединений, или эквивалентная нагрузка должна была быть организована программой.

Поскольку Unix предоставлял стандартные потоки, среда выполнения Unix C также была обязана поддерживать его. В результате большинство сред выполнения C (и потомки C ), независимо от операционной системы, обеспечивают эквивалентную функциональность.

Стандартный ввод (stdin)

Стандартный ввод - это поток, из которого программа считывает свои входные данные. Программа запрашивает передачу данных с помощью операции чтения. Не все программы требуют потокового ввода. Например, программы dir и ls (которые отображают имена файлов, содержащихся в каталоге) могут принимать аргументы командной строки, но выполнять свои операции без какого-либо потока ввод данных.

Если не перенаправлен на, стандартный ввод наследуется от родительского процесса. В случае интерактивной оболочки, которая обычно связана с keyboard.

. Файловый дескриптор для стандартного ввода равен 0 (нулю); POSIX определение: STDIN_FILENO; соответствующая переменная C - FILE * stdin; аналогично, переменная C ++ - это std :: cin.

Стандартный вывод (stdout)

Стандартный вывод - это поток, в который программа записывает свои выходные данные. Программа запрашивает передачу данных с операцией записи. Не все программы производят вывод. Например, команда переименовать файл (иначе называемая mv, move или ren ) не сообщает об успехе.

Если не перенаправлено, стандартный вывод наследуется от родительского процесса. В случае интерактивной оболочки это обычно текстовый терминал , инициировавший программу.

Файловый дескриптор для стандартного вывода равен 1 (единице); POSIX определение: STDOUT_FILENO; соответствующая переменная C - FILE * stdout; аналогично, переменная C ++ - это std :: cout.

Стандартная ошибка (stderr)

Стандартная ошибка - это еще один поток вывода, обычно используемый программами для вывода сообщений об ошибках или диагностика. Этот поток не зависит от стандартного вывода и может быть перенаправлен отдельно. Это решает проблему полупредиката , позволяя различать выходные данные и ошибки, и аналогично функции, возвращающей пару значений - см. Проблема полупредиката: многозначный возврат. Обычным местом назначения является текстовый терминал , который запустил программу, чтобы обеспечить максимальную вероятность быть увиденным, даже если стандартный вывод перенаправлен (что не всегда наблюдается). Например, вывод программы в конвейере перенаправляется на ввод следующей программы, но ошибки каждой программы по-прежнему поступают непосредственно в текстовый терминал.

Допустимо и нормально направлять стандартный вывод и стандартную ошибку в одно и то же место назначения, например, в текстовый терминал. Сообщения появляются в том же порядке, в каком их записывает программа, если только не используется буферизация. Например, в обычных ситуациях стандартный поток ошибок не буферизуется, но стандартный выходной поток буферизуется по строкам; в этом случае текст, записанный в стандартную ошибку позже, может появиться на терминале раньше, если буфер стандартного потока вывода еще не заполнен.

файловый дескриптор для стандартной ошибки определяется в POSIX как 2 (два); файл заголовка содержит символ STDERR_FILENO; соответствующая переменная C - FILE * stderr. Стандартный заголовок C ++ предоставляет две переменные, связанные с этим потоком: std :: cerrи std :: clog, первая из которых не буферизуется, а вторая использует тот же механизм буферизации, что и все остальные потоки C ++.

Оболочки в стиле Борна позволяют перенаправлять стандартную ошибку в то же место назначения, на которое направляется стандартный вывод с использованием оболочки в стиле

2>1

csh, позволяющей стандартной ошибке перенаправляться в то же место назначения, куда направляется стандартный вывод с использованием

>

Стандартная ошибка была добавлена ​​в Unix в 1970-х годах после того, как несколько потраченных впустую запусков фотонабора закончились тем, что сообщения об ошибках набирались вместо отображения на терминале пользователя.

Временная шкала

1950-е: Фортран

Фортран имеет эквивалент файловых дескрипторов Unix: По соглашению, многие реализации Фортрана используют номера единиц UNIT = 5для stdin, UNIT = 6для стандартного вывода и UNIT = 0для стандартного вывода. В 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 средства ввода и вывода в совокупности назывались средствами передачи. Костер координировал определение стандарта передачи. Модель включала три стандартных канала: стоять в, выделятьи стоять сзади.

Пример
# ALGOL 68 example # main :( REAL number; getf (stand in, ($ g $, number)); printf (($ "Number is:" g (6,4) "OR" $, number)); # OR # putf (stand out, ($ "Number - это : "g (6,4)"! "$, число)); новая строка (выделиться))
Ввод:Вывод:
3,14159
Число: +3,142 ИЛИ Число это: +3.142!

1970-е: C и Unix

В языке программирования C стандартные потоки ввода, вывода и ошибок присоединяются к существующим файловым дескрипторам Unix 0, 1 и 2 соответственно. В среде POSIX вместо магических чисел следует использовать определения <unistd.h >STDIN_FILENO, STDOUT_FILENO или STDERR_FILENO. Также предоставляются указатели на файлы stdin, stdout и stderr.

Кен Томпсон (разработчик и разработчик исходной операционной системы Unix) изменил sort в версии 5 Unix, чтобы принимать «-» как стандартный ввод, который распространяется на другие утилиты и стали частью операционной системы в виде специального файла в Версии 8. Диагностика была частью стандартного вывода в версии 6, после чего Деннис М. Ричи создал концепцию стандартной ошибки.

1995: Java

В Java стандартные потоки упоминаются как System.in (для стандартного ввода), System.out (для stdout) и System.err (для stderr).

public static void main (String args) {try {BufferedReader br = new BufferedReader (new InputStreamReader ( System.in)); Строка s = br.readLine (); двойное число = Double.parseDouble (s); System.out.println ("Число:" + число); } catch (Exception e) {System.err.println ("Ошибка:" + e.getMessage ()); }}

2000-е:.NET

В C # и других .NET языках стандартные потоки называются System.Console.In(для stdin), System.Console.Out(для stdout) и System.Console.Error(для stderr). Основные возможности чтения и записи для потоков 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.Console.In.ReadLine (); двойное число = double.Parse (s); System.Console.Out.WriteLine ("Число: {0: F3}", число); возврат 0; // Если Parse () сгенерировал исключение} catch (ArgumentNullException) {System.Console.Error.WriteLine ("Номер не был введен!"); } catch (FormatException) {System.Console.Error.WriteLine ("Указанное значение не является допустимым числом!"); } catch (OverflowException) {System.Console.Error.WriteLine («Указанное число слишком велико!»); } return -1; }
'Пример Visual Basic.NET. Открытая функция Main () как целое число Попробуйте Dim s As String = System.Console. [In].ReadLine () Dim number As Double = Double.Parse (s) System.Console.Out.WriteLine ("Number is: {0: F3}", number) Return 0 'Если Parse () выдал исключение Catch ex As System.ArgumentNullException System.Console. [Error].WriteLine ("Номер не был введен!") Перехватить ex2 как System.FormatException System.Console. [Error].WriteLine («Указанное значение не является допустимым числом!») Перехватить ex3 как System.OverflowException System.Console. [Ошибка].WriteLine («Указанное число слишком big! ") End Try Return -1 End Function

При применении класса System.Diagnostics.Process можно использовать экземпляр properties StandardInput, StandardOutputи StandardErrorэтого класса для доступа к стандартным потокам процесса.

Python

Python предоставляет файловые объекты, представляющие stdin, stdout и stderr. Мы можем показать, как мы можем использовать эти объекты для работы с вводом и выводом нашей программы.

sys.stdin

Модуль sys Python предоставляет нам все три файловых объекта для stdin, stdout и stderr. В качестве объекта входного файла мы используем sys.stdin. Это похоже на файл, где вы можете открывать и закрывать его, как и любой другой файл.

вот простой пример:


program stdin.py


import sys stdin_fileno = sys.stdin # Продолжает чтение из стандартного ввода и завершает работу, только если присутствует слово 'exit' # Этот цикл по умолчанию не завершается, поскольку stdin открыт для строки в stdin_fileno: # Удалите завершающие символы новой строки с помощью strip () if "exit" == line.strip (): print ("Найден выход. Завершение программы") exit (0) else : print ("Сообщение от sys.stdin: --->{} <---".format(line))

Использование:

$ printf" это \ n разные \ n слова "| python stdin.py Сообщение от sys.stdin: --->эти <--- Сообщение от sys.stdin: --->отличаются <--- Сообщение от sys.stdin: --->слова <--- 

Приведенный выше фрагмент продолжает считывать ввод со стандартного ввода и выводит сообщение в консоль ( stdout), пока не встретится слово exit. ПРИМЕЧАНИЕ. Обычно мы не закрываем объект файла stdin по умолчанию, хотя это разрешено. Таким образом, stdin_fileno.close () является допустимым кодом Python. Теперь, когда мы немного знаем о stdin, позвольте нам перейти на стандартный вывод.

sys.stdout

Для вывода ut, мы используем sys.stdout. Он похож на sys.stdin, но напрямую отображает все, что написано в нем, в консоли.

В приведенном ниже фрагменте показано, что мы получаем вывод в консоль, если пишем в sys.stdout.


программа stdout.py


import sys stdout_fileno = sys.stdout sample_input = ["Привет", "Привет из Python", "exit"] для ip в sample_input: # Печатает в stdout stdout_fileno.write (ip + " \ n ")

Для выполнения:. python stdout.py.

Вывод:. Привет. Привет от Python. exit.

sys.stderr

Это похож на sys.stdout, потому что он также выводит непосредственно в консоль. Но разница в том, что их можно использовать для печати сообщений об исключениях и ошибках, а также информационных / отладочных комментариев. (Вот почему это называется стандартной ошибкой). Это может быть очень полезно, когда вместо этого для записи данных используется стандартный вывод. Вот пример.


программа stderr.py


import sys stdout_fileno = sys.stdout stderr_fileno = sys.stderr sample_input = [«Привет», «Привет из Python», «exit»] для ip в sample_input: # Выводит на стандартный вывод # Пытается чтобы добавить целое число со строкой. Вызывает исключение try: stdout_fileno.write (ip + "\ n") # Перехватывает исключения, кроме: stderr_fileno.write ("Exception Occurred! \ N") stderr_fileno.write ("ip =" + ip) try: ip = ip + 100 # Перехватить все исключения, кроме: stderr_fileno.write ("Exception Occurred! Ip =" + ip + "\ n")

Для выполнения: python stderr.py

Вывод:. Hi. Произошло исключение! ip = Hi. Hello from Python. Произошла исключительная ситуация! ip = Hello from Python. exit. Произошло исключение! ip = exit.

Как вы могли заметить, для всех входных строк мы пытаемся добавить к целому числу, что вызовет исключение. Мы перехватываем все такие исключения и печатаем еще одно сообщение отладки с помощью sys.stderr.


Перенаправление к файлу

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

Следующий фрагмент перенаправляет вывод (stdout) в файл с именем Output.txt.

Итак, мы не увидим ничего, напечатанного в консоли, потому что теперь оно печатается в сам файл! В этом суть перенаправления вывода. Вы «перенаправляете» вывод в другое место. (На этот раз в Output.txt, а не в Консоль)

import sys # Сохраните текущий стандартный вывод, чтобы мы могли вернуть sys.stdout после # завершения перенаправления stdout_fileno = sys.stdout sample_input = ["Привет," "Hello from Python", "exit"] # Перенаправить sys.stdout в файл sys.stdout = open ("Output.txt", "w") для ip в sample_input: # Печать в перенаправленный stdout (Output.txt) sys.stdout.write (ip + '\ n') # Печатает в фактический сохраненный обработчик stdout stdout_fileno.write (ip + '\ n') # Закройте файл sys.stdout.close () # Восстановите sys.stdout на нашем старый обработчик сохраненных файлов sys.stdout = stdout_fileno

Вывод:

$ root @ ubuntu: ~ # python3 output_redirection.py Привет, привет от Python exit $ root @ ubuntu: ~ # cat Output.txt Привет, привет от Python exit

Как видите, мы распечатали вывод как в Консоль, так и в Output.txt. Сначала мы сохраняем исходный объект обработчика файла sys.stdout в другую переменную. Нам это нужно не только для восстановления sys.stdout в старом обработчике (указывающем на консоль), но мы также можем печатать на консоль, используя эту переменную! Обратите внимание, что после записи в файл мы закрываем его, аналогично тому, как мы закрываем файл, потому что этот файл все еще был открыт. Наконец, мы восстанавливаем обработчик sys.stdout в консоли, используя переменную stdout_fileno. Аналогичный процесс можно выполнить для перенаправления ввода и ошибок, заменив sys.stdout на sys.stdin или sys.stderr и работая с входами и исключениями вместо вывода. Здесь было описано использование stdin, stdout и stderr в Python с использованием модуля sys. А также, как управлять соответствующими обработчиками файлов для перенаправления в / из файла.

GUI

Графические пользовательские интерфейсы (GUI) не всегда используют стандартные потоки, они используются, когда GUI являются оболочками базовых скриптов и / или консольных программ, например git-cola git GUI https://git-cola.github.io или графический интерфейс менеджера пакетов synaptic, который обертывает команды apt в debian и / или ubuntu. Перенаправление программ с графическим интерфейсом пользователя не всегда практично и полезно. Графические интерфейсы пользователя, созданные с помощью инструментов сценариев, таких как zenity zenity и kdialog от проекта KDE или qdialog, вместо этого используют stdin, stdout и stderr, такие графические интерфейсы более удобны. простой в реализации и использовании также из-за природы сценариев, вместо полного графического интерфейса, запрограммированного и скомпилированного на C / C ++ с использованием qt или gtk или другой эквивалентной проприетарной структуры виджетов. Существует некоторая аналогия со стандартным обменом потоками в программах с чистым графическим интерфейсом, вероятно, при вырезании (или копировании) текстовых панелей одного приложения и вставке в другое, но, поскольку требуются ручные операции пользователя, перемещение большого количества паст неэффективно, поэтому Связь stdin / stdout настолько важна в сценариях конвейера, что также может управляться программами с графическим интерфейсом пользователя и завершаться программами графических визуализаторов. Меню Services, реализованное в NeXTSTEP и Mac OS X, также аналогично стандартным потокам. В этих операционных системах графические приложения могут предоставлять функции через общесистемное меню, которое работает с текущим выбором в графическом интерфейсе, независимо от того, в каком приложении.

Некоторые программы с графическим интерфейсом пользователя, в основном в Unix, по-прежнему записывают отладочную информацию в стандартные ошибки. Другие (например, многие медиаплееры Unix) могут читать файлы со стандартного ввода. Популярные программы Windows, которые открывают отдельное окно консоли в дополнение к своим окнам графического интерфейса, являются эмуляторами, а DOSBox.

GTK-сервер может использовать стандартный ввод как интерфейс связи с интерпретируемой программой для реализации графического интерфейса.

Парадигма Common Lisp Interface Manager "представляет" элементы графического интерфейса пользователя, отправленные в расширенный выходной поток.

См. Также

Ссылки

Источники

Внешние ссылки

Последняя правка сделана 2021-06-09 07:39:20
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте