无法使用“#!/usr/bin/env python”将参数传递给 python
Posted
技术标签:
【中文标题】无法使用“#!/usr/bin/env python”将参数传递给 python【英文标题】:Cannot pass an argument to python with "#!/usr/bin/env python" 【发布时间】:2011-03-19 09:40:50 【问题描述】:我需要有一个直接可执行的 python 脚本,所以我用#!/usr/bin/env python
开始文件。但是,我还需要无缓冲输出,所以我尝试了#!/usr/bin/env python -u
,但使用python -u: no such file or directory
失败。
我发现#/usr/bin/python -u
可以工作,但我需要它来获得PATH
中的python
以支持虚拟env
环境。
我有什么选择?
【问题讨论】:
您可以查看SO question,了解有关如何进行无缓冲输出的一些信息。 【参考方案1】:将参数传递给 shebang 行不是标准的,并且正如您所试验的那样,它不能与 Linux 中的 env 结合使用。 bash 的解决方案是使用内置命令“set”来设置所需的选项。我认为您可以使用 python 命令设置标准输入的无缓冲输出。
my2c
【讨论】:
【参考方案2】:这是一个杂牌,需要 bash,但它可以工作:
#!/bin/bash
python -u <(cat <<"EOF"
# Your script here
print "Hello world"
EOF
)
【讨论】:
谢谢,这对我解决另一个问题很有效(使用带参数的单声道 csharp shell)【参考方案3】:当您在 Linux 上使用 shebang 时,解释器名称之后的整行其余部分将被解释为单个参数。 python -u
被传递给env
,就好像你输入了:/usr/bin/env 'python -u'
。 /usr/bin/env
搜索名为 python -u
的二进制文件,但没有。
【讨论】:
【参考方案4】:在某些环境中,env 不会拆分参数。
所以你的环境正在你的路径中寻找python -u
。
我们可以使用 sh 来解决。
用以下代码行替换您的 shebang,一切都会好起来的。
#!/bin/sh
''''exec python -u -- "$0" $1+"$@" # '''
# vi: syntax=python
附言我们不必担心 sh 的路径,对吧?
【讨论】:
对于那些想知道这是如何工作的人:Why does this snippet work?$1+"$@"
hack 可能至少有 20 年没有必要了 :)
黑客也许是不必要的,但它不会造成任何伤害,不是吗?知道它很有趣 :-) 我今天才知道它。无论如何,我认为"exec" "python" "-u" "--" "$0" "$@"
可能更容易理解——它有什么缺陷吗? (我认为它与1+
hack 不兼容?)
我的方法有个缺点。如果您想将一些复杂的东西传递给 bash,例如嵌套了 '
或 "
的字符串,那么您的方法更可靠。这是一个有趣的问题!我的可能更容易理解,但你的更健壮。也许您的答案应该澄清它必须以''''exec
开头,并且字符串必须以# '''
结尾(#
之前有一个空格)。只要我们遵循这些规则,并且没有任何额外的三引号'''
,您的方法就是完美且灵活的。
@user4815162342 Here 是$1+"$@"
的更多上下文。所以"$@"
在大多数情况下应该可以自己正常工作。【参考方案5】:
最好使用环境变量来启用它。参见 python 文档:http://docs.python.org/2/using/cmdline.html
你的情况:
export PYTHONUNBUFFERED=1
script.py
【讨论】:
每次重启时都需要这样做吗? @dan:当你在同一个 shell 中时不会。在export
一个变量之后,它将保持设置,直到您覆盖或unset
它【参考方案6】:
这可能有点过时,但 env(1) 手册告诉人们可以在这种情况下使用“-S”
#!/usr/bin/env -S python -u
它似乎在 FreeBSD 上运行良好。
【讨论】:
哇,如果这能广泛使用就好了,但在 cygwin 上也不可用:( 似乎-S
选项特定于 env(1)
的 BSD 变体,但很高兴知道
Linux 现在也有 env -S
- 从 coreutils 8.30 1 开始(可能需要一段时间才能出现在您附近的发行版上)。与 FreeBSD 的 env(1)
语义相同 - 万岁,因为良好的功能可移植性。
在 Solaris (11.3) 上也没有运气... :(
#!/usr/bin/env -S node --inspect - WORKS!【参考方案7】:
这里是/usr/bin/env
的替代脚本,它允许在哈希爆炸行上传递参数,基于/bin/bash
并且限制在可执行路径中不允许使用空格。我称之为“envns”(env No Spaces):
#!/bin/bash
ARGS=( $1 ) # separate $1 into multiple space-delimited arguments.
shift # consume $1
PROG=`which $ARGS[0]`
unset ARGS[0] # discard executable name
ARGS+=( "$@" ) # remainder of arguments preserved "as-is".
exec $PROG "$ARGS[@]"
假设这个脚本位于 /usr/local/bin/envns,这里是你的 shebang 行:
#!/usr/local/bin/envns python -u
在 Ubuntu 13.10 和 cygwin x64 上测试。
【讨论】:
这应该是捆绑的:) 注意:大多数 unix-ish #!出于安全原因,实现不允许使用脚本。我很惊讶这适用于 Ubunut 13.10。 截至 2019-01-20 也适用于 ubuntu 16.04,不确定其他版本。【参考方案8】:基于 Larry Cai 的回答,env
允许您直接在命令行中设置变量。这意味着-u
可以替换为python
之前的等效PYTHONUNBUFFERED
设置:
#!/usr/bin/env PYTHONUNBUFFERED="YESSSSS" python
适用于 RHEL 6.5。我很确定env
的功能几乎是通用的。
【讨论】:
仅供参考,这在 Debian 中不起作用。我不确定为什么它不起作用(查看ps
输出应该没有任何区别)但它永远不会返回。当您在 Debian 中执行此操作时,python 本身是否真的在运行并不是很清楚。我在几个地方试过这个 - 与等效的命令行相比,绝对不能按预期工作。
@MartyMacGyver。很可能与您使用的env
甚至python
的版本有关。
可能是 env 的版本,但到目前为止它不适用于任何现代 Debian 变体。 Python 似乎并没有真正在 Debian 上运行在这种情况下,这使得它在某些平台和/或配置之外的使用受到限制。【参考方案9】:
我最近为env
的 GNU Coreutils 版本编写了一个补丁来解决这个问题:
http://lists.gnu.org/archive/html/coreutils/2017-05/msg00018.html
如果你有这个,你可以这样做:
#!/usr/bin/env :lang:--foo:bar
env
将:lang:foo:--bar
拆分为lang
、foo
和--bar
字段。它将在PATH
中搜索解释器lang
,然后使用参数--foo
、bar
以及脚本的路径和该脚本的参数调用它。
还有一个功能可以在选项中间传递脚本的名称。假设您要运行lang -f <thecriptname> other-arg
,然后是剩余的参数。使用这个补丁env
,它是这样完成的:
#!/usr/bin/env :lang:-f::other-arg
相当于 的最左边字段被替换为后面的第一个参数,在哈希爆炸调用下,它是脚本名称。然后删除该参数。
这里,other-arg
可能是 lang
处理的东西,也可能是脚本处理的东西。
为了更好地理解,请查看补丁中的大量 echo
测试用例。
我选择了:
字符,因为它是POSIX 系统上PATH
中使用的现有分隔符。由于env
执行PATH
搜索,因此它几乎不可能用于名称包含冒号的程序。 标记来自
find
实用程序,它使用它来表示将路径插入-exec
命令行。
【讨论】:
对于任何阅读本文并感到充满希望的人,补丁was abandoned。以上是关于无法使用“#!/usr/bin/env python”将参数传递给 python的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 StorageClass 配置卷 - 无法获取存储帐户的存储密钥
Worklight Studio 和本地开发,有时无法使用 Java 类,有时无法使用 HTML 文件
Ubuntu 80端口无法使用-非root用户无法使用1024以下端口