如何在shebang中使用环境变量?


34

我有一个Python脚本,需要与特定的python安装一起运行。有没有一种方法可以制作Shebang,使其与之一起运行$FOO/bar/MyCustomPython

Answers:


29

射手线非常有限。在许多unix变体(包括Linux)下,您只能有两个词:命令和单个参数。通常也有长度限制。

通用的解决方案是编写一个小的外壳包装程序。命名Python脚本foo.py,并将shell脚本放在旁边foo.py并调用它foo。这种方法不需要Python脚本上的任何特定标头。

#!/bin/sh
exec "$FOO/bar/MyCustomPython" "$0.py" "$@"

另一种诱人的方法是像上面的脚本那样编写包装脚本,并将其#!/path/to/wrapper/script作为shebang行放在Python脚本上。但是,大多数联合国不支持shebang脚本的链接,所以这是行不通的。

如果MyCustomPython位于中$PATH,则可以使用env它进行查找:

#!/usr/bin/env MyCustomPython
import 

另一种方法是将脚本安排为有效的Shell脚本(在其自身上加载正确的Python解释器)和目标语言(此处为Python)的有效脚本。这就要求您找到一种为目标语言编写这种双语言脚本的方法。在Perl中,这称为if $running_under_some_shell

#!/bin/sh
eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
    if $running_under_some_shell;
use 

这是在Python中达到相同效果的一种方法。在外壳程序中"true"true实用程序,该实用程序将忽略其参数(两个单字符字符串:')并返回一个真值。在Python中,"true"是一个字符串,当解释为布尔值时为true,因此这是一条if始终为true并执行字符串文字的指令。

#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import 

Rosetta代码具有其他几种语言的这种双语言脚本。


1
@克里斯:一切都在单引号内。请解释...
斯特凡希门尼斯

1
你是个流血的巫师……太好了。我用它来编辑PYTHONPATHenv变量,以从非标准位置为我没有root访问权限的系统上的CGI脚本加载模块。救生员。再次感谢。
wspurgin '16

12

Shebang行不会进行变量扩展,因此您无法使用$FOO/MyCustomPython它,因为它将搜索名为dollar-FOO -...的可执行文件。

一种替代方法是让您的shebang指向shell脚本作为解释器,然后该shell脚本可以使用环境变量来找到正确的脚本并执行。

示例:mypython.sh/usr/local/bin(或上的任何其他目录$PATH)中创建一个脚本,其内容如下:

#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"

那么您可以使用该shebang行MyCustomPython通过mypython.sh以下命令执行Python脚本:

#!/usr/bin/env mypython.sh

6
使用$python,而不是$PYTHON-按照惯例,我们将环境变量($PYTHON脚本中的PAGER,EDITOR,SHELL ... 不是环境变量)和内部shell变量(BASH_VERSION,RANDOM等)大写。所有其他变量名称应至少包含一个小写字母。该约定避免了意外覆盖环境和内部变量。另外,请勿对脚本使用扩展名。脚本定义了可以运行的新命令,并且通常不给命令扩展名。
克里斯·唐纳

4

您可以使用自定义python安装的绝对路径,也可以将其放入$PATHand使用中#!/usr/bin/env [command]。否则,为其编写包装器,并使用它exec来替换过程映像,例如:

#!/bin/bash
exec "$ENV/python" "$@"

3

首先,确定您的Python版本与已安装的标准Python(例如,附加模块)有何不同,然后在程序“ switch”开始时,如何调用Python:

#!/usr/bin/python
import os
import sys
try:
    import MyCustomModule
except ImportError:
    # only need to use expandvar if you know the string below has an envvar
    custprog = os.path.expandvar("$FOO/bar/MyCustomPython")
    os.execv(custprog, sys.argv) # call alternate python with the same arguments
    raise SystemExit('could not call %s' % custprog)
# if we get here, then we have the correct python interpreter

这应该允许该程序被任何其他Python实例调用。对于带有内置sql库的实例,我无法执行类似的操作,而该实例无法作为系统python中的模块导入。


0

如果你可以替换$FOO$FOO/bar/MyCustomPython用具体路径的选择,你可以告诉env家当行,其中通过直接设置自定义查找您的自定义Python版本PATH中它。

#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python

编辑:似乎只工作不带引号的PATH值周围:

#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python

5
请注意,这不适用于所有的unix变体(例如,不适用于Linux)。而且您要从路径中删除所有现有目录,这很可能会导致问题。
吉尔(Gilles)“所以,别再邪恶了”,

1
PATH好像这样展开:PATH=$PATH:/path/to/whatever...
Bengt 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.