То, что shebang использовать для скриптов python, выполняется под pyenv virtualenv
Когда предполагается, что python script запускается из pyenv
virtualenv
, что является правильным shebang для файла?
В качестве примера тестового примера, в python по умолчанию для моей системы (OSX) не установлен pandas
. Pyenv virtualenv venv_name
делает. Я попытался получить путь к исполняемому файлу python из virtualenv.
$ pyenv activate venv_name
(venv_name)$ which python
/Users/username/.pyenv/shims/python
Поэтому я сделал свой пример script.py
:
#!/Users/username/.pyenv/shims/python
import pandas as pd
print 'success'
Но когда я попытался запустить script, я получил сообщение об ошибке:
(venv_name) $ ./script.py
./script.py: line 2: import: command not found
./script.py: line 3: print: command not found
Хотя запуск этого пути в командной строке работает нормально:
(venv_name) $ /Users/username/.pyenv/shims/python script.py
success
(venv_name) $ python script.py # also works
success
Что для этого нужно? В идеале, я хочу что-то общее, чтобы оно указывало на питон любого моего текущего venv.
Ответы
Ответ 1
Я действительно не знаю, почему вызов интерпретатора с полным путем не сработает для вас, я использую его все время, но если вы хотите использовать интерпретатор python, который находится в вашей среде, вы должны сделать:
#!/usr/bin/env python
Таким образом вы выполняете поиск в среде, в которой используется интерпретатор python.
Ответ 2
Если вам нужно использовать больше оболочки, чем вы можете поместить в строку #!
shebang, вы можете запустить файл с помощью простой оболочки script, которая запускает Python в том же файле.
#!/bin/bash
"exec" "pyenv" "exec" "python" "$0" "[email protected]"
# the rest of your Python script can be written below
Из-за цитирования Python не выполняет первую строку и вместо этого объединяет строки для модуля docstring... который фактически игнорирует его.
Здесь вы можете увидеть .
Ответ 3
Как вы и ожидали, вы должны иметь возможность использовать полный путь к виртуальной среде python в shebang для выбора/управления средой, в которой работает script, независимо от среды управления script.
В комментариях к вашему вопросу VPfB вы обнаружите, что /Users/username/.pyenv/shims/python
представляет собой оболочку script, которая выполняет exec $pyenv_python
. Вы должны иметь возможность echo $pyenv_python
определить реальный питон и использовать его в качестве своего сибанга.
Смотрите также: https://unix.stackexchange.com/questions/209646/how-to-activate-virtualenv-when-a-python-script-starts
Попробуйте pyenv virtualenvs
найти список каталогов виртуальной среды.
И тогда вы можете найти использование shebang примерно так:
#!/Users/username/.pyenv/python/versions/venv_name/bin/python
import pandas as pd
print 'success'
... позволит script работать с использованием выбранной виртуальной среды в других (виртуальных или нет) средах:
(venv_name) $ ./script.py
success
(venv_name) $ pyenv activate non_pandas_venv
(non_pandas_venv) $ ./script.py
success
(non_pandas_venv) $ . deactivate
$ ./script.py
success
$
Трюк заключается в том, что если вы вызываете двоичную информацию виртуальной среды python, python просматривает это место двоичного пути для поддерживающих файлов и заканчивает работу с использованием окружающей виртуальной среды. (См. Per Как работает virtualenv?)
Ответ 4
может быть, вам нужно проверить права доступа к файлу:
sudo chmod +x script.py
Ответ 5
Это не совсем ответ на вопрос, но это предложение от ephiement, я думаю, гораздо лучший способ сделать то, что вы хотите. Я немного развил и добавил еще несколько объяснений о том, как это работает и как вы можете динамически выбирать питон для использования:
#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
echo Using preferred python $ALTERNATIVE_PYTHON
exec $PREFERRED_PYTHON "$0" "[email protected]"
elif [ -x $ALTERNATIVE_PYTHON ]; then
echo Using alternative python $ALTERNATIVE_PYTHON
exec $ALTERNATIVE_PYTHON "$0" "[email protected]"
else
echo Using fallback python $FALLBACK_PYTHON
exec python3 "$0" "[email protected]"
fi
exit 127
'''
__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())