【问题标题】:Is it possible to construct a shebang that works for both Python 2 and 3?是否可以构建一个适用于 Python 2 和 3 的 shebang?
【发布时间】:2021-12-13 23:24:48
【问题描述】:

我需要编写一个与 Python 2 和 Python 3 兼容的 Python 脚本,可以直接从 shell 调用(意味着它有一个 shebang),并且可以在安装了任何一个 Python 版本但可能没有的系统上运行两者都有。

通常我可以像这样为 Python 2 编写一个 shebang:

#!/usr/bin/env python

对于 Python 3:

#!/usr/bin/env python3

但是如果没有安装相应的 Python 版本,这两个都将失败,因为据我所知,具有 Python 3 但没有 Python 2 的系统不会将 python 别名或符号链接到 python3。 (如果我错了,请纠正我。)

那么有没有办法编写一个带有 shebang 的 Python 脚本,只要安装了其中一个,它就会使用 Python 2 或 Python 3 执行脚本?

这主要是为了解决即将发布的macOS版本中删除Python 2的问题, (注:我最初写的时候是在错误理解Python 2会被Python 3取代的情况下写的在 macOS 中,但实际上 Apple 正在完全删除 Python。) 但也可以应用于 Linux。

【问题讨论】:

  • 第一个 shebang 调用默认 Python,可以是 2 或 3。系统不太可能安装特定版本但不会设置默认 Python 别名。所以,TLDR:第一个 shebang 就是你要找的。​​span>
  • 您能否仅使用 shell 脚本检测 Python 的存在或不存在,并根据 shell 脚本检测到的内容调用正确的解释器?
  • 首先您将如何安装脚本?通常您不会自己编写 shebang,安装程序会在安装代码时编写它,并且它与用于安装包的任何 Python 运行时相关联。
  • 只有 Python 3 的系统通常将其安装在 python 名称下。这是经销商的选择,但我经常看到它。
  • @AlexW 我考虑过这样做,但如果可能的话,我更愿意将脚本保留为单个文件,该文件仍可以导入 python 并作为独立脚本直接运行。一个正确的 shebang 可以做到这一点。

标签: python python-3.x shell shebang


【解决方案1】:

实际上,我只会指定 python3 并将其作为先决条件。

但是,从技术上讲,可以欺骗 Python 文件使其成为自己的 shell 脚本包装器:

#!/bin/sh
''':'
for name in python3 python2 python
do
    type "$name" > /dev/null 2>&1 && exec "$name" "$0" "$@"
done
echo >&2 "Please install python"
exit 1
':'''

print("Hello from Python")

【讨论】:

  • 这太棒了!您应该提到 exec 替换了当前的 shell 脚本。
  • 我想知道这样的事情是否可行!我也很好奇 ''':'':''' 有什么意义,以及它如何不影响中间的 shell 脚本。
  • 你确定也需要转发参数吗?
  • @BriBri: 对于 shell,''':' 就是 :(查找“冒号命令”)
  • 我唯一想知道的是echo >&2 "..." 与外壳无关