用于python脚本的shebang在pyenv virtualenv下运行

时间:2017-05-19 18:32:40

标签: python python-2.7 pyenv

当一个python脚本应该从pyenv virtualenv运行时,该文件的正确shebang是什么?

作为示例测试用例,我系统上的默认python(OSX)没有安装pandas。 pyenv virtualenv venv_name确实如此。我尝试从virtualenv获取python可执行文件的路径。

$ 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'


但是当我尝试运行脚本时,我收到了一个错误:

(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所在的python。

5 个答案:

答案 0 :(得分:40)

我真的不知道为什么用完整路径调用解释器对你不起作用,我一直都在使用它,但如果你想使用你环境中的python解释器你应该这样做:

#!/usr/bin/env python

这样就可以在环境中搜索要使用的python解释器。

答案 1 :(得分:4)

如果你需要使用比#! shebang行更多的shell,你可以使用一个简单的shell脚本启动文件,该脚本在同一个文件上启动Python。

#!/bin/bash
"exec" "pyenv" "exec" "python" "$0" "$@"
# the rest of your Python script can be written below

由于引用,Python不执行第一行,而是将模块docstring连接在一起...这实际上忽略了它。

您可以看到更多here

答案 2 :(得分:3)

正如您所料,您应该能够使用shebang中虚拟环境的python的完整路径来选择/控制脚本运行的环境,而不管控制脚本的环境如何。

在您的问题评论中,VPfB&您发现/Users/username/.pyenv/shims/python是执行exec $pyenv_python的shell脚本。你应该能够echo $pyenv_python来确定真正的python并将其用作你的shebang。

另请参阅: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'

...将使脚本能够在其他(虚拟或非虚拟)环境中使用所选的虚拟环境:

(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会查看该二进制文件的支持文件的路径位置,最终使用周围的虚拟环境。 (参见How does virtualenv work?

答案 3 :(得分:0)

也许您需要检查文件权限:

sudo chmod +x script.py

答案 4 :(得分:0)

这并不能确切地回答Q,但是我认为通过言辞提出的建议是一种更好的方法来完成您想要的事情。我已经详细说明并添加了一些更多的解释,说明了它是如何工作的以及如何动态选择要使用的python:

#!/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" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
    echo Using alternative python $ALTERNATIVE_PYTHON
    exec $ALTERNATIVE_PYTHON "$0" "$@"
else
    echo Using fallback python $FALLBACK_PYTHON
    exec python3 "$0" "$@"
fi
exit 127
'''

__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())