- Как настроить веб-сервер Apache на запуск Python в Windows
- 1. Установите Python
- 2. Настройка Apache на запуск Python CGI
- 3. Перезапустите Apache
- 4. Запустите тестовую страницу Python
- Несколько советов по организации Python-приложения на сервере
- Сервисы
- Локальные настройки
- Настройка NGINX + uWSGI для Python на Ubuntu
- Запуск uWSGI приложения
- Hello World
- Сервис uWSGI
- uWSGI + NGINX
- Изменение настроек uWSGI
- Установка и настройка NGINX
Как настроить веб-сервер Apache на запуск Python в Windows
Скрипты Python можно запускать в окружении Apache аналогично запуску скриптов PHP. Для этого нужно сделать небольшую настройку.
Я устанавливал веб-сервер по этой инструкции, если вы устанавливали по другой инструкции, то отредактируйте пути под свои значения.
1. Установите Python
Если у вас ещё не установлен Python, то скачайте установщик здесь: https://www.python.org/downloads/windows/ (файл Windows x86-64 executable installer).
Я установил в предлагаемый путь, но также выбрал добавление папки с исполнимыми файлами Python в переменные окружения (возможно, это делать необязательно).
Забегая вперёд скажу — путь до папки с установленным Python нужно будет указывать в начале каждого Python cgi скрипта, поэтому или выберите более простую папку, куда вы устанавливаете Python, либо запомните имя путь до предложенной директории.
В конце программа установки предложила снять максимальное ограничение на длину пути — я согласился (возможно, это делать необязательно):
2. Настройка Apache на запуск Python CGI
Теперь откройте для редактирования файл httpd.conf, у меня он расположен по пути C:\Server\bin\Apache24\conf\httpd.conf.
Найдите там строку
и добавьте к ней ExecCGI. Должна получиться такая строка (ВНИМАНИЕ: набор опций у вас может быть другим):
Теперь найдите строку:
Раскомментируйте её, то есть удалите символ # в начале строки и добавьте к концу строки .py. Новая строка будет выглядеть примерно так:
3. Перезапустите Apache
4. Запустите тестовую страницу Python
В папке для ваших сайтов (у меня это C:\Server\data\htdocs\) создайте файл test.py и скопируйте в него:
Обратите внимание на самую верхнюю строку, то есть на C:\Users\Alex\AppData\Local\Programs\Python\Python37\python.exe — вам нужно заменить её на своё значение, указав путь до файла python.exe. Даже если вы выбрали предложенную по умолчанию папку, как минимум, вам нужно заменить имя пользователя Alex на имя своего пользователя.
ПРИМЕЧАНИЕ: обратите внимание, что путь до файла python.exe может различаться в зависимости от выбранной папки для установки, имени пользователя (если вы установили в C:\Users\), а также в зависимости от версии, например, это может быть папка Python39:
Отредактируйте самую верхнюю строку в соответствии с вашей установкой.
Источник
Несколько советов по организации Python-приложения на сервере
В этой статье я хочу поделиться несколькими удобными способами организации вашего проекта на рабочем (даже продакшен) сервере.
Я работаю, в основном, с Python/Django стеком, поэтому все примеры будут, в первую очередь, применительно к этому набору. Также ключевые технологии: Ubuntu (17.10), Python3 (3.6).
- Логи (logrotate)
- Демоны (systemd)
- локальные настройки
Предполагается что вы делаете все грамотно, приложение хранится в репозитории, деплоится в отдельную папку на сервере, используется, например, virtualenv. Для запуска используется отдельно созданный юзер, который имеет достаточно прав, но не слишком много (например не имеет sudo и не разрешен логин по ssh).
Для начала я повторю прописные истины, что все что хранится в репозитории — это только чистый код и статичные данные. Все настройки содержат только дефолты, никаких паролей и ключей, даже в неиспользуемых файлах.
Даже на рабочем компьютере (ноутбуке) где вы пишете код у вас в папке проекта не должно быть ничего что бы вы не могли закачать на продакшен. Имеется в виду порочная практика использования файлика «local_settings.py» в папке settings внутри проекта (как вариант — development_settings.py). Я разберу этот пример ниже.
Наверняка вы используете логирование. Встроенный модуль logging очень хорош, но не всегда стоит изощряться и использовать его для всего на свете.
Например, ротация логов. В интернете попадаются сложные и изощренные способы начиная от стандартного RotatingFileHandler и заканчивая написанием собственного демона на сокетах для записи логов из нескольких источников. Проблемы начинаются из-за желания делать все на «чистом Python». Это глупо и неэффективно, зато приносит кучу возможных мест возникновения ошибок.
Используйте сервис logrotate. Ниже приводится простой конфиг для логов celery.
Стандартными средствами пишем файлик /var/log/myproject/celery.log, ежедневно он кладется в папку /var/log/myproject/archive/ и к имени добавляется суффикс предыдущего дня.
Если у вас лог пишется очень быстро и вы хотите его ротировать каждый час, то в конфиге перекомментируйте строчки «daily» и «hourly». Также нужно настроить logrotate чтобы он запускался каждый час (по умолчанию обычно ежедневно). Выполните в bash:
Конфиг (файлик myservice) надо положить в папку logrotate
- конфиг надо именно скопировать, симлинки работать не будут
- в принципе, конфиг почти взят из доки по logrotate, но очень важно поставить copytruncate директиву
- (добавлено из комментария rusnasonov ) logrotate туповат и использует простейшую систему ротирования, без буферов. Ротирование проходит в два шага — сначала копируется старый файл, а потом он обрезается на старом месте. Это может привести к потере логов, которые были записаны в промежутке (отражено в документации)
copytruncate важна по той причине, что при ротировании файл не будет закрыт. Поскольку мы ротируем файл на «живой» системе, файл открыт и сервисы, которые в него пишут, делают это по какому-то файловому дескриптору. Если вы просто переместите файл и создадите новый пустой, то он не будет использоваться. copytruncate говорит что нужно скопировать содержимое, а потом очистить файл, но не закрывать.
Сервисы
Как вы запускаете ваше приложение? Есть куча разных способов. По моим наблюдения основные такие:
- запускаем screen/tmux и внутри запускаем в интерактивном режиме скрипт
- режим демона типа «-D» для gunicorn или celery
- supervisord
- init.d скрипт
- Docker
Все они имеют свои плюсы, но, на мой взгляд, они имеют еще больше минусов.
Я не буду здесь рассматривать Docker. Во-первых, у меня не так много опыта работы с ним. А во-вторых, если вы используете контейнеры, то вам и остальные советы из этой статьи не очень нужны. Там подход уже другой.
Я считаю, что если система предоставляет нам удобный инструмент, то почему бы им не воспользоваться.
В Ubuntu начиная с версии 15.04 по-умолчанию поставляется systemd для управления сервисами (и не только).
systemd очень удобен тем, что самостоятельно делает все правильно:
- запускает приложение под нужным пользователем и устанавливает переменные окружения, если нужно
- при внезапной остановке приложения — перезапускает его заданное количество раз
- очень гибок и позволяет настроить зависимости и порядок запуска
Конечно, если у вас нет systemd, то можно смотреть в сторону supervisord, но у меня довольно большая нелюбовь к этому инструменту и я избегаю его использовать.
Я надеюсь не будет людей, кто будет сомневаться что при наличии systemd использовать supervisord вредно.
Ниже я приведу пример конфига для запуска.
Запуск gunicorn (проксируется через локальный nginx, но это здесь неважно).
Здесь важно не использовать режим демонизации. Мы запускаем gunicorn обычным процессом, а демонизирует его сам systemd, он же и следит за перезапуском при падениях.
Обратите внимание, что мы используем путь к python и gunicorn относительно virtualenv-папки.
Для celery все будет таким же, но строку запуска я рекомендую такой (пути и значения поставьте свои):
Стоит обратить внимание на параметры для перезапуска:
Вкратце это означает следующее: если сервис упал, то запусти его снова через 2 секунды, но не больше 5 раз за 11 секунд. Важно понимать, что если значение в StartLimitIntervalSec будет, например, 9 секунд, то в случае если сервис остановится 5 раз подряд (сразу после запуска), то после пятого падения systemd сдастся и не будет его больше поднимать (2 * 5). Значение 11 выбрано именно с тем, чтобы исключить такой вариает. Если, например, у вас был сетевой сбой на 15 секунд и приложение падает сразу после старта (без таймаута), то пусть уж лучше оно долбит до победного, чем просто останавливается.
Чтобы установить этот конфиг в систему, можно просто сделать симлинк из рабочей папки:
Однако, с симлинками надо быть осторожными — если у вас проект лежит не на системном диске, то есть вероятность что он может монтироваться после старта сервисов (например, сетевой диск или memory-mapped). В этом случае он просто не запустится. Здесь вам придется гуглить как правильно настроить зависимости, да и вообще конфиг тогда лучше скопировать в папку systemd.
Update: после замечания andreymal я думаю что будет правильнее копировать конфиги в папку и ставить им правильные права:
Еще советую отключить вывод в консоль, иначе все будет попадать в syslog.
Когда у вас все компоненты заведены в systemd, то использование каждого из них сводится к:
Когда компонентов больше одного, то имеет смысл написать скрипт для массового управления всем хозяйством на сервере.
Для удаленной отладки через консоль (запустит shell_plus из django-extensions):
Если у вас больше одного сервера, то, конечно, вы используете уже свои скрипты для разворачивания, это просто пример.
Локальные настройки
Это тема для холивара и я хочу заметить, что этот параграф — исключительно моя точка зрения, которая базируется на моем опыте. Делайте как хотите, я просто советую.
Суть проблемы в том, что как ни пиши приложение, ему, скорее всего, придется иметь дело с данными, которые где-то хранятся. Список юзеров, путь к ключам, пароли, путь к базе, и тп… Все эти настройки хранить в репозитории нельзя. Кто-то хранит, но это порочная практика. Небезопасно и негибко.
Какие есть самые частые способы хранения таких настроек и какие проблемы с ними:
- файлик local_settings.py, который хранится в папке проекта рядом с дефолтными setting.py
Проблема: можно случайно закоммитить файл, можно его затереть при копировании/обновлении папки (rsync или из архива) - переменные окружения. Тоже не очень безопасно, не очень удобно (при soft-reload например)
- отдельный файл вне папки проекта
Я рекомендую именно этот способ. Обычно я для проекта создаю yaml-файл в папке «/usr/local/etc/». У меня написан небольшой модуль, который используя магию хаки загружает переменные из файлика в locals() или globals() импортирующего модуля.
Используется очень просто. Где-то в глубинах settings.py для Django (лучше ближе к концу) достаточно вызвать:
И все содержимое будет замешано в глобальные settings. У меня используется merge для списков и словарей, это может быть не всем удобно. Важно помнить, что Django импортирует только UPPERCASE константы, то есть в файлике настройки первого уровня у вас сразу должны быть в верхнем регистре.
Источник
Настройка NGINX + uWSGI для Python на Ubuntu
В нашей инструкции будет рассмотрена настройка веб-сервера для поддержки приложений, разработанных на языке Python. Руководство рассчитано для операционных систем семейства Deb (Ubuntu, Debian, Mint).
Запуск uWSGI приложения
Устанавливаем python и дополнительные компоненты:
apt-get install python3 python3-dev python3-pip
- python3 — сам python третьей версии.
- python3-dev — стандартный набор библиотек. Нужен для установки и сборки дополнительных модулей.
- python3-pip — система управления пакетами для python.
Устанавливаем дополнительные пакеты для python:
pip3 install virtualenv uwsgi
- virtualenv — утилита для создания изолированного python-окружения.
- uwsgi — веб-сервер для интерпретации кода, в нашем случае, python.
uWSGI установлен — посмотрим версию приложения:
Создаем каталог, в котором разместим наше тестовое приложение:
mkdir -p /var/www/python_app
. и перейдем в созданный каталог:
Создадим файл со следующим содержимым:
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
def application(env, start_response):
start_response(‘200 OK’, [(‘Content-Type’,’text/html’)])
return [b»
Hello World
* в данном примере мы просто выводим на экран знаменитую фразу «Hello World».
Если в нашей системе используется брандмауэр с запрещающими правилами, открываем порт 8080:
iptables -I INPUT -p tcp —dport 8080 -j ACCEPT
apt-get install iptables-persistent
Создаем виртуальное окружение:
Активируем созданное окружение командой:
Запускаем веб-сервер на порту 8080:
uwsgi —socket 0.0.0.0:8080 —protocol=http -w wsgi
Открываем браузер и переходим по адресу http:// :8080 — мы должны увидеть нашу страницу «Hello World».
Веб-сервер работает. Остановим его работу комбинацией клавиш Ctrl + С и деактивируем виртуальную среду:
Переходим к настройке uWSGI в качестве демона.
Сервис uWSGI
Чтобы не запускать сервис для каждого приложения вручную, необходимо настроить веб-сервер uWSGI. Он будет контролировать процесс работы с каждым приложением и позволит задать индивидуальные параметры с помощью конфигурационных файлов.
Устанавливаем веб-сервер командой:
apt-get install uwsgi uwsgi-plugin-python3
Создаем конфигурационный файл следующего содержания:
[uwsgi]
module = wsgi:application
chdir = /var/www/python_app
plugins = python3
max-requests = 5000
processes = 5
threads = 2
master = true
http = 0.0.0.0:8080
die-on-term = true
- chdir — в данный каталог необходимо перейти до запуска сервиса. Это должен быть путь с нашим приложением.
- plugins — uwsgi может работать не только с python, поэтому мы явно указываем плагин и версию языка.
- max-requests — количество запросов, после достижения которых должны перезапуститься воркеры.
- processes — количество воркеров, которые будут запущены при старте сервиса.
- threads — число потоков, которые будут доступны для каждого из воркеров.
- master — разрешить или запретить мастер процесс.
- http — задаем адрес интерфейса и порт, на которых будет слушать сервис.
- die-on-term — завершать работу или перезапускать сервис, если подан сигнал SIGTERM. В данном примере будет выполнен выход.
Разрешаем и стартуем сервис:
systemctl enable uwsgi
systemctl restart uwsgi
Открываем браузер и переходим по адресу http:// :8080/ — должна открываться наша страница Hello World.
uWSGI + NGINX
По сути, наш сервер готов к работе, но очень часто, uWSGI настраивается в связке с NGINX, который берет на себя задачи по проксированию запросов http и отдачи статики. Рассмотрим пример настройки данной связки.
Изменение настроек uWSGI
Откроем на редактирование ранее созданный конфигурационный файл:
* мы будем обращаться к uWSGI через сокетный файл, таким образом, держать сервис на отдельном порту избыточно.
Добавим к нашей настройке:
[uwsgi]
.
socket = wsgi.sock
chmod-socket = 660
vacuum = true
uid = www-data
gui = www-data
- socket — путь до сокетного файла, через который будут взаимодействовать наши uWSGI и NGINX.
- chmod-socket — выставляем права на сокетный файл.
- vacuum — удалять или нет при старте сервиса ранее созданные сокетные файлы.
- uid — назначает владельца сокетного файла.
- gui — назначает группу владельца сокетного файла.
Меняем владельца каталога нашего проекта на пользователя, под которым работает NGINX (в Ubuntu это, как правило, www-data):
chown -R www-data:www-data /var/www/python_app
systemctl restart uwsgi
Установка и настройка NGINX
Переходим к настройке NGINX. Для начала, установим его:
apt-get install nginx
systemctl enable nginx
Откроем на редактирование конфигурационный файл default:
* это самый простой путь для тестирования нашей настройки. Для продуктивной среды хорошим тоном будет настройка виртуальных доменов.
Приведем location / к следующему виду:
location / <
#try_files $uri $uri/ =404;
include uwsgi_params;
uwsgi_pass unix:/var/www/python_app/wsgi.sock;
try_files $uri $uri/ /wsgi.py?$query_string;
>
* в данном примере мы все запросы переводим на файл wsgi.py с передачей в качестве аргументов строки запроса. Все запросы передадутся на uWSGI через сокетный файл wsgi.sock, находящийся в каталоге нашего проекта.
Проверим корректность настройки nginx:
systemctl restart nginx
Готово, открываем браузер и переходим по адресу http:// / (уже без указания на порт) — должна открываться все та же страница Hello World.
Источник