Марк Лутц - Изучаем Python, Четвертое издание (1184811), страница 93
Текст из файла (страница 93)
Но вам и в этом случае необходимо вручную восстановить sys.stdout в первоначальное значение sys.__stdout__, чтобы вернуться к оригинальномупотоку вывода. За дополнительными подробностями обращайтесь к описанию модуля sys в руководстве по стандартной библиотеке.370Глава 11. Присваивание, выражения и printПотребность в таком перенаправлении возникает на удивление часто, а ручноесохранение и восстановление оригинального потока вывода – процедура достаточно сложная, что привело к появлению расширения для инструкции print,которое делает такое перенаправление ненужным.В версии 3.0 именованный аргумент file позволяет перенаправить в файл вывод единственного вызова функции print, не прибегая к переустановке значения sys.stdout.
Так как такое перенаправление носит временный характер,обычные вызовы функции print продолжают выводить текст в оригинальныйпоток вывода. В версии 2.6 того же эффекта можно добиться, указав в началеинструкции print символы >> и вслед за ними – объект файла (или другой совместимый объект). Например, следующий фрагмент выводит текст в файл log.txt:log = open(‘log.txt’, ‘a’)print(x, y, z, file=log)print(a, b, c)# 3.0# Вывести в объект, напоминающий файл# Вывести в оригинальный поток выводаlog = open(‘log.txt’, ‘a’)print >> log, x, y, zprint a, b, c# 2.6# Вывести в объект, напоминающий файл# Вывести в оригинальный поток выводаЭти способы перенаправления удобно использовать, когда в одной и той же программе необходимо организовать вывод и в файл, и в стандартный поток вывода.
Однако если вы собираетесь использовать эти формы вывода, вам потребуется создать объект-файл (или объект, который имеет метод write, как и объектфайла) и передавать инструкции этот объект, а не строку с именем файла:C:\misc> c:\python30\python>>> log = open(‘log.txt’, ‘w’)>>> print(1, 2, 3, file=log) # В 2.6: print >> log, 1, 2, 3>>> print(4, 5, 6, file=log)>>> log.close()>>> print(7, 8, 9)# В 2.6: print 7, 8, 97 8 9>>> print(open(‘log.txt’).read())1 2 34 5 6Эти расширенные формы инструкции print нередко используются для вывода сообщений об ошибках в стандартный поток ошибок, sys.stderr. Вы можетелибо использовать его метод write и форматировать выводимые строки вручную, либо использовать синтаксис перенаправления:>>> import sys>>> sys.stderr.write((‘Bad!’ * 8) + ‘\n’)Bad!Bad!Bad!Bad!Bad!Bad!Bad!Bad!>>> print(‘Bad!’ * 8, file=sys.stderr) # В 2.6: print >> sys.stderr, ‘Bad’ * 8Bad!Bad!Bad!Bad!Bad!Bad!Bad!Bad!Теперь, когда вы знаете все о перенаправлении вывода, эквивалентность функции print и метода write файлов должна показаться вам очевидной.
В следующем примере демонстрируется вывод текста обоими способами в версии 3.0,затем демонстрируется перенаправление вывода во внешний файл и выполняется проверка содержимого текстовых файлов:371Операция print>>>>>>1 2>>>>>>1 24>>>X = 1; Y = 2print(X, Y)>>>4>>>b’1>>>b’1open(‘temp2’, ‘w’).write(str(X) + ‘ ‘ + str(Y) + ‘\n’) # Запись в файл# Вывод: простой способimport sys# Вывод: сложный способsys.stdout.write(str(X) + ‘ ‘ + str(Y) + ‘\n’)print(X, Y, file=open(‘temp1’, ‘w’))print(open(‘temp1’, ‘rb’).read())2\r\n’print(open(‘temp2’, ‘rb’).read())2\r\n’# Перенаправление в файл# Двоичный режимКак видите, для отображения текста лучше пользоваться операцией print,если только вы не получаете особое удовольствие от ввода с клавиатуры.
Другой пример, демонстрирующий эквивалентность использования операцииprint и метода write файлов, – пример имитации функции print для Python версий 2.6 и более ранних, вы найдете в главе 18.Реализация вывода,не зависящая от версии интерпретатораНаконец, для тех, кто не может ограничиться только версией Python 3.0 и ищетспособ организации вывода, совместимый с 3.0, имеется несколько вариантовна выбор.
Первый состоит в том, чтобы использовать инструкции print для версии 2.6 и затем автоматически преобразовывать их в эквивалентные вызовыфункции print для версии 3.0 с помощью сценария 2to3. Дополнительные подробности об этом сценарии вы найдете в документации к ���������������������Python��������������� 3.0 – он пытается преобразовать программный код, написанный для версии 2.X, так, чтобыон мог выполняться под управлением Python 3.0.Второй заключается в том, чтобы использовать функцию print для версии 3.0в программах, выполняющихся под управлением ������������������������Python������������������ 2.6, включив возможность использования этой функции с помощью инструкции:from __future__ import print_functionЭта инструкция включает поддержку разновидности инструкции print в интерпретаторе Python 2.6, которая точно соответствует функции print в версии 3.0. Благодаря этому вы сможете использовать все возможности функцииprint в версии 2.6, и при этом позднее вам не придется менять операции выводапри переходе на новую версию 3.0.Кроме�������������������������������������������������������������������того��������������������������������������������������������������������������������������������������������������������������������, имейте������������������������������������������������������������������������������������������������������������������в��������������������������������������������������������������������������������������������������������� ���������������������������������������������������виду�����������������������������������������������, что���������������������������������������������������������������������������������������простые���������������������������������������������������������������������������случаи������������������������������������������������������������использования���������������������������������������операции����������������вы���вода, как в первой строке табл. 11.5, будут действовать в любой версии Python.Благодаря тому, что синтаксис языка позволяет заключать в круглые скобкилюбые выражения, мы всегда можем имитировать вызов функции print версии 3.0 в программном коде для версии 2.6, просто добавив скобки.
Единственный недостаток такого подхода состоит в том, что он образует кортеж из выводимых объектов, когда их более одного – в выводимом тексте они будут заключены в круглые скобки. В версии 3.0, например, в круглых скобках, в вызовефункции, может быть указано произвольное количество объектов:372Глава 11. Присваивание, выражения и printC:\misc> c:\python30\python>>> print(‘spam’)# Синтаксис вызова функции print в 3.0spam>>> print(‘spam’, ‘ham’, ‘eggs’) # Вызов с нескольким аргументамиspam ham eggsВ первом случае в версии 2.6 результат будет тот же самый, но во втором случаебудет создан кортеж:C:\misc> c:\python26\python>>> print(‘spam’)# 2.6: использование скобок в инструкцииspam>>> print(‘spam’, ‘ham’, ‘eggs’) # В действительности – это объект кортежа!(‘spam’, ‘ham’, ‘eggs’)Чтобы обеспечить настоящую независимость от версии интерпретатора, необходимо сначала сконструировать строку, используя оператор форматированиястрок, или метод format, или другие инструменты для работы со строками, с которыми мы познакомились в главе 7:>>> print(‘%s %s %s’ % (‘spam’, ‘ham’, ‘eggs’))spam ham eggs>>> print(‘{0} {1} {2}’.format(‘spam’, ‘ham’, ‘eggs’))spam ham eggsРазумеется, если имеется возможность пользоваться исключительно версиейPython 3.0, можно вообще позабыть о способах обеспечения совместимостиверсий.
Однако многим программистам придется еще не раз столкнуться илиписать программный код для версии Python 2.X.На протяжении всей книги я использую функцию print в версии Python 3.0. Обычно я буду предупреждать, что при опробовании примеров в интерпретаторе версии 2.6 в выводе могутпоявиться дополнительные круглые скобки, потому что при наличии нескольких элементов образуется кортеж, но иногда я небуду делать этого, поэтому считайте это примечание предупреждением – если вы увидите дополнительные круглые скобкив выводе при опробовании примеров в интерпретаторе версии 2.6, то либо опустите скобки в инструкции print, либо перепишите инструкции вывода, используя приемы обеспечениясовместимости, описанные здесь, либо попытайтесь полюбитьэти лишние скобки.Придется держать в уме: print и stdoutЭквивалентность инструкции print и метода write объекта sys.stdoutимеет большое значение. Она позволяет перенаправить объект sys.stdout в определяемый пользователем объект, который поддерживает тотже самый метод write, что и файлы.
Так как инструкция print всеголишь передает текст методу sys.stdout.write, вы можете перехватыватьвыводимый текст, перенаправив sys.stdout в объект, обладающий методом write для обработки текста.Операция print373Например, можно отправить текст в окно графического интерфейса илиотправить его в несколько мест, определив объект с методом write, который выполнит все необходимые действия. Пример использования такой возможности вы увидите в шестой части этой книги, когда мы будемизучать классы, но в общих чертах это выглядит примерно так:class FileFaker:def write(self, string):# Выполнить какие-либо действия со строкойimport syssys.stdout = FileFaker()print someObjects# Передает строку методу write классаЭтот прием возможен благодаря тому, что инструкция print является тем, что в следующей части книги мы назовем полиморфной операцией, – она не интересуется тем, что из себя представляет объект sys.stdout, ей нужен всего лишь метод (то есть интерфейс) с именем write.Такое перенаправление в объекты может быть реализовано еще прощес помощью именованного аргумента file в версии 3.0 и расширеннойформы >> инструкции print в версии 2.6, благодаря чему нам не требуется явно перенаправлять объект sys.stdout – обычные операции выводапо-прежнему будут выводить текст в объект sys.stdout:myobj = FileFaker() # 3.0: Перенаправление вывода для одной инструкцииprint(someObjects, file=myobj) # Не влияет на объект sys.stdoutmyobj = FileFaker() # 2.6: Перенаправление вывода для одной инструкцииprint >> myobj, someObjects# Не влияет на объект sys.stdoutВстроенная функция input в языке Python читает данные из файла sys.stdin, благодаря чему существует возможность перенаправить ввод аналогичным образом, используя классы, реализующие метод read.
Смотрите пример использования функции input и цикла while, который приводится в главе 10, чтобы лучше представлять себе, о чем речь.Обратите внимание, что вывод текста осуществляется в поток stdout, – этообеспечивает возможность вывода документов HTML в CGI-сценариях.Кроме того, это позволяет выполнить перенаправление ввода и выводадля сценария на языке Python обычными средствами командной строкиоперационной системы:python script.py < inputfile > outputfilepython script.py | filterProgramМеханизм перенаправления операций вывода в языке Python является альтернативой этим видам перенаправления средствами команднойоболочки.374Глава 11.