Как веб-фреймворки Python, WSGI и CGI подходят друг другу

150

У меня есть учетная запись Bluehost, где я могу запускать скрипты Python как CGI. Я думаю, это самый простой CGI, потому что для запуска мне нужно определить следующее в .htaccess:

Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py

Теперь, когда я смотрю веб-программирование на Python, я много слышу о WSGI и о том, как его использует большинство фреймворков. Но я просто не понимаю, как все это сочетается, особенно когда мой веб-сервер (Apache работает на компьютере хоста), а не то, с чем я действительно могу играть (кроме определения .htaccessкоманд).

Как связаны между собой WSGI , CGI и фреймворки? Что мне нужно знать, устанавливать и делать, если я хочу запустить веб-фреймворк (скажем, web.py или CherryPy ) в моей базовой конфигурации CGI? Как установить поддержку WSGI?

Эли Бендерский
источник

Ответы:

242

Как WSGI, CGI и фреймворки связаны между собой?

Apache прослушивает порт 80. Получает HTTP-запрос. Он анализирует запрос, чтобы найти способ ответить. Апач имеет много вариантов ответа. Один из способов ответа - использовать CGI для запуска скрипта. Другой способ ответить - просто подать файл.

В случае CGI Apache подготавливает среду и вызывает сценарий по протоколу CGI. Это стандартная ситуация Unix Fork / Exec - подпроцесс CGI наследует среду ОС, включая сокет и стандартный вывод. Подпроцесс CGI записывает ответ, который возвращается к Apache; Apache отправляет этот ответ в браузер.

CGI примитивен и раздражает. Главным образом потому, что он разветвляет подпроцесс для каждого запроса, а подпроцесс должен закрыть или закрыть stdout и stderr, чтобы обозначить конец ответа.

WSGI - это интерфейс, основанный на шаблоне проектирования CGI. Это не обязательно CGI - он не должен обрабатывать подпроцесс для каждого запроса. Это может быть CGI, но это не обязательно.

WSGI добавляет в шаблон проектирования CGI несколько важных способов. Он анализирует заголовки HTTP-запросов и добавляет их в среду. Он предоставляет любой POST-ориентированный ввод в виде файлового объекта в среде. Он также предоставляет вам функцию, которая будет формулировать ответ, избавляя вас от большого количества деталей форматирования.

Что мне нужно знать / установить / сделать, если я хочу запустить веб-фреймворк (скажем, web.py или cherrypy) в моей базовой конфигурации CGI?

Напомним, что разветвление подпроцесса стоит дорого. Есть два способа обойти это.

  1. Встраивает mod_wsgi или mod_pythonвстраивает Python в Apache; ни один процесс не разветвлен. Apache запускает приложение Django напрямую.

  2. Демон mod_wsgi или mod_fastcgiпозволяет Apache взаимодействовать с отдельным демоном (или «длительным процессом»), используя протокол WSGI. Вы запускаете длительный процесс Django, а затем настраиваете Apache mod_fastcgi для связи с этим процессом.

Обратите внимание, что mod_wsgiможет работать в любом режиме: встроенный или демон.

Когда вы прочитаете о mod_fastcgi, вы увидите, что Django использует flup для создания WSGI-совместимого интерфейса на основе информации, предоставленной mod_fastcgi. Трубопровод работает так.

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

У Django есть несколько «django.core.handlers» для различных интерфейсов.

Для mod_fastcgi Django предоставляет объект, manage.py runfcgiкоторый интегрирует FLUP и обработчик.

Для mod_wsgi для этого есть основной обработчик.

Как установить поддержку WSGI?

Следуйте этим инструкциям.

https://code.google.com/archive/p/modwsgi/wikis/IntegrationWithDjango.wiki

Для фона см. Это

http://docs.djangoproject.com/en/dev/howto/deployment/#howto-deployment-index

С. Лотт
источник
4
Я не могу установить mod_wsgi, потому что я на виртуальном хостинге. Все, что у меня есть, это поддержка fcgi. Как я могу по-прежнему запускать приложения WSGI через него?
Эли Бендерский
3
+1 Это отличный ответ и ответы на многие (но не все) вопросы, которые я имею в виду. Этот ответ еще не завершен. Вы хорошо объяснили о CGI и WSGI, но какова связь и различия между FASTCGI и WSGI? Что лучше? Как они работают? Как mod_python попал в картину?
когти
14
S.Lott вместо того, чтобы жаловаться на то, что когда люди спрашивают, что «лучше», почему бы просто не заявить, что «mod_wsgi лучше как X, fastcgi лучше для Y», и если у ОП есть более конкретные вопросы, они будут задавать.
Грегг Линд
7
@ Грег Линд: Почему бы просто не заявить, что "mod_wsgi лучше как X, fastcgi лучше для Y"? Потому что это не очень легко сделать. Существуют десятки нефункциональных факторов качества, которые являются элементами наборов X и Y. Трудно перечислить их все. Для людей гораздо лучше задавать конкретные вопросы о факторах качества, которые имеют отношение к делу.
S.Lott
4
Только для заметок: опция runfcgi устарела с версии 1.7, а поддержка FastCGI была удалена в Django 1.9.
OBu
58

Я думаю, что ответ Флориана отвечает на ваш вопрос о том, что такое WSGI, особенно если вы читаете PEP .

Что касается вопросов, которые вы ставите ближе к концу:

WSGI, CGI, FastCGI и т. Д. - все это протоколы для веб-сервера для запуска кода и доставки динамического контента, который создается. Сравните это со статической веб-службой, где обычный HTML-файл в основном доставляется клиенту.

CGI, FastCGI и SCGI не зависят от языка. Вы можете писать CGI-скрипты на Perl, Python, C, Bash, что угодно. CGI определяет , который исполняемый файл будет называться, на основе URL, и как она будет называться: аргументы и окружающей среды. Он также определяет, как возвращаемое значение должно быть передано обратно на веб-сервер после завершения вашего исполняемого файла. Варианты - это в основном оптимизация, позволяющая обрабатывать больше запросов, снижать задержку и т. Д .; основная концепция та же самая.

WSGI - это только Python. Вместо протокола, независимого от языка, определяется стандартная сигнатура функции:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

Это полное (если ограниченное) приложение WSGI. Веб-сервер с поддержкой WSGI (например, Apache с mod_wsgi) может вызывать эту функцию всякий раз, когда поступает запрос.

Причина, по которой это так здорово, заключается в том, что мы можем избежать грязного шага преобразования HTTP GET / POST в CGI в Python и обратно на выход. Это гораздо более прямая, чистая и эффективная связь.

Кроме того, намного проще иметь долговременные фреймворки, работающие за веб-серверами, если все, что нужно сделать для запроса, - это вызов функции. При использовании простого CGI вам придется запускать всю структуру для каждого отдельного запроса.

Чтобы иметь поддержку WSGI, вам необходимо установить модуль WSGI (например, mod_wsgi ) или использовать веб-сервер с встроенным WSGI (например, CherryPy ). Если ни то, ни другое невозможно, вы можете использовать мост CGI-WSGI, указанный в PEP.

Джеймс Брейди
источник
3
Чья это глупая идея - не делать язык WSGI независимым? Какой смысл тогда? Можно также отправить весь Python как модуль Apache.
Салман фон Аббас
2
@ SalmanPK Я думаю, что это просто компромисс. Конечно, нелегко (если не невозможно) создать независимый от языка протокол, который можно использовать, просто реализуя функцию на выбранном языке.
phunehehe
21

Вы можете запустить WSGI через CGI, как показано в примере Pep333 . Однако каждый раз, когда появляется запрос, запускается новый интерпретатор Python, и необходимо создавать весь контекст (соединения с базой данных и т. Д.), Что занимает много времени.

Лучше всего, если вы захотите запустить WSGI, если бы ваш хост установил mod_wsgi и выполнил соответствующую конфигурацию, чтобы перенести управление на ваше приложение.

Flup - это еще один способ работы с WSGI для любого веб-сервера, который может говорить на FCGI , SCGI или AJP. Из моего опыта действительно работает только FCGI, и он может быть использован в Apache либо через mod_fastcgi, либо если вы можете запустить отдельный демон Python с mod_proxy_fcgi .

WSGI - это протокол, очень похожий на CGI, который определяет набор правил взаимодействия веб-сервера и кода Python, он определяется как Pep333 . Это позволяет многим различным веб-серверам использовать множество различных сред и приложений, использующих один и тот же протокол приложения. Это очень полезно и делает его таким полезным.

Флориан Бош
источник
3
Работает ли WSGI поверх CGI, для чего нужен «flup»? Как flup связан со схемой?
Эли Бендерский
7

Если вам неясны все термины в этом пространстве, и давайте посмотрим правде в глаза, это сбивает с толку запутанный акроним, есть также хороший фоновый читатель в форме официального HOWTO на питоне, в котором обсуждаются CGI против FastCGI против WSGI и так далее. на: http://docs.python.org/howto/webservers.html

Ричард Бордман
источник
2
URL устарел, я думаю, что он обновлен: docs.python.org/2.7/howto/webservers.html
Stefaan
Отличный материал :) Необходимо прочитать это официальное введение вместе с принятым ответом.
Рик
4

Это простой уровень абстракции для Python, похожий на спецификацию Servlet для Java. В то время как CGI действительно низкоуровневый и просто сбрасывает данные в среду процесса и стандартный ввод / вывод, две вышеупомянутые спецификации моделируют запрос и ответ http как конструкции на языке. Однако у меня сложилось впечатление, что в Python люди не совсем остановились на фактических реализациях, поэтому у вас есть набор эталонных реализаций и другие библиотеки типов утилит, которые предоставляют другие функции наряду с поддержкой WSGI (например, Paste). Конечно, я могу ошибаться, я новичок в Python. Сообщество "веб-сценариев" сталкивается с проблемой в другом направлении (виртуальный хостинг, наследие CGI,

Аарон
источник