Выбрать главу

Операция перенаправления стандартного потока ошибок из командной строки выглядит несколько сложнее и хуже переносится. В большинстве Unix-подобных систем перехватить вывод в поток stderr обычно можно с помощью операции перенаправления вида command > output 2>&1. Однако в некоторых версиях Windows она не действует, и даже в некоторых оболочках для Unix она может иметь другой вид - за дополнительной информацией обращайтесь к страницам справочного руководства по вашей оболочке.

Возможность перенаправления с помощью функции print

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

print(stuff, file=afile) # afile - это объект, а не имя строковой переменной

выведет stuff в afile, а не в поток sys.stdout. По своему действию это напоминает присваивание объекта переменной sys.stdout, но в данном случае отпадает необходимость сохранять и восстанавливать первоначальное значение, чтобы вернуться к использованию оригинального потока вывода (как было показано в разделе, описывающем перенаправление потоков в объекты). Например:

import sys

print(‘spam’ * 2, file=sys.stderr)

выведет текст в объект стандартного потока ошибок, а не в sys.stdout, причем такое перенаправление будет действовать только для данного вызова функции print. Следующий вызов функции print (без аргумента file) выведет текст в стандартный поток вывода, как обычно. Точно так же в качестве выходного файла можно передать свой собственный объект или экземпляр класса из стандартной библиотеки:

>>> from io import StringIO >>> buff = StringIO()

>>> print(42, file=buff)

>>> print('spam', file=buff)

>>> print(buff.getvalue())

42

spam

>>> from redirect import Output >>> buff = Output()

>>> print(43, file=buff)

>>> print('eggs', file=buff)

>>> print(buff.text)

43

eggs

Другие варианты перенаправления: еще раз об os.popen и subprocess

Ближе к концу предыдущей главы мы впервые встретились с функцией os.popen и родственной ей subprocess.Popen, которые предоставляют возможность перенаправления потоков ввода-вывода других команд из программы на языке Python. Как мы видели, эти инструменты могут использоваться для выполнения команд оболочки (например, команд, которые обычно вводятся с клавиатуры в ответ на приглашение DOS или csh), и они возвращают объект Python, похожий на файл, соединенный с потоком вывода команды, - чтение из объекта файла позволяет сценарию принимать вывод другой программы. Однако эти инструменты могут также использоваться для соединения с потоками ввода.

Благодаря этому функцию os.popen и инструменты из модуля subprocess можно рассматривать как еще один способ перенаправления потоков порождаемых программ, родственный только что рассмотренным приемам. Их действие во многом похоже на действие оператора | объединения команд в конвейер (фактически имена этих инструментов означают «pipe open» - «открыть канал»), но они выполняются внутри сценария и предоставляют схожий с файлами интерфейс к потокам данных, связанных каналом. По духу они близки функции redirect, но запускают не функции, а программы, и потоки ввода-вывода обрабатываются в порождающем сценарии как файлы (не привязанные к объектам классов). Эти инструменты перенаправляют потоки ввода-вывода программ, запускаемых сценарием, а не самого сценария.

Перенаправление ввода или вывода с помощью os.popen

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

C:\...\PP4E\System\Streams> type hello-out.py print(‘Hello shell world’)

C:\...\PP4E\System\Streams> type hello-in.py inp = input()

open(‘hello-in.txt’, ‘w’).write(‘Hello ‘ + inp + ‘\n’)

Эти сценарии могут запускаться из командной строки, как обычно:

C:\...\PP4E\System\Streams> python hello-out.py Hello shell world

C:\...\PP4E\System\Streams> python hello-in.py Brian

C:\...\PP4E\System\Streams> type hello-in.txt Hello Brian

В предыдущей главе мы видели, что сценарии на языке Python могут также читать вывод других программ и подобных им сценариев, как показано ниже:

C:\...\PP4E\System\Streams> python >>> import os

>>> pipe = os.popen('python hello-out.py') # ‘r’ - по умолчанию, чтение stdout