запуск кода python на сервере
CGI: пишем простой сайт на Python. Часть 1: Hello world
Сегодня я расскажу про то, как написать Hello world, как CGI-скрипт.
Настройка локального сервера
В Python уже есть встроенный CGI сервер, поэтому его настройка элементарна.
Для запуска из консоли (для любителей linux-систем). Запускать нужно из той папки, где мы хотим работать:
Для сидящих на Windows чуть проще будет запуск Python файла (заметьте, что он должен находиться в той же папке, в которой мы планируем работать!):
Теперь откройте браузер и в адресной строке наберите localhost:8000
Если у вас примерно такая же картина, значит, у вас все заработало!
Hello world
Теперь в той папке, где мы запустили сервер, создаём папку cgi-bin (у меня она уже создана).
В этой папке создаём скрипт hello.py со следующим содержимым:
Первая строка говорит о том, что это Python скрипт (CGI-скрипты можно не только на Python писать).
Вторая строка печатает заголовок. Он обозначает, что это будет html файл (бывает ещё css, javascript, pdf и куча других, и браузер различает их по заголовкам).
Третья строка (просто символ новой строки) отделяет заголовки от тела ответа.
Четвёртая печатает Hello world.
Теперь переходим на localhost:8000/cgi-bin/hello.py
Если у вас не работает, проверьте, установлены ли права на выполнение.
Также в консоли запущенного сервера появляются сообщения об ошибках. Например, убрал скобочку и обновил страницу:
В следующей части мы рассмотрим обработку данных форм и cookies.
Настройка NGINX + uWSGI для Python на Ubuntu
В нашей инструкции будет рассмотрена настройка веб-сервера для поддержки приложений, разработанных на языке Python. Руководство рассчитано для операционных систем семейства Deb (Ubuntu, Debian, Mint).
Запуск uWSGI приложения
Устанавливаем python и дополнительные компоненты:
apt-get install python3 python3-dev python3-pip
Устанавливаем дополнительные пакеты для python:
pip3 install virtualenv uwsgi
uWSGI установлен — посмотрим версию приложения:
Создаем каталог, в котором разместим наше тестовое приложение:
. и перейдем в созданный каталог:
Создадим файл со следующим содержимым:
def application(env, start_response):
start_response(‘200 OK’, [(‘Content-Type’,’text/html’)])
return [b»
Hello World
* в данном примере мы просто выводим на экран знаменитую фразу «Hello World».
Если в нашей системе используется брандмауэр с запрещающими правилами, открываем порт 8080:
apt-get install iptables-persistent
Создаем виртуальное окружение:
Активируем созданное окружение командой:
Запускаем веб-сервер на порту 8080:
Открываем браузер и переходим по адресу 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
Разрешаем и стартуем сервис:
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
Меняем владельца каталога нашего проекта на пользователя, под которым работает NGINX (в Ubuntu это, как правило, www-data):
systemctl restart uwsgi
Установка и настройка NGINX
Переходим к настройке NGINX. Для начала, установим его:
apt-get install nginx
systemctl enable nginx
Откроем на редактирование конфигурационный файл default:
* это самый простой путь для тестирования нашей настройки. Для продуктивной среды хорошим тоном будет настройка виртуальных доменов.
Приведем location / к следующему виду:
* в данном примере мы все запросы переводим на файл wsgi.py с передачей в качестве аргументов строки запроса. Все запросы передадутся на uWSGI через сокетный файл wsgi.sock, находящийся в каталоге нашего проекта.
Проверим корректность настройки nginx:
systemctl restart nginx
Готово, открываем браузер и переходим по адресу http:// / (уже без указания на порт) — должна открываться все та же страница Hello World.
Несколько советов по организации Python-приложения на сервере
В этой статье я хочу поделиться несколькими удобными способами организации вашего проекта на рабочем (даже продакшен) сервере.
Я работаю, в основном, с Python/Django стеком, поэтому все примеры будут, в первую очередь, применительно к этому набору. Также ключевые технологии: Ubuntu (17.10), Python3 (3.6).
Предполагается что вы делаете все грамотно, приложение хранится в репозитории, деплоится в отдельную папку на сервере, используется, например, 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
copytruncate важна по той причине, что при ротировании файл не будет закрыт. Поскольку мы ротируем файл на «живой» системе, файл открыт и сервисы, которые в него пишут, делают это по какому-то файловому дескриптору. Если вы просто переместите файл и создадите новый пустой, то он не будет использоваться. copytruncate говорит что нужно скопировать содержимое, а потом очистить файл, но не закрывать.
Сервисы
Как вы запускаете ваше приложение? Есть куча разных способов. По моим наблюдения основные такие:
Все они имеют свои плюсы, но, на мой взгляд, они имеют еще больше минусов.
Я не буду здесь рассматривать 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):
Если у вас больше одного сервера, то, конечно, вы используете уже свои скрипты для разворачивания, это просто пример.
Локальные настройки
Это тема для холивара и я хочу заметить, что этот параграф — исключительно моя точка зрения, которая базируется на моем опыте. Делайте как хотите, я просто советую.
Суть проблемы в том, что как ни пиши приложение, ему, скорее всего, придется иметь дело с данными, которые где-то хранятся. Список юзеров, путь к ключам, пароли, путь к базе, и тп… Все эти настройки хранить в репозитории нельзя. Кто-то хранит, но это порочная практика. Небезопасно и негибко.
Какие есть самые частые способы хранения таких настроек и какие проблемы с ними:
Я рекомендую именно этот способ. Обычно я для проекта создаю yaml-файл в папке «/usr/local/etc/». У меня написан небольшой модуль, который используя магию хаки загружает переменные из файлика в locals() или globals() импортирующего модуля.
Используется очень просто. Где-то в глубинах settings.py для Django (лучше ближе к концу) достаточно вызвать:
И все содержимое будет замешано в глобальные settings. У меня используется merge для списков и словарей, это может быть не всем удобно. Важно помнить, что Django импортирует только UPPERCASE константы, то есть в файлике настройки первого уровня у вас сразу должны быть в верхнем регистре.
Развертывание сервера с помощью Python: от А до Я.
В этом руководстве вы узнаете, как настроить сервер и развернуть веб-приложение с нуля, используя только Python.
В этом уроке я проиллюстрирую, как настроить сервер для запуска веб-приложения без какого-либо другого инструмента, кроме Python.
В конце его у вас будет:
В те времена, когда Docker еще не существовал, я обычно настраивал серверы в облачной среде с помощью кода Python. В основном это был скрипт/проект Python, который я запускал на своей (локальной) машине, и он выполнял команды на (удаленном) сервере.
Я давно не пользовался этим проектом шахт, но наткнулся на него на прошлой неделе и понял две вещи:
На самом деле, причина, по которой я написал это, заключается в том, что еще раньше я настраивал все серверы вручную: вход через ssh, установка необходимых пакетов и т. Д.
Это означает, что код выделяет детали всего, что вы должны делать на сервере, в отличие от использования Docker, где большинство деталей скрыто.
Поэтому этот пост может быть полезен по двум причинам:
Обзор учебника
Код организован в функции, где каждая функция выполняет задачу на сервере, даже если она выполняется на локальной машине.
Поэтому, прежде чем смотреть на код, стоит подумать о том, какие шаги вам нужно было бы выполнить (вручную), если бы вы не читали этот учебник.
Вы многому научитесь, делая это вручную. Давайте сначала рассмотрим обзор каждого отдельного шага, а затем еще раз рассмотрим каждый из них вместе с кодом.
Шаг 1 – Базовая конфигурация машины
Затем, поскольку вы хотите запустить приложение Python, вам необходимо настроить Python на сервере.
Большинство операционных систем поставляются с предустановленным двоичным файлом Python по умолчанию. Однако, на мой взгляд, это не очень хорошее решение.
Причина в том, что вы, возможно, разработали свое приложение с Python3.7, но тогда на сервере есть Python3.9. Все рухнет, и будет трудно понять, почему.
Вот почему в моем коде также есть конкретные инструкции по настройке правильной версии Python в 3 подшагах.
Наконец, как и в большинстве приложений Python, вы захотите создать virtualenv только для этого приложения.
Если в вашем приложении есть выделенный сервер, то есть это единственное программное обеспечение, работающее в нем, вы можете пропустить эту часть. Мой код в любом случае содержит функцию также для установки virtualenvwrapper и настройки virtualenv, предназначенного для этого приложения.
Это конец первого шага.
Шаг 2 – Установите приложение
Чтобы сервер запустил ваше приложение, это должно быть установлено! Если ваше приложение является исполняемым файлом, который можно установить, вам следует загрузить его (через curl или wget ) или скопировать его с локальной машины на удаленный сервер (через scp ).
Более распространенный случай с приложениями Python, по крайней мере для меня, – это когда для запуска приложения нам нужен исходный код. В этом случае вам нужно поместить исходный код на удаленный сервер. Есть два распространенных способа сделать это:
В своем коде я буду использовать вариант 1, поэтому я могу показать вам хороший способ, который я нашел тогда, чтобы написать код, который переключается между ветвями и фиксациями в репозитории (например, если вы хотите выполнить откат).
Шаг 3 – Запустите приложение!
Эта часть является самой простой, особенно если вы используете готовый к работе надежный веб-сервер. Я выбрал Gunicorn, но есть много альтернатив, которые одинаково просты в использовании.
Это три шага, которые вы должны пройти на высоком уровне. Теперь я хочу рассмотреть их более внимательно вместе с вами, но… есть одна недостающая деталь: как мы можем отправлять команды для выполнения на сервер, не выполняя ручной вход через ssh?
Настройка подключения
К счастью для нас, пакет Python под названием fabric решает эту проблему. Все, что вам нужно, – это такая функция, которая создает соединение с сервером:
Объект соединения, возвращаемый этой функцией, будет использоваться во всем остальном коде.
Часть 1 подробно
В части 1 мы хотим настроить сервер на самом базовом уровне: библиотеки ОС, языки программирования и т. Д.
Ну, мы можем сделать то же самое в коде Python, благодаря объекту подключения. Вот код.
Приведенный выше код реализует три подэтапа, которые я обсуждал ранее:
Это еще одна причина, по которой я сказал, что очень важно выполнить ручное развертывание хотя бы один раз!
Часть 2 подробно
В части 2 я сказал, что мы хотим сделать две вещи:
На первый взгляд эта функция может показаться немного сложной, но это не так. Я написал общую функцию, которая позволяет вам проверять конкретную ветвь по имени или конкретную фиксацию по ее хэшу, и именно поэтому функция выглядит сложной.
Часть 3 подробно
ЛАДНО, ладно… Я делаю еще несколько вещей в коде:
И это все! Последнее, на что нам нужно обратить внимание, – это как загрузить переменные среды.
Для доказательства концепций я искал только готовое к использованию приложение Flask. Я хотел использовать приложение, которое не было разработано мной, чтобы показать вам, насколько гибок этот код.
Я нашел пример приложения, опубликованного на GitHub компанией Digital Ocean. Я не имею к ним никакого отношения, но это выглядело хорошо для этого проекта, поэтому вы видите его в secret.py файл. Вот он:
Последний трюк!
Код был написан несколько лет назад, но есть один последний трюк, который я реализовал и которым хочу поделиться с вами.
Мотивация заключается в том, что иногда мне захочется запустить одну из функций, которые мы видели, и только одну. И иногда им могут понадобиться аргументы во входных данных (это относится к _pull_repo ).
Вот что я придумал два года назад.
Давайте проверим это!
Пришло время проверить. Я хочу заранее сказать вам, что результат хороший: я был очень счастлив, что мой код работал идеально, даже если я не использовал его некоторое время!
Во-первых, я создал небольшую машину на Linode. Я не связан с ними, я просто хотел использовать другого поставщика, так как код приложения принадлежит Digital Ocean.
Самая маленькая машина на Linode стоит 5 долларов (у других поставщиков такая же цена), и весь тест длился менее 5 минут, поэтому я потратил всего несколько центов. Я выбрал Debian 10 в качестве ОС.
Затем я скопировал хост, имя пользователя и пароль root из консоли Linode в secret.py файл.
Затем я загрузил Github gist, сохранив то же имя файла azPyDeploy.py в том же каталоге, где secret.py есть.
И, наконец, я выполнил четыре простые команды.
Первый занял несколько минут (помните, что он компилирует и устанавливает Python), и когда все было сделано, веб-приложение работало на сервере!!
Заключительные комментарии и код
Я знаю, что это не похоже на то, как вы бы сделали развертывание производства сегодня. Даже я все время использую Docker и некоторые более продвинутые инфраструктурные системы, предоставляемые AWS.
Если по какой-то причине вы не можете использовать больше автоматизированных систем, то проект в этом руководстве может быть полезен.
Вот полный код, на случай, если gist не сработает.
Дайте мне знать, если вы столкнулись с какой-либо проблемой при воспроизведении этого урока.
Запуск Python и python-скрипт на компьютере
Код, написанный на языке Python, может храниться в редакторе кода, IDE или файле. И он не будет работать, если не знать, как его правильно запускать.
В этом материале рассмотрим 7 способов запуска кода, написанного на Python. Они будут работать вне зависимости от операционной системы, среды Python или местоположения кода.
Где запускать Python-скрипты и как?
Python-код можно запустить одним из следующих способов:
Запуск Python-кода интерактивно
Для запуска интерактивной сессии нужно просто открыть терминал или командную строку и ввести python (или python3 в зависимости от версии). После нажатия Enter запустится интерактивный режим.
Вот как запустить интерактивный режим в разных ОС.
Интерактивный режим в Linux
Откройте терминал. Он должен выглядеть приблизительно вот так :
После нажатия Enter будет запущен интерактивный режим Python.
Интерактивный режим в macOS
На устройствах с macOS все работает похожим образом. Изображение ниже демонстрирует интерактивный режим в этой ОС.
Интерактивный режим в Windows
Запуск Python-скриптов в интерактивном режиме
В таком режиме можно писать код и исполнять его, чтобы получить желаемый результат или отчет об ошибке. Возьмем в качестве примера следующий цикл.
Для выхода из интерактивного режима нужно написать следующее:
И нажать Enter. Вы вернетесь в терминал, из которого и начинали.
Есть и другие способы остановки работы с интерактивным режимом Python. В Linux нужно нажать Ctrl + D, а в Windows — Ctrl + Z + Enter.
Стоит отметить, что при использовании этого режима Python-скрипты не сохраняются в локальный файл.
Как выполняются Python-скрипты?
Отличный способ представить, что происходит при выполнении Python-скрипта, — использовать диаграмму ниже. Этот блок представляет собой скрипт (или функцию) Python, а каждый внутренний блок — строка кода.
При запуске скрипта интерпретатор Python проходит сверху вниз, выполняя каждую из них. Именно таким образом происходит выполнение кода.
Но и это еще не все.
Блок-схема выполнения кода интерпретатором
Это набор инструкций, которые приводят к финальному результату.
Иногда полезно изучать байткод. Если вы планируете стать опытным Python-программистом, то важно уметь понимать его для написания качественного кода.
Это также пригодится для принятия решений в процессе. Можно обратить внимание на отдельные факторы и понять, почему определенные функции/структуры данных работают быстрее остальных.
Как запускать Python-скрипты?
Для запуска Python-скрипта с помощью командной строки сначала нужно сохранить код в локальный файл.
Возьмем в качестве примера файл, который был сохранен как python_script.py. Сохранить его можно вот так:
Сохранить скрипт в текстовом редакторе достаточно легко. Процесс ничем не отличается от сохранения простого текстового файла.
Но если использовать командную строку, то здесь нужны дополнительные шаги. Во-первых, в самом терминале нужно перейти в директорию, где должен быть сохранен файл. Оказавшись в нужной папке, следует выполнить следующую команду (на linux):
После нажатия Enter откроется интерфейс командной строки, который выглядит приблизительно следующим образом:
Теперь можно писать код и с легкостью сохранять его прямо в командной строке.