К сожалению, я должен особо отметить тот факт, что поддержка выгрузки файлов в модели CGI, реализованной в стандартной библиотеке, была частично нарушена в Python 3.1. Если говорить кратко, в настоящее время внутренняя реализация модуля cgi возбуждает исключение, если попытаться выгрузить на сервер двоичные данные или текст в несовместимой кодировке. Это исключение возникает еще до того, как сценарий получит возможность вмешаться, что делает невозможной реализацию обходных решений. Выгрузка файлов в модели CGI в версии Python 2.X действовала потому, что строки могли обрабатывать двоичные данные, но в современной версии 3.X возникает ошибка.
Отчасти данная потеря функциональности проистекает из того факта, что модуль cgi использует механизм анализа, реализованный в пакете email, для извлечения входных данных, состоящих из нескольких частей, и потому испытывает те же самые проблемы, свойственные пакету email, о которых подробно рассказывалось в главе 13. Механизм анализа в пакете email ожидает получить полный текст сообщения в виде строки str, что может приводить к ошибкам в реализации поддержки модели CGI, при выгрузке некоторых типов данных. Как отмечалось в главе 13, при выгрузке файлов через CGI они могут содержать смесь текстовых и двоичных данных — включая исключительно двоичные данные, не преобразованные в формат MIME, текст в любой возможной кодировке и произвольные их комбинации. Требование текущей версии пакета email декодировать эти данные в строку str для анализа является совершенно несовместимым, хотя, похоже, что и сам модуль cgi в некоторых случаях действует не совсем корректно.
Если у вас появится желание своими глазами увидеть, в каком виде данные выгружаются броузерами, откройте и попробуйте выполнить файлы HTML и Python с именами test-cgiu-uploads-bug*, включенные в пакет примеров, и с их помощью выгрузить текст, двоичные и смешанные данные:
• test-cgi-uploads-bug.html/py пытается выполнить анализ обычным способом, который дает положительные результаты для некоторых типов текстовых файлов, но всегда терпит неудачу при попытке декодировать двоичные файлы
• test-cgi-uploads-bug0.html/py пытается использовать двоичный режим при работе с входным потоком, но всегда терпит неудачу с ошибкой, сообщающей о недопустимом типе, для обоих типов файлов, текстовых и двоичных, из-за того, что пакет email ожидает получить данные в виде строки str
• test-cgi-uploads-bug1.html/py сохраняет входной поток с единственным файлом
• test-cgi-uploads-bug.html/py сохраняет входной поток с несколькими файлами
Последние два сценария в этом списке просто читают и сохраняют данные в двоичном режиме в файл для дальнейшего просмотра и отображают два заголовка, переданных в переменных окружения, которые используются при анализе (тип содержимого «multipart/form-data» и объем данных). Попытка проанализировать сохраняемые входные данные с помощью модуля cgi будет терпеть неудачу, если только это не будут текстовые данные в совместимой кодировке. В действительности, из-за того, что данные могут представлять собой произвольную смесь текста и двоичных данных, корректный механизм анализа должен будет читать их в двоичном режиме и свободно переключаться между текстовым и двоичным режимами в процессе анализа.
Весьма вероятно, что такое положение дел улучшится в будущем, но, скорее всего, не ранее, чем в версии Python 3.3 или выше. Даже спустя почти два года после выхода версии 3.0 эта книга играет роль бета-тестера гораздо чаще, чем могла бы. В первую очередь это обусловлено тем, что разделение типов str/bytes в Python 3.X не получило полной реализации в стандартной библиотеке Python к моменту появления этой версии. Конечно, это не означает, что нужно относиться с пренебрежением к тем, кто тратил свое время и силы на создание версии 3.X. Тем не менее, для меня, принадлежащего к числу тех, кто помнит еще версию 0.X, эта ситуация выглядит далекой от идеала.
Разработка программного кода взамен модуля cgi и используемого им пакета email — единственное настоящее решение всех проблем — практически невозможная задача для этой книги. Поэтому пока сценарии CGI, выполняющие выгрузку файлов и реализованные в этой книге, будут работать только с текстовыми файлами и только с текстом в совместимой кодировке. Это распространяется и на вложения электронной почты, выгружаемые с помощью веб-приложения электронной почты PyMailCGI, рассматриваемого в следующей главе, — еще одна причина, почему в этом издании этот пример не был дополнен новыми функциональными возможностями, как это произошло с приложением PyMailGUI из предыдущей главы. Отсутствие возможности прикреплять таким способом изображения к электронным письмам — это серьезное ограничение, которое сужает область применения в целом.
Обновления, которые, возможно, в будущем справятся с этой проблемой, ищите на веб-сайте книги (описывается в предисловии). Исправления, вероятно, окажутся несовместимыми с текущим прикладным интерфейсом библиотечных модулей, но такова действительность в мире разработки программного обеспечения, за исключением случаев, когда новая система пишется с чистого листа. (А «бегство» — это не выход…)
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011