在python的shebang中包含命令行选项是否可行?

17

我的Python脚本的顶部有规范化的shebang。

#!/usr/bin/env python

然而,当我运行我的脚本时,我仍经常希望将无缓冲输出导出到日志文件中,因此最终会调用以下命令:

$ python -u myscript.py &> myscript.out &

我能否在shebang中嵌入-u选项,就像这样...

#!/usr/bin/env python -u

仅调用:

$ ./myscript.py &> myscript.out &

...仍然获得无缓冲? 我怀疑这样做行不通,并想在尝试之前进行确认。 有什么方法可以实现这个吗?


是的,你应该这样做。 "shebang" 只是一个指向脚本负责的二进制应用程序的指针。如果没有,你可以创建一个别名 alias ppython="python -u" 并且只需使用 #!/usr/bin/env ppython - Torxed
2
Torxed,你试过你的答案了吗?这种方法在OSX或Linux中不起作用。如果它在你的操作系统中起作用,请分享细节,因为那将是有趣的。它不能在OSX或Linux(或我相信,任何一种Unix)中工作的原因是env在路径上搜索可执行文件,而别名不在路径上。别名在shebang行上的工作方式和原因与内置命令在shebang行上的工作方式和原因相同。如果你的操作系统允许这样做,请分享! - Chris Johnson
3个回答

14

在shebang行中可以添加参数,但大多数操作系统对参数的数量有非常小的限制。POSIX仅要求支持一个参数,这是很普遍的,包括Linux。

由于您正在使用/usr/bin/env命令,因此已经使用了该单个参数来运行python,因此无法添加另一个参数-u。如果要使用python -u,则需要硬编码python的绝对路径,而不是使用/usr/bin/env,例如:

#!/usr/bin/python -u

参见相关问题:如何在 shebang(即 #!)中使用多个参数?


谢谢。看起来很容易,但我知道肯定有陷阱。=)是否有人深入POSIX要求的内部,我可以给他们发送电子邮件,谈论如果支持多个参数将会是多么棒的功能? - Mittenchops
3
可能不会。这就是一直以来的工作方式,而 POSIX 只是将现有的行为标准化了。即使他们改变了 POSIX,您也需要等待数年时间才能够使用可移植性重设计足够多的实现。 - Barmar

7

自coreutils 8.30版开始,env的新版本中有一个名为-S的选项。引用自man env

   The -S option allows specifing multiple parameters in a script.  Running a script named 1.pl containing the follow‐
  ing first line:

         #!/usr/bin/env -S perl -w -T

  Will execute perl -w -T 1.pl .

  Without the '-S' parameter the script will likely fail with:

         /usr/bin/env: 'perl -w -T': No such file or directory

1
太棒了!我的祈祷在8年后得到了回应! - Mittenchops

4

一种便携的方法是创建另一个可执行文件来体现您的选项。

例如,将此文件放在您的路径上并命名为upython,并使其可执行:

#!/usr/bin/env bash
python -u -and -other -options "$@"

使用您需要的任何选项运行命令。然后您的myscript.py脚本可以像这样:

#!/usr/bin/env upython
(... your normal Python code ...)
建议通过shell别名来实现这个功能。但我认为在任何版本的Unix系统中都不会奏效。我在几个发行版上测试了一下,都没有成功。我的方法可以在任何Unix系统中使用。

传递命令行参数到另一个脚本或函数的正确方式是使用带引号的 "$@"(而不是 $@),因为没有引号,带有空格的参数会被分割。 (关于别名的部分是绝对正确的。它不起作用。)最后,我建议永远不要使用 env bash,而是直接使用 bash 的路径(例如,#!/bin/bash)。Python确实存在问题。Bash则不然。事实上,Bash的更大问题在于在调整了 PATH 以使用其他不同工具(如python、make等)之后,意外使用了错误的Bash版本。 - michael
对于像这样的包装脚本,我喜欢加入"exec",这样包装器就不会再进程列表中出现。即:"exec python -u -and -other ...." - Chris Cogdon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接