Почему heroku local: run хочет использовать глобальную установку python вместо действующего виртуального env?
Используя Heroku для развертывания нашего приложения Django, все работает по спецификации, за исключением команды heroku local:run
.
Нам часто нужно запускать команды через файл Django manage.py. Выполнение их на удаленной, как одноразовые диноды, работает безупречно.
Чтобы запустить их локально, мы попробуем:
heroku local:run python manage.py the_command
Что не удается, несмотря на то, что текущий виртуальный env содержит установку Django, с
ImportError: No module named django.core.management
Диагностика через путь python
Затем heroku local:run which python
возвращает:
/usr/local/bin/python
В то время как which python
возвращает:
/Users/myusername/MyProject/venv/bin/python #the correct value
- Это ошибка в локации Heroku: run? Или мы не понимаем его ожидаемого поведения?
- И что еще более важно: существует ли способ использовать
heroku local:run
действующий виртуальный env?
Ответы
Ответ 1
После контакта с поддержкой Heroku мы поняли проблему.
Поддержка подтвердила, что heroku local:run
должна, как и ожидалось, использовать действующее виртуальное виртуальное приложение.
Проблема - проблема локальной конфигурации из-за нашего .bashrc
контента: heroku local:run
sources .bashrc
(и в нашем случае это было добавление $PATH с пути к глобальной установке Python, виртуальный env). С другой стороны, heroku local
не отправляет этот файл. Чтобы процитировать последнее сообщение от их поддержки:
heroku local: run запускает команду с помощью bash в интерактивном режиме, который читает ваш профиль, vs heroku local (aliased to heroku local: start), который не запускается в интерактивном режиме.
Ответ 2
Добавить в ответ Ad N. Причина, по которой он абсолютно настаивал на использовании системы Python вместо виртуальной среды, из которой она была использована, заключается в следующем.
Heroku local: запуск источников .bashrc, который включает в себя пользователя PATH и любые дополнения к PATH по умолчанию. Сюда входит расположение системы Python, но не обязательно любые дополнительные интерпретаторы Python. Он будет использовать любой интерпретатор Python, который будет считаться первым, что по праву должно быть системным Python (в противном случае очень важные вещи, такие как управление init и пакетами, работают некорректно или вообще)
Похоже на то, что это вместо того, чтобы запускать его как localku localk: запускать, который использует .bashrc и включает в себя систему Python, чтобы запускать ее как локальную локальную, чтобы она использовала все, что активно в виртуальной среде.
Ответ 3
Запуск Heroku локально документирован здесь, однако он говорит только об использовании heroku local
, который спецификация документации является синонимом heroku local:start
heroku local - это более короткая альтернатива heroku local: start, который делает то же самое.
автоответчик OP указывает, что разработчики Heroku подтвердили, что если используется heroku local
(эквивалентно heroku local:start
), то локальный .bashrc
не используется, и виртуальный питон используется как ожидалось
Если используется heroku local:run
, то локальная машина .bashrc
будет найдена и в случае OP, которая .bashrc
добавила путь к системе python
в $PATH
и, следовательно, была использована системная установка python.
Итак, вывод заключается в том, что heroku local:run
должен использовать виртуальный python, но не будет, если ваш .bashrc
будет содержать команды, которые заставили бы его использовать системную версию python (например, поместив путь в систему python сначала в переменной пути).
Подробнее через прогулку по коду
Чтобы увидеть код и понять детали с этой точки зрения, посмотрите репозиторий Github для heroku-local
, в частности в разделе commands
. Здесь мы видим, что есть один файл Javascript для команды run
, а другой - для команды start
. Загляните внутрь, и вы видите, что они выглядят очень похожими, за исключением того, что они называются forego.run
и forego.start
соответственно (примечание forego
использует Foreman в Go - см. здесь). В свою очередь, вызовите Node.js child_process.spawn()
, чтобы запустить процесс forego
, снова с помощью run
или start
как аргументы соответственно.
После этого - run.go
определяет NewProcess
, на котором он вызывает ShellInvocationCommand
, который является специфичным для платформы. Наконец, мы видим корень проблемы в unix.go
здесь, где вы видите, что профиль получен в ShellInvocationCommand
. При использовании start.go
метод запуска процесса полностью отличается, profile
не используется, поэтому используется виртуальный питон.