その行がなくてもファイルは同じように実行されるように思えます。
その行がなくてもファイルは同じように実行されるように思えます。
回答:
Pythonの複数のバージョンがインストールされている場合/usr/bin/env
は、使用するインタプリタが環境の最初のインタプリタであることを確認します$PATH
。代替案は、次のようなものをハードコーディングすることです#!/usr/bin/python
。それは問題ありませんが、柔軟性が低くなります。
Unixでは、解釈されることを意図した実行可能ファイル#!
は、最初の行の先頭にa を置き、その後にインタプリタ(および必要なフラグ)を付けることで、使用するインタプリタを示すことができます。
あなたが他のプラットフォームの話をしている場合は、当然のことながら、このルールは適用されません(ただし、その「シェバング行が」問題はありませんし、あなたがプラットフォームにそのスクリプトをコピーする場合に役立ちますと、このようなLinuxの、マックなどのUnixベース、 、など)。
chmod +x myscript.py
)、その後、それを直接実行している:./myscript.py
、というだけよりもpython myscript.py
。
env
すると、ユーザーがPATHを変更して使用するインタープリターを選択できるという点で、最大の柔軟性が得られます。多くの場合、この柔軟性は必要ありませんが、たとえばLinuxではプロセス名にスクリプト名を使用できず、ps
「python」に戻るという欠点があります。たとえば、ディストリビューション用のpythonアプリをパッケージ化するときは、使用しないようにアドバイスしますenv
。
py
ランチャーはWindowsでシバン行を使用できます。Python 3.3に含まれているか、個別にインストールできます。
/usr/bin/env: Key has expired
何時間も経過した後、メッセージでプロセスが停止してしまいました。
それはシバンラインと呼ばれています。Wikipediaのエントリ説明:
コンピューティングでは、シバン(ハッシュバング、ハッシュプリング、ポンドバン、クランチバンとも呼ばれます)は、文字「#!」を指します。それらがテキストファイルの最初の行としてインタープリターディレクティブの最初の2文字である場合。Unixライクなオペレーティングシステムでは、プログラムローダーはこれらの2文字の存在をファイルがスクリプトであることを示し、ファイルの最初の行の残りの部分で指定されたインタープリターを使用してそのスクリプトを実行しようとします。
Unix FAQエントリも参照してください。
実行するインタープリターがシバン行で決定されないWindowsでも、シバン行でオプションを指定することにより、インタープリターにオプションを渡すことができます。一般的なシバン行を1回限りのスクリプト(SOで質問に答えるときに書いたスクリプトなど)で維持すると便利です。そのため、WindowsとArchLinuxの両方ですばやくテストできます。
ENVユーティリティは、あなたがパス上でコマンドを呼び出すことができます:
残りの最初の引数は、呼び出すプログラム名を指定します。
PATH
環境変数に従って検索されます。残りの引数は、引数としてそのプログラムに渡されます。
他の答えを少し広げて、コマンドラインスクリプトが/usr/bin/env
シバン行を慎重に使用することによってトラブルに陥る方法の小さな例を次に示します。
$ /usr/local/bin/python -V
Python 2.6.4
$ /usr/bin/python -V
Python 2.5.1
$ cat my_script.py
#!/usr/bin/env python
import json
print "hello, json"
$ PATH=/usr/local/bin:/usr/bin
$ ./my_script.py
hello, json
$ PATH=/usr/bin:/usr/local/bin
$ ./my_script.py
Traceback (most recent call last):
File "./my_script.py", line 2, in <module>
import json
ImportError: No module named json
jsonモジュールはPython 2.5には存在しません。
この種の問題を防ぐ1つの方法は、ほとんどのPythonで通常インストールされるバージョン付きのpythonコマンド名を使用することです。
$ cat my_script.py
#!/usr/bin/env python2.6
import json
print "hello, json"
Python 2.xとPython 3.xを区別するだけの場合は、Python 3の最近のリリースでもpython3
名前が提供されています。
$ cat my_script.py
#!/usr/bin/env python3
import json
print("hello, json")
which python
返す場合は/usr/bin/python
、ローカルディレクトリパスをハードコードできます:#!/usr/bin/python
。しかし、それは#!/usr/bin/env python
グローバルなアプリケーションよりも柔軟性に欠けます。
pythonスクリプトを実行するには、シェルに3つのことを伝える必要があります。
シバンは#!
達成します(1.)。キャラクターは多くのスクリプト言語のコメントマーカーである#
ため、シバンはaで始まり#
ます。したがって、シバン行の内容はインタープリターによって自動的に無視されます。
env
コマンドが実現(2)と(3)。「うれしさ」を引用すると
env
コマンドの一般的な用途は、envが起動するように指示されたコマンドの$ PATHを検索するという事実を利用して、インタープリターを起動することです。シバン行では絶対パスを指定する必要があり、さまざまなインタープリター(perl、bash、python)の場所が大きく異なる可能性があるため、次のように使用するのが一般的です。
#!/usr/bin/env perl
/ bin / perl、/ usr / bin / perl、/ usr / local / bin / perl、/ usr / local / pkg / perl、/ fileserver / usr / bin / perl、/ homeのいずれであるかを推測する代わりに/ MrDaniel / usr / bin / perl(ユーザーのシステム上)...一方、envはほとんど常に/ usr / bin / envにあります。(そうでない場合を除いて、一部のシステムは/ bin / envを使用する場合がありますが、それはかなりまれなケースであり、Linux以外のシステムでのみ発生します。)
おそらくあなたの質問はこの意味です:
使用したい場合: $python myscript.py
その行はまったく必要ありません。システムはpythonを呼び出し、次にpythonインタープリターがスクリプトを実行します。
ただし、使用する場合: $./myscript.py
通常のプログラムやbashスクリプトのように直接呼び出す場合は、その行を記述して、実行に使用するプログラムをシステムに指定する必要があります(また、で実行可能にするchmod 755
)
exec
Linuxカーネルのシステムコールはシバン(#!
)をネイティブに理解します
bashを行う場合:
./something
Linuxでは、これはexec
システムコールをパスで呼び出します./something
。
カーネルのこの行は、httpsexec
://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25に渡されるファイルで呼び出されます。
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
ファイルの最初のバイトを読み取り、それらをと比較します#!
。
比較が真の場合、行の残りの部分はLinuxカーネルによって解析され、最初の引数としてexec
パス/usr/bin/env python
と現在のファイルを使用して別の呼び出しを行います。
/usr/bin/env python /path/to/script.py
これは#
、コメント文字として使用するすべてのスクリプト言語で機能します。
そして、はい、あなたは無限ループを作ることができます:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a
Bashはエラーを認識します。
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#!
たまたま人間が読めるだけですが、それは必須ではありません。
ファイルが異なるバイトで始まった場合、exec
システムコールは異なるハンドラーを使用します。その他の最も重要な組み込みハンドラーは、ELF実行可能ファイル用です。https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305は、バイトをチェックします7f 45 4c 46
(これは、人間にも起こります)読み取り可能.ELF
)。/bin/ls
ELF実行可能ファイルであるの最初の4バイトを読み取ることで確認します。
head -c 4 "$(which ls)" | hd
出力:
00000000 7f 45 4c 46 |.ELF|
00000004
そのため、カーネルがこれらのバイトを認識すると、ELFファイルを取得し、それをメモリに正しく配置して、新しいプロセスを開始します。参照:カーネルはどのようにLinuxで実行可能な実行可能バイナリファイルを取得しますか?
最後に、binfmt_misc
メカニズムを使用して独自のシバンハンドラーを追加できます。たとえば、.jar
ファイルのカスタムハンドラーを追加できます。このメカニズムは、ファイル拡張子によってハンドラーもサポートします。別のアプリケーションは、QEMUで異なるアーキテクチャの実行可能ファイルを透過的に実行することです。
私はPOSIXがシバンを指定しているとは思いません:https ://unix.stackexchange.com/a/346214/32558 、それは根拠のセクションで、そして「実行可能スクリプトがシステムによってサポートされている場合、何かが起こる」。ただし、macOSとFreeBSDでも実装されているようです。
PATH
検索動機
おそらく、シバンが存在する大きな動機の1つは、Linuxでは、次のようにコマンドを実行したいということですPATH
。
basename-of-command
の代わりに:
/full/path/to/basename-of-command
しかし、シバンメカニズムがなければ、Linuxは各タイプのファイルを起動する方法をどのように知るのでしょうか。
コマンドでの拡張子のハードコーディング:
basename-of-command.py
または、すべてのインタープリターにPATH検索を実装します。
python basename-of-command
可能性はありますが、コマンドを別の言語にリファクタリングすることを決定した場合、すべてが壊れるという大きな問題があります。
シバンはこの問題を美しく解決します。
技術的には、Pythonでは、これは単なるコメント行です。
この行は、シェルから(コマンドラインから)pyスクリプトを実行する場合にのみ使用されます。これは「シバン」として知られています。、Pythonスクリプトだけでなく、さまざまな状況で使用されます。
ここでは、特定のバージョンのPython を起動するようにシェルに指示します(ファイルの残りの部分を処理します)。
py.exe
。これは、標準のPythonインストールの一部です。
これを行う主な理由は、オペレーティングシステム環境間でスクリプトを移植できるようにするためです。
たとえば、mingwの下では、pythonスクリプトは以下を使用します。
#!/c/python3k/python
GNU / Linuxディストリビューションでは、次のいずれかです。
#!/usr/local/bin/python
または
#!/usr/bin/python
そして、最高の商用Unix sw / hwシステム(OS / X)の下では、次のようになります。
#!/Applications/MacPython 2.5/python
またはFreeBSDの場合:
#!/usr/local/bin/python
ただし、これらすべての違いにより、以下を使用することにより、スクリプトをすべてに移植できます。
#!/usr/bin/env python
/usr/bin/python
です。Linuxでは、システムによってインストールされたPythonもほぼ確実です/usr/bin/python
(私は他に何も見たことがないので、意味がありません)。がないシステムがあるかもしれないことに注意してください/usr/bin/env
。
python
はそれほどポータブルではなく、ディストリビューションのデフォルトのPythonインタープリターです。Arch Linuxは長い間デフォルトでPython 3を使用しますが、Python 2は2020
最も見落としがちなことをすぐに理解できない可能性があることを強調することはおそらく意味があります。python
端末に入力するとき、通常はフルパスを提供しません。代わりに、実行可能ファイルはPATH
環境変数で検索されます。次に、Pythonプログラムを直接実行する場合は/path/to/app.py
、使用するインタプリタをシェルに指示する必要があります(ハッシュバングを介して、他のコントリビュータが上で説明しているもの)。
Hashbangはインタープリターへのフルパスを期待しています。したがって、Pythonプログラムを直接実行するには、特にvirtualenvの使用を考慮すると、大幅に異なるPythonバイナリへのフルパスを提供する必要があります。移植性に対処するためのトリック/usr/bin/env
が使用されます。後者は元々環境をインプレースで変更し、そこでコマンドを実行することを目的としています。変更が提供されていない場合、現在の環境でコマンドを実行します。これにより、効果的に同じPATH
ルックアップが行われます。
これは、どのプログラムがスクリプトを実行できるかをシェルに伝えるシェル規則です。
#!/ usr / bin / env python
Pythonバイナリへのパスに解決されます。
ドキュメントで提案されている推奨される方法:
2.2.2。実行可能なPythonスクリプト
BSD風のUnixシステムでは、Pythonスクリプトは、シェルスクリプトのように、次の行を挿入することで直接実行可能にすることができます。
#! /usr/bin/env python3.2
http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scriptsから
使用するインタープリターを指定するだけです。これを理解するには、ターミナルからを実行してファイルを作成し、touch test.py
そのファイルに次のように入力します。
#!/usr/bin/env python3
print "test"
そして、行うchmod +x test.py
スクリプトを実行可能にします。この後、あなたが./test.py
するとき、あなたは言っているエラーを得るべきです:
File "./test.py", line 2
print "test"
^
SyntaxError: Missing parentheses in call to 'print'
python3は印刷演算子をサポートしていないためです。
次に、コードの最初の行を次のように変更します。
#!/usr/bin/env python2
test
python2が印刷演算子をサポートしているので、標準出力に印刷して機能します。これで、スクリプトインタープリターを切り替える方法を学びました。
その行がなくてもファイルは同じように実行されるように思えます。
もしそうなら、おそらくあなたはWindowsでPythonプログラムを実行していますか?Windowsはその行を使用しません。代わりに、ファイル名拡張子を使用して、ファイル拡張子に関連付けられているプログラムを実行します。
ただし、2011年には、このLinuxの動作をWindowsで(ある程度)模倣する「Pythonランチャー」が開発されました。これは、実行するPythonインタープリターを選択することだけに限定されます。たとえば、両方がインストールされているシステムでPython 2とPython 3のどちらかを選択します。ランチャーはpy.exe
、Pythonのインストールと同様にオプションでインストールされ.py
、ランチャーがその行をチェックして、指定されたPythonインタープリターバージョンを起動するようにファイルに関連付けることができます。
$ python myscript.py
いる可能性があります。
これは、「実際の」答えよりも多くの履歴情報を意味します。
あなたはデザイナーのすべてのものを置く場所の独自の概念を持っていた、と時々のPython、Perlの、Bash、または他のGNU /オープンソースのものがたくさん含まれていませんでしたオペレーティングシステムのようなUNIXのLOTSた日にその背中を忘れないでくださいすべてのを。
これは、さまざまなLinuxディストリビューションにも当てはまります。Linuxの場合-FHS以前[1]-/ usr / bin /または/ usr / local / bin /にpythonがある場合があります。または、インストールされていない可能性があるため、独自にビルドして〜/ binに配置しました
Solarisは、部分的にはBerkeley UnixからSystem Vへの移行として、私がこれまで取り組んだ中で最悪でした。/usr/、/usr/local/、/usr/ucb、/opt/などにあるもので終わる可能性があります。これにより、いくつかのために、本当に長いパス。Sunfreeware.comの各パッケージを独自のディレクトリにインストールしたことの思い出がありますが、バイナリが/ usr / binにシンボリックリンクされているかどうかは思い出せません。
ああ、そして時には/ usr / binがNFSサーバー上にあった[2]。
したがって、env
ユーティリティはこれを回避するために開発されました。
それからあなたは書くことができ#!/bin/env interpreter
、パスが適切である限り、物事が実行される合理的なチャンスがありました。もちろん、妥当な意味(PythonおよびPerlの場合)は、適切な環境変数も設定したことを意味します。bash / ksh / zshの場合は機能しました。
これは、人々がシェルスクリプト(perlやpythonなど)を迂回していて、Red Hat Linuxワークステーションで/ usr / bin / pythonをハードコーディングした場合、SGIで問題が発生するため、重要でした。 、私はIRIXがpythonを正しい場所に置いたと思います。しかし、Sparcステーションではまったく動作しない可能性があります。
私のsparcステーションが恋しいです。しかし、多くはありません。さて、あなたは私にE-Bayをぶらぶらさせてもらいました。バステージ。
[1]ファイルシステム階層標準。https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2]はい、そして時々人々はまだそのようなことをします。いいえ、帯にはカブもタマネギも着用していません。
たとえば、仮想環境でスクリプトをvenv
実行which python
しているvenv
場合、作業中に実行すると、Pythonインタープリターへのパスが表示されます。
~/Envs/venv/bin/python
仮想環境の名前は、Pythonインタープリターへのパスに埋め込まれていることに注意してください。したがって、スクリプトでこのパスをハードコーディングすると、2つの問題が発生します。
したがって、ジョナサンの答えに加えて、理想的なシバンは#!/usr/bin/env python
、OS間の移植性だけでなく、仮想環境全体の移植性でもあります。
との間の移植性の問題を考慮するpython2
とpython3
、プログラムが両方と互換性がない限り、常にどちらかのバージョンを指定する必要があります。
いくつかのディストリビューションは、出荷されているpython
にシンボリックリンクpython3
今しばらくの間-に依存しないpython
ことpython2
。
これはPEP 394で強調されています:
プラットフォーム間の違いを許容するには、Pythonインタープリターを呼び出す必要があるすべての新しいコードでpythonを指定するのではなく、python2またはpython3(またはより具体的なpython2.xおよびpython3.xバージョンを指定する必要があります。移行に関する注意事項を参照) 。この区別は、シェルスクリプトから呼び出す場合、system()呼び出しを介して呼び出す場合、または他のコンテキストで呼び出す場合に、シバンで行う必要があります。
使用する実行可能ファイルを選択できます。これは、おそらく複数のpythonインストールがあり、それぞれに異なるモジュールがあり、選択したい場合に非常に便利です。例えば
#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
echo Using preferred python $ALTERNATIVE_PYTHON
exec $PREFERRED_PYTHON "$0" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
echo Using alternative python $ALTERNATIVE_PYTHON
exec $ALTERNATIVE_PYTHON "$0" "$@"
else
echo Using fallback python $FALLBACK_PYTHON
exec python3 "$0" "$@"
fi
exit 127
'''
__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())
#!/usr/bin/env python
上部にのみWebページを実行および表示するCGIスクリプト(.py)。