我理解启动python脚本之间的区别,例如:
#!/usr/bin/env python
或
#!/usr/bin/python
据我了解,只需像在 shell 中那样执行 python,因此它看起来$PATH
.第二个不是固定路径,这很不方便,在不同的系统中,python解释器可能位于另一条路径中。
我的问题是,为什么我们需要env
?为什么我们可以做:
#!python
这在我的电脑中工作得很好?有理由更喜欢打电话给env
吗?
简短回答:这取决于外壳。 在 bash 中,#!python
将被忽略,您必须使用#!/usr/bin/env python
. 另一方面,zsh
似乎能够处理#!python
。
长答案(对于bash(:
假设你的 Python 文件名为"tst.py" 并有以下内容
#!python
import sys
print(sys.executable, sys.version)
然后您可以随时输入
python tst.py
第一行完全无关紧要,甚至没有看过。
但是,如果您执行以下操作(例如在 Linux 上(
chmod +x tst.py
./tst.py
然后查看第一行以确定应该使用哪个解释器(bash,perl,python,其他东西?(,这里至少对于我的操作系统(ubuntu(和我的shell(bash(需要可执行文件名称的绝对路径(例如/bin/bash
、/bin/python
、/usr/bin/env
(
如果我在我的 ubuntu 机器上调用 ./tst.py,我会得到
bash: ./tst.py: python: bad interpreter: No such file or directory
特殊情况下Windows,当键入 tst.py 或单击python脚本时。 如果你在Windows上,会查看该行,但即使它是错误的,也会使用默认的python解释器。例如,在Windows上,此行可用于显式选择python2或python3。 Windows 使用文件类型关联来确定要为哪个后缀调用哪个可执行文件。对于.py文件(安装了Python 3.x(,这通常是py.exe它是位于系统路径中的可执行文件,它只会调用python解释器。根据安装的版本,Shebang 线和环境变量,这可能表示虚拟环境
补遗: 第一行由 shell 解释,在窗口情况下由 py.exe 解释。
似乎bash需要绝对路径来命令,而zsh也接受相对路径。
所以只为 zsh
#!python
工作得很好,而bash需要绝对路径,因此使用env命令的技巧
#!/usr/bin/env python
对于应由 cronjob 执行的脚本,最好对 python 可执行文件的路径进行硬编码,因为 PATH 对于 cronjobs 来说是相当简约的,所以最好有类似的东西
#!/usr/bin/python3.5
或
#!/home/username/myvirtualenv/bin/python
每个 Python脚本都是在编写时考虑特定版本的 Python。如果 shebang 是#!/usr/bin/env python
的,则将使用的版本置于单个调用者的控制之下,其PATH
可能无法提供正确的版本。
#!/usr/bin/python
好一点,因为它将决定权交给了脚本本身。但是,脚本作者不一定知道 Python 的更正版本在您的系统上的位置,因此它仍然可能无法正常工作。
解决方案是在安装模块或脚本时指定系统上的正确位置。此时,Python 安装程序(pip
等(会将任何包含单词python
的 shebang(#!python
是最小的此类 shebang(重写为安装程序指定的路径。
现在,当您运行脚本时,它将指向您已经提供的正确路径,而不受运行时 PATH 查找的约束,该查找可能会选择错误的版本。
请注意,#!python
并不意味着按原样使用,尽管出于各种原因它可能对您有用。这是一种确保脚本获得正确解释器的固定、绝对路径的方法。#!/usr/bin/python
也会受到安装时替换的影响,因此可以作为可用的默认值。