シバンで環境変数を使用するにはどうすればよいですか?


34

特定のPythonインストールで実行する必要があるPythonスクリプトがあります。それが実行されるようにシバンを作成する方法はあり$FOO/bar/MyCustomPythonますか?

回答:


29

シバングラインは非常に限られています。多くのUNIXバリアント(Linuxを含む)では、コマンドと1つの引数という2つの単語しか使用できません。多くの場合、長さの制限もあります。

一般的な解決策は、小さなシェルラッパーを記述することです。Pythonスクリプトfoo.pyに名前を付け、シェルスクリプトを横に置いてfoo.py呼び出しますfoo。このアプローチでは、Pythonスクリプトに特定のヘッダーは必要ありません。

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

別の魅力的なアプローチは、上記のようなラッパースクリプトを記述#!/path/to/wrapper/scriptし、Pythonスクリプトのシェバン行として配置することです。ただし、ほとんどの大学はシバングスクリプトのチェーンをサポートしていないため、これは機能しません。

にある場合MyCustomPythonは、検索に$PATH使用できますenv

#!/usr/bin/env MyCustomPython
import 

さらに別のアプローチは、スクリプトを有効なシェルスクリプト(適切な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で同じ効果を実現する1つの方法を次に示します。シェル内"true"trueユーティリティは、引数(2つの1文字の文字列:')を無視し、真の値を返します。Pythonでは"true"、ブール値として解釈されるときにtrueにifなる文字列です。したがって、これは常にtrueであり、文字列リテラルを実行する命令です。

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

Rosettaコードには、他のいくつかの言語でこのような二重言語スクリプトがあります。


1
@Chris:すべてが単一引用符で囲まれています。...教えてください
ステファン・ヒメネス

1
あなたは血まみれのウィザードです...これは素晴らしいです。これを使用してPYTHONPATHenv変数を編集し、ルートアクセス権のないシステムでCGIスクリプトの非標準の場所からモジュールをロードしました。命の恩人。再度、感謝します。
wspurgin

12

シバン行は変数展開さ$FOO/MyCustomPythonれないため、dollar-FOO-という名前の実行可能ファイルを検索するために使用することはできません。

別の方法としては、シェバンがシェルスクリプトをインタープリターとして指すようにして、このシェルスクリプトが環境変数を使用して正しいものを見つけて実行することができます。

例:次のコンテンツmypython.sh/usr/local/bin(またはのその他のディレクトリ$PATH)にスクリプトを作成します。

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

次に、このshebang行を使用して、PythonスクリプトをMyCustomPythonviaで実行できますmypython.sh

#!/usr/bin/env mypython.sh

6
使用$pythonしないでください$PYTHON-慣例により、環境変数(大文字のPAGER、EDITOR、SHELL ... $PYTHONは環境変数ではありません)および内部シェル変数(BASH_VERSION、RANDOM、...)を大文字にします。他のすべての変数名には、少なくとも1つの小文字を含める必要があります。この規則により、環境変数および内部変数が誤ってオーバーライドされるのを防ぎます。また、スクリプトに拡張機能を使用しないでください。スクリプトは、実行可能な新しいコマンドを定義します。通常、コマンドには拡張機能はありません。
クリスダウン

4

カスタムPythonインストールへの絶対パスを使用するか、それをに$PATH使用してを使用することができます#!/usr/bin/env [command]。それ以外の場合はexec、例としてラッパーを作成し、プロセスイメージの置換に使用します。

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

3

最初に、Pythonのバージョンが既にインストールされている標準Python(追加モジュールなど)とどのように異なるかを判断し、プログラムの開始時に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インスタンスからプログラムを呼び出すことができます。システムのpythonにモジュールとしてインポートできないビルトインsqlライブラリを持つインスタンスに対しても同様のことを行います。


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では動作しません)。また、既存のすべてのディレクトリをパスから削除しているため、今後問題が発生する可能性があります。
ジル 'SO-悪であるのをやめる'

1
次のPATHように展開する方がPATH=$PATH:/path/to/whatever...
適切
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.