别碰我的shebang

27 投票
5 回答
12581 浏览
提问于 2025-04-15 14:53

我最讨厌的一个事情就是关于distutils的,它会改变shebang行。简单来说,就是原本更合理、环境变量决定的内容

#!/usr/bin/env python

会神奇地变成

#!/whatever/absolute/path/is/my/python

这在使用grok的时候也能看到:我在一个虚拟环境中用grokproject开始了我的项目,但现在我不能随便移动开发目录了,因为它在shebang指令中写了绝对路径。

我问这个问题有两个原因:

  • 首先,我想移动项目,因为我最开始是在一个目录(Experiments)里开发的,现在想把它移到一个合适的路径,但我做不到。所以我创建了一个新的虚拟环境和grokproject,然后复制了我的文件。这样解决了问题,但我对更合理的解决方案还是很好奇。特别是,如果虚拟环境的Python解释器引用是相对的,最开始就不会出现这个问题。你知道虚拟环境的布局,可以很容易地引用虚拟环境的Python。
  • 第二个原因是,我希望能够把虚拟环境通过scp传到另一台电脑上,并且在那里顺利运行。如果路径是硬编码的,那就做不到。

5 个回答

2

我没有办法解决你的问题,但我能理解现在distutils的行为为什么是这样的。

#!/usr/bin/env python这行代码会运行系统默认的Python版本。只要你的代码能和这个版本兼容,这样做是没问题的。但是,如果系统默认的Python版本更新了(比如从2.5更新到3),那么你的代码或者其他引用了/usr/bin/env的Python代码可能就会出问题,尽管旧的Python版本仍然安装着。因此,直接写出合适的Python解释器的路径是有道理的。

补充:你说得对,指定python2.4或者类似的版本确实可以解决这个问题。

补充2:当同一个Python版本有多个安装时,事情就不那么简单了,正如Ned Deily在下面的评论中提到的。

13

Distutils会自动把脚本的第一行(也叫shebang)替换成执行setup.py时所用的Python程序的路径。如果你想改变这个默认行为,有两个方法可以选择:

方法一:手动设置

你可以在运行setup.py时加上一个参数--executable=/path/to/my/python,这样就可以指定你想用的Python路径。可以传递参数。

举个例子:

% python setup.py build --executable=/opt/local/bin/python -d

方法二:自动设置

另一个方法是向setup.cfg文件添加一行。如果你还没有setup.cfg文件,可以在和setup.py同一个文件夹里创建一个。setup.py在启动时会查找这个文件。这里指定的任何选项仍然可以通过命令行的参数来覆盖。

% cat setup.cfg 
[build]
executable = /opt/local/bin/python -d
15

当然,你可以随意移动开发目录。当你运行它时,Distutils 会自动调整你应该使用的 Python 路径。这些调整是在你执行构建操作时进行的。只需移动目录,然后重新运行启动脚本和构建操作,就完成了!

Distutils 会改变你用来运行它的 Python 路径。如果不这样做,你可能会在一个 Python 版本中安装一个库,但当你尝试运行脚本时,它会失败,因为脚本是用另一个没有这个库的 Python 版本运行的。

这并不是疯狂的做法,实际上这是唯一合理的方式。

更新:如果你知道自己在做什么,可以这样操作:

/path/to/install/python setup.py build -e "/the/path/you/want/python" install

不过,确保你先清理构建目录哦。:)

撰写回答