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

Если потребуется принимать входные данные из stdin и использовать консоль для взаимодействия с пользователем, в сценарий нужно будет внести дополнительные изменения: нам придется отказаться от использования функции input и задействовать специальные интерфейсы для чтения ответов пользователя непосредственно с клавиатуры. В Windows такую возможность обеспечивает модуль msvcrt, входящий в состав стандартной библиотеки Python; в большинстве Unix-подобных систем достаточно будет использовать файл устройства /dev/tty.

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

Пример 3.8. PP4E\System\Streams\moreplus.py

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

import sys def getreply():

читает клавишу, нажатую пользователем,

даже если stdin перенаправлен в файл или канал

if sys.stdin.isatty():    # если stdin связан с консолью,

return input(‘?’)    # читать ответ из stdin

else:

if sys.platform[:3] == ‘win’: #    если stdin был перенаправлен,

import msvcrt    #    его нельзя использовать для чтения

msvcrt.putch(b’?’)    #    ответа пользователя

key = msvcrt.getche()    #    использовать инструмент консоли

msvcrt.putch(b’\n’)    #    getch(), которая не выводит символ

return key    #    для нажатой клавиши

else:

assert False, ‘platform not supported’

#для Linux: open(‘/dev/tty’).readline()[:-1]

def more(text, numlines=10):

реализует постраничный вывод содержимого строки в stdout

lines = text.splitlines() while lines:

chunk = lines[:numlines]

lines = lines[numlines:]

for line in chunk: print(line)

if lines and getreply() not in [b’y’, b’Y’]: break

if name == ‘ main ’:    # если выполняется, а не импортируется

if len(sys.argv) == 1:    # если нет аргументов командной строки

more(sys.stdin.read())    # вывести содержимое stdin

else:

more(open(sys.argv[1]).read()) # иначе вывести содержимое файла

Большая часть нововведений этой версии находится в функции getreply Метод файла isatty сообщает, соединен ли stdin с консолью, - если да функция просто считывает ответ из stdin, как и раньше. Конечно, по добная дополнительная логика необходима только в сценариях, предусматривающих возможность взаимодействия с пользователем и получения входных данных из stdin. В приложениях с графическим интерфейсом можно было бы, например, выводить диалог, реализовать обработку событий от клавиатуры в виде функций обратного вызова и так далее (знакомиться с графическими интерфейсами мы будем в главе 7).

Имея на вооружении функцию getreply, можно спокойно запускать утилиту moreplus различными способами. Как и прежде, можно импортировать и непосредственно вызывать функцию этого модуля, передавая ей ту строку, которую требуется вывести постранично:

>>> from moreplus import more

>>> more(open('adderSmall.py').readO)

import sys

print(sum(int(line) for line in sys.stdin))

И так же, как и прежде, при запуске с аргументом командной строки этот сценарий интерактивно будет пролистывать текст указанного файла:

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

import sys

print(sum(int(line) for line in sys.stdin))

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

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