在 pyenv viralenv 下运行 Python 脚本时要使用哪些 shebang

当 Python 脚本应该从 pyenv virtualenv运行时,文件的正确 开始吧是什么?

作为一个示例测试用例,我的系统(OS X)上的默认 Python 没有安装 pandas。Pyenv virtualenv venv_name可以。我尝试从 viralenv 获取 Python 可执行文件的路径。

pyenv activate venv_name
which python

Output:

/Users/username/.pyenv/shims/python

So I made my example script.py:

#!/Users/username/.pyenv/shims/python
import pandas as pd
print 'success'

但是当我尝试运行这个脚本(从‘ venv _ name’中)时,我得到了一个错误:

./script.py

Output:

./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

还有:

python script.py # Also works

产出:

success

什么是正确的方法?理想情况下,我想要一些通用的东西,这样它就会指向 Python,不管我当前的 venv 是什么。

53794 次浏览

我真的不明白为什么调用带有 full 路径的解释器对你不起作用。我一直在用。但是如果您想使用环境中的 Python 解释器,您应该这样做:

#!/usr/bin/env python

这样,您就可以在环境中搜索 Python 解释器以使用它。

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

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

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

你可以看到更多的 给你

As you expected, you should be able to use the full path to the virtual environment's Python executable in the shebang to choose/control the environment the script runs in regardless of the environment of the controlling script.

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

参见: 译自: 美国《科学》杂志网站(href = “ https://unix.stackexchange.com/questions/209646/how-to-active-viralenv-when-a-python-script-start”) https://unix.stackexchange.com/questions/209646/how-to-activate-virtualenv-when-a-python-script-starts

尝试 pyenv virtualenvs查找虚拟环境目录的列表。

And then you might find a using shebang something like this:

#!/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 解释器将查看该二进制文件的路径位置以寻找支持文件,并最终使用周围的虚拟环境。(见每 * Virtual alenv 是如何工作的?)

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

sudo chmod +x script.py

It's not exactly answering the question, but this suggestion by ephiement I think is a much better way to do what you want. I've elaborated a bit and added some more of an explanation as to how this works and how you can dynamically select the Python executable to use:

#!/bin/sh
#
# Choose the Python executable we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concatenation by Python; the 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())

如果您的环境中有一个 Python 可执行文件,那么在99% 的情况下,您可以使用:

#!/usr/bin/env python

然而,对于 Linux 上遵循相同语法的自定义 venv,我无法使用,因为 venv创建了一个到创建 venv的 Python 解释器的链接,所以我必须执行以下操作:

#!/path/to/the/venv/bin/python

但实际上,您可以在终端中调用 Python 解释器。这是 #!之后的内容。

如果你只想要一个简单的脚本和一个简单的 pyenv viralenv 选项,你可以使用一个 Bash 脚本和你的源代码作为一个 Herdoc,如下所示:

#!/bin/bash
PYENV_VERSION=<your_pyenv_virtualenv_name> python - $@ <<EOF
import sys
print(sys.argv)
exit
EOF

我做了一些额外的测试。下面的工作:

#!/usr/bin/env -S PYENV_VERSION=<virtual_env_name> python

/usr/bin/env python不能工作,因为它不了解虚拟环境。

假设您的 main.py位于 ./venv目录的旁边,那么您需要从 venv目录中使用 Python。或者换句话说,使用这个方法:

#!venv/bin/python

现在你可以做:

./main.py