【问题标题】:How to fix shebang flags that are not recognized on some systems如何修复在某些系统上无法识别的 shebang 标志
【发布时间】:2011-04-20 19:29:55
【问题描述】:

由于某种原因,-O(优化)标志在我访问的 Red Hat Enterprise Server(版本 5.3)的 shebang 行中无法识别。在其他系统上,可以毫无问题地识别标志。

在 OS X 上执行以下脚本可以正常工作。可以验证对 -O 标志的识别,因为它启用(如果不存在)或禁用(如果给定)if __debug__ 条件下的任何内容:

#!/usr/bin/env python -O                                                                                                                                                                       

if __name__ == '__main__':

    if __debug__:
        print 'lots of debugging output on'

    print 'Fin'

在 RHE 系统上执行相同的脚本会导致:

/usr/bin/env: python -O: 没有这个文件 或目录

没有-O标志,脚本在RHE系统上正常执行(即,__debug__内置变量将设置为True)。

是否有解决此问题的跨平台方法?是否有特定于平台的方法来解决 shebang 行上的标志问题到 python 解释器?

编辑:在解释器范围内设置 __debug__ 变量(不使用 shebang 标志)的任何其他解决方法也很有趣。

【问题讨论】:

  • 我依稀记得一个说法,你不能指望能够在shebang中传递多个参数,而python就是/usr/bin/env python中的那个参数...
  • @delnan 这也是我的恐惧。我希望可能有一些巧妙的方法来引用python 以及可以使用的标志,但我没有找到任何东西。
  • @uku 因为在某些系统上,我不希望默认python的系统版本(通常版本$PATH设置选择默认的python解释器(例如,可能在其主目录中的解释器)。
  • @Uku Loskit:使用/usr/bin/env python 可以让你的脚本在不同地方安装了python的不同机器上运行。
  • @Uku:因此,每当 python 解释器的位置发生变化时(或者 - 对于广泛分布的东西非常重要 - 当您将它安装在放置其他地方的解释器),或者您将不同的解释器提升为默认版本(使用python3 时更可能的情况)。

标签: python shell shebang


【解决方案1】:

制作一个小shell脚本怎么样:

pythono

#!/bin/sh    
/usr/bin/env python -O "$@"

然后更改您的脚本以使用:

#!pythono       

另请注意,将环境变量PYTHONOPTIMIZE 设置为非空字符串与使用-O 标志相同。来自man python 手册页:

   PYTHONOPTIMIZE
          If this is set to a non-empty string it is equivalent to  specifying  the
          -O option. If set to an integer, it is equivalent to specifying -O multi‐
          ple times.

【讨论】:

  • 呃,如果你能做到,你不需要env,你可以有python -O "$@"
  • 我喜欢这个。我认为这是解决我的特定问题的最简单的方法。
  • @unutbu 我将/usr/bin/env 调用移至pythono 内部,因为这大概就是您的意思。应该不需要调用/usr/bin/env pythono,而如果你不调用env,脚本可能会执行错误的python。注意pythono 也必须在您的PATH 上。
【解决方案2】:

某些系统不允许在#! 样式的行上有多个参数。在任何情况下,“env hack”都不是官方推荐的解决路径问题的方法——解决这个问题的首选方法是让安装程序重写#! 行以引用/bin/python/usr/bin/python,如适合系统。

http://pubs.opengroup.org/onlinepubs/009695399/utilities/sh.html

【讨论】:

  • 也很高兴知道。谢谢随机。
【解决方案3】:

为了稍微扩展unutbu 所说的内容,您可以选择在运行时初始化PYTHONOPTIMIZE。这适用于所有现代 shell:

% PYTHONOPTIMIZE=1 foo.py
Fin

为了完整性:

% foo.py
lots of debugging output on
Fin

【讨论】:

  • 谢谢。能够基于每个脚本启用/禁用会更好。
  • 你知道的!这是 *nix 范围内的事情,而不是特定于 Python。
【解决方案4】:

请试试这个:

#!/bin/sh
''''exec python -O -- "$0" ${1+"$@"} # '''
if __name__ == '__main__':

    if __debug__:
        print 'lots of debugging output on'

    print 'Fin'
# vi: syntax=python

【讨论】:

  • 不错的多语言脚本!
【解决方案5】:

将shebang更改为:

#!/usr/bin/python -O

当然,这假设 Python 解释器安装为 /usr/bin/python;否则,根据需要进行调整。

另请参阅this questionmy answer to it

【讨论】:

    【解决方案6】:

    我相信您使用#!/usr/bin/env python 的原因是您可以利用PATH 找到您最喜欢的python 版本。

    如果不是这种情况,并且您可以使用/usr/bin/python(或解释器的其他硬编码路径),那么最直接的解决方案应该是使用@keith-thompson 建议的#!/usr/bin/python -O

    但是,假设您想继续依赖 PATH 来查找 python,您需要调用 shell 才能控制命令行:

    #!/bin/sh
    exec python -O - "$@" <<EOF
    
    # ... your python code starts here ...
    if __name__ == '__main__':
    
        if __debug__:
            print 'lots of debugging output on'
    
        print 'Fin'
    # ... your python code ends here ...
    
    EOF
    

    这类似于@unutbu 建议的pythono 解决方案,只是它不依赖PATH 来查找中间脚本,这意味着它的性能稍好一些,并且更安全一些。

    这个解决方案的缺点是混合了两种语言,这意味着你不能简单地说python myscript.py 来执行你的代码并将__debug__ 设置为True。如果您打算有时通过脚本(例如~/bin/myscript.py)直接执行代码并打开-O,但有时在调试环境中手动运行脚本(例如python ~/bin/myscript.py)和@ 987654337@ 关闭,那么我相信你最好的选择是使用@ade-yu 提出的专家技巧或使用@unutbu 建议的简单pythono 选项。

    希望这会有所帮助!

    【讨论】:

    • 您需要使用“EOF”(带引号)来避免让 shell 尝试解释 heredoc 的内容(比如文本中是否有 $foo)。
    【解决方案7】:

    让你的shebang不带旗帜;然后,再次执行环境,并将标志传递给heredoc。

    #!/usr/bin/env python
    
    /usr/bin/env python -O <<EOF
    code goes here...
    ...
    EOF
    

    基本上在文件末尾有你的终止EOF。

    【讨论】:

    • /usr/bin/env python -O &lt;&lt;EOF 是无效的语法,实际上这对我来说会导致SyntaxError。 -1
    • 这还不错,只需稍作改动即可解决您尝试使用 python interpeter 运行 shell 代码的事实。而是让它成为一个 shell 脚本:#!/bin/sh 在 shebang 行,然后在下一行 exec python -O &lt;&lt; EOF(注意 exec 并且不需要 /usr/bin/env)。
    【解决方案8】:

    假设您想继续使用#!/usr/bin/env,您可以利用以下事实

    1. python 的命令行开关具有等效的环境变量
    2. env可用于在运行命令前设置环境变量

    将这些放在一起,您将得到以下解决方案:

    #!/usr/bin/env PYTHONOPTIMIZE=1 python

    您要求“跨平台”。这仅适用于 Unix(例如 Linux、OS X 等)。我不能为 Windows 说话。我希望这也能在 cygwin 下工作,但 YMMV。

    【讨论】:

    • 这遇到了同样的问题,即只有 she-bang 行中的第一个参数被保证传递给解释器,例如。 G。在 Linux 上,这会导致 /usr/bin/env 调用的无限递归,因为 PYTHONOPTIMIZE=1 python 被解释为单个参数。 -1
    • @DavidFoerster 的评论似乎是有效的——至少我也可以在 freebsd 上重现该问题。也许在这个答案中更正会很有用。
    • 感谢@david-foerster。我在 OS X 上进行了测试,它运行良好,但没有意识到在 Linux 上它实际上是 exec ` '/usr/bin/env' 'PYTHONOPTIMIZE=1 python' _script_` 显然没有达到目的。我会提出一个新的答案。
    猜你喜欢
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2021-03-24
    • 2021-04-20
    • 2011-11-06
    • 2014-07-11
    相关资源
    最近更新 更多