Недавно я опубликовал мой первый пакет Python на pypi.org. Это довольно простой модуль, который проверяет и обновляет правила переадресации IP-адресов в доменах Google. Он довольно функционален и может запускаться с различными параметрами из командной строки и, например, по расписанию через пользовательский crontab, но его также можно импортировать в проект.

Следующим логическим шагом было попытаться интегрировать его в приложение Django, и в качестве цели я выбрал свой небольшой портфолио проекта веб-приложения (слишком неловко давать ссылку на него, но я уверен, что вы могли бы найти его без особых усилий! ). На самом деле это была единственная логическая цель, учитывая, что это приложение работает с сервера, для которого я создал пакет, и хотя у меня есть много других приложений на разных стадиях разработки, которые могут подойти, как мы узнаем, есть огромная разница между тем, чтобы что-то работало в разработке, и тем, чтобы это работало в продакшене , особенно когда речь идет о Django.

Прежде всего, я должен сказать, что тестировал сценарий до смерти, прежде чем выпустить его в мир. Затем я получил невероятно полезный отзыв на codereview.stackexchange.com — полезный тем, что я узнал несколько лучших практик, не столько тем, что я несколько раз ломал свой код, пытаясь включить их! Это привело к серии творческих номеров версий / журналов изменений, позволяющих мне продолжать загружать исправления ошибок / readme-правки в pypi (0.1, 0.1.1, 0.1.2, 0.1.2.1 и т. д.).

После того, как я опубликовал его, тестирование (и игра) стало более увлекательным благодаря возможности установить его на любую систему, о которой я только мог подумать, с помощью простой установки pip — мне особенно понравилось тестировать его на «Pydroid» (фантастический Android приложение для любителей Python) — и снова багов становилось все меньше и меньше. Здорово!

Итак, об интеграции Django…

Первоначальная интеграция так же проста, как создание базового модуля для планирования задачи (также pip install apscheduler) и его импорт в метод apps.py ready вашего основного приложения. Например:

И это все. Это все, что вам должно понадобиться для планирования задачи в Django. Но что, если вашему пакету нужно создать файл?

О, привет еще раз, PermissionError! Основная проблема заключалась в разрешениях для файла pickle и файла журнала, который создает пакет, и я думал, что это должно быть довольно просто выяснить, но я жестоко ошибался.

Моя основная машина — это настольный ПК с Windows 10, но у меня есть несколько других компьютеров с Linux, как физических, так и виртуальных, и на самом деле я часто использую WSL поверх cmd или PowerShell, где это возможно, потому что Linux CLI просто лучше! Однако, сказав это, намного проще войти в %AppData%, чем в /var/log или где-либо еще в системе POSIX, похоже!

В конце концов, я остановился на ведении журнала в файле в каталоге пакета ../lib/python3.9/site-packages/my-python-module (я не сдался, я сделал перерыв в здравомыслии и исправлю это в будущих обновлениях!). Тем не менее, я все еще сталкивался с проблемами, когда скрипт запускался от имени пользователя Apache2, www-dataпоскольку очевидно, что у этого пользователя совершенно другой набор разрешений. В конце концов  — «и я имею в виду ооооочень много времени спустя»: «почти целую ночь/день гугления и настройки» — «я наткнулся на решение, которое было недалеко от моей мечты о том, чтобы работать прямо из коробки»! (У меня были различные успехи, связанные со сложными chmod и chown, но я не очень доволен ими!)

Найденное мной решение, которое сейчас звучит так просто, состоит в том, чтобы запустить модуль от имени пользователя www-data перед запуском/перезапуском веб-сервера, НО осторожно используя путь python вашей виртуальной среды или тот же, что и в файле (файлах) конфигурации apache2, так что, когда вы в конечном итоге запустите веб-сервер, все файлы конфигурации, связанные с модулем, который вы хотите запустить, были созданы и, следовательно, могут использоваться www-data. В моем случае эта команда выглядит так:

sudo -u www-data ~/project/venv/bin/python3 -m my_python_module

И после этого все странности просто прекратились! Ну наконец то! Нет лучшего чувства, чем когда твой код наконец-то работает, верно?! Это оправдывает все повреждения печени/легких и выпадение волос! Я проверил соответствующие файлы и, конечно же, владелец и владелец группы теперь были www-data, как я и ожидал.

Теперь пакет полностью интегрирован в мое приложение, поэтому он может эффективно обновлять свои собственные правила DNS, если и когда это необходимо. Я еще многое могу упорядочить и отполировать  — разрешения не идеальны, я хотел бы в идеале остаться владельцем файла, а www-data — владельцем группы, и я думаю, что следующим шагом, вероятно, будет создание версия, специфичная для django, которая интегрирована как промежуточное ПО или установленное приложение, но я определенно достиг важной вехи: там, где раньше скрипт выполнялся как отдельное задание crontab (все еще возможно с тем же пакетом), теперь он встроен в код самого приложения Django, который, честно говоря, чертовски хорош!

РЕДАКТИРОВАТЬ: Как кратко упоминалось выше, чтобы вручную установить разрешения для рассматриваемого каталога, вы можете использовать:

sudo chown -R :www-data /path/to/venv/lib/python3.8/site-packages/my_module
sudo chmod -R g+rws /path/to/venv/lib/python3.8/site-packages/my_module

См. мою первую статью о сборке пакета: