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

import sys

def getreply():

?n

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

C:\...\PP4E\System\Streams> python moreplus.py < moreplus.py

обеспечивает постраничный вывод в stdout содержимого строки, файла или потока; если запускается как самостоятельный сценарий, обеспечивает постраничный вывод содержимого потока stdin или файла, имя которого указывается в виде аргумента командной строки; когда входные данные поступают через поток stdin, исключается возможность использовать его для получения ответов пользователя - вместо этого можно использовать платформозависимые инструменты или графический интерфейс;

import sys

def getreply():

?n

C:\...\PP4E\System\Streams> type moreplus.py | python moreplus.py

обеспечивает постраничный вывод в stdout содержимого строки, файла или потока; если запускается как самостоятельный сценарий, обеспечивает постраничный вывод содержимого потока stdin или файла, имя которого указывается в виде аргумента командной строки; когда входные данные поступают через поток stdin, исключается возможность использовать его для получения ответов пользователя - вместо этого можно использовать платформозависимые инструменты или графический интерфейс;

import sys

def getreply():

?n

Наконец, если вывод одного сценария отправляется по каналу на ввод другого, все работает как надо, и при этом взаимодействие с пользователем не вызывает нарушений (и вовсе не потому, что нам просто повезло):

......\System\Streams> python teststreams.py < input.txt | python moreplus.py

Hello stream world Enter a number>8 squared is 64 Enter a number>6 squared is 36 Enter a number>Bye

Здесь стандартный вывод одного сценария подается на стандартный ввод другого сценария, находящегося в том же каталоге: moreplus.py читает вывод teststreams.py.

Все перенаправления в таких командах действуют только потому, что сценариям безразлично, чем в действительности являются стандартный ввод и вывод - консолью, файлами или каналами между программами. Например, при запуске moreplus.py как самостоятельного сценария он просто читает поток sys.stdin; командная оболочка (например, DOS в Windows, csh в Linux) прикрепляет такие потоки к источникам, определяемым командой, перед запуском сценария. Для доступа к этим источникам сценарии используют заранее открытые объекты файлов stdin и stdout, независимо от их истинной природы.

Для читателей, ведущих подсчет: мы запускали один сценарий постраничного вывода more четырьмя различными способами - импортируя и вызывая его функцию, передавая имя файла через аргумент командной строки, перенаправляя stdin в файл и передавая вывод команды по каналу в stdin. Благодаря возможности импортировать функции, принимать аргументы командной строки и получать ввод через стандартные потоки системные инструменты Python можно повторно использовать в разнообразных режимах.

Перенаправление потоков в объекты Python

Все приведенные выше способы перенаправления стандартных потоков действуют для программ, написанных на любом языке программирования, который обеспечивает возможность перехватывать стандартные потоки, и зависят скорее от процессора командной строки оболочки, чем от самого интерпретатора. Операции перенаправления в командной строке, такие как < filename и | program, обрабатываются оболочкой, а не интерпретатором Python. Более «питонистый» способ перенаправления можно реализовать в самих сценариях, присваивая переменным sys.stdin и sys.stdout объекты, похожие на файлы.

Это возможно благодаря тому, что любой объект, который набором методов напоминает файл, может выступать в роли стандартного потока. Важен не конкретный тип объекта, а его интерфейс (иногда его называют протоколом). Это означает следующее:

•    Любой объект, обладающий методами чтения, может быть присвоен переменной sys.stdin, в результате чего ввод будет осуществляться через методы чтения этого объекта.

•    Любой объект, обладающий методами записи, может быть присвоен переменной sys.stdout; в результате весь стандартный вывод будет отправляться методам этого объекта.

Так как функции print и input просто вызывают методы write и readline объектов, на которые ссылаются sys.stdout и sys.stdin, мы можем генерировать и перехватывать стандартные текстовые потоки с помощью объектов, реализованных с помощью классов.