その行がなくてもファイルは同じように動作するようです。
いくつかのバージョンのPythonがインストールされている場合、/usr/bin/env
は、使用されるインタプリタがあなたの環境の$PATH
の最初のものであることを確認します。代わりの方法は、#!/usr/bin/python
のようなものをハードコードすることです。それは問題ありませんが、それほど柔軟ではありません。
Unixでは、解釈されることを意図された executable ファイルは、最初の行の先頭に#!
を持ち、その後にインタプリタ(そしてそれが必要とするかもしれないフラグ)を置くことによってどのインタプリタを使うかを示すことができます。
あなたが他のプラットフォームについて話しているのであれば、もちろん、この規則は適用されません(しかしその "Shebang line"は害を及ぼさず、そのスクリプトをUnixベースのプラットフォーム with にコピーすれば助けになります。 Linux、Macなどとして).
それは Shebang line と呼ばれます。 Wikipediaの記事に説明されているように :
コンピューティングでは、Shebang(ハッシュバング、ハッシュサンプリング、ポンドバング、またはクランチバングとも呼ばれます)は文字 "#!"を表します。それらがテキストファイルの最初の行としてインタプリタディレクティブの最初の2文字であるとき。 Unixライクなオペレーティングシステムでは、プログラムローダーはこれら2文字の存在をファイルがスクリプトであることを示すものとして扱い、ファイルの最初の行の残りで指定されたインタプリタを使ってそのスクリプトを実行しようとします。
Unix FAQエントリ も参照のこと。
Shebang行が実行されるインタプリタを決定しないWindowsでも、Shebang行でそれらを指定することによってインタプリタにオプションを渡すことができます。一般的なShebangの行を1回限りのスクリプト(SOの質問に答えるときに書いたものなど)にしておくと便利なので、Windowsと ArchLinux の両方ですばやくテストできます。
envユーティリティ を使用すると、パス上でコマンドを呼び出すことができます。
最初の残りの引数は呼び出すプログラム名を指定します。環境変数
PATH
に従って検索されます。残りの引数はすべてそのプログラムへの引数として渡されます。
他の答えを少し拡張して、これは/usr/bin/env
Shebang行の不用意な使用によってあなたのコマンドラインスクリプトがどのように問題を起こすことができるかの小さな例です:
$ /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つの方法は、ほとんどのPythonsに通常インストールされているバージョン付きの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")
Pythonスクリプトを実行するには、シェルに3つのことを伝える必要があります。
Shebangの#!
は(1)を達成しました。 #
文字は多くのスクリプト言語のコメントマーカーであるため、Shebangは#
で始まります。したがって、Shebang行の内容はインタプリタによって自動的に無視されます。
env
コマンドは(2.)と(3.)を実行します。 「重厚さ」を引用すると
env
コマンドの一般的な用途は、envが起動するように指示されたコマンドを$ PATHで検索するという事実を利用して、インタプリタを起動することです。 Shebang行では絶対パスを指定する必要があり、またさまざまなインタプリタ(Perl、bash、python)の場所は大きく異なる可能性があるため、使用するのが一般的です。/ bin/Perl、/ usr/bin/Perl、/ usr/local/bin/Perl、/ usr/local/pkg/Perl、/ fileserver/usr/bin/Perl、または/のいずれであるかを推測する代わりに
#!/usr/bin/env Perl
ユーザーのシステム上のhome/MrDaniel/usr/bin/Perl ...一方、envはほとんどの場合/ usr/bin/envにあります。 (そうでない場合を除いて;いくつかのシステムは/ bin/envを使用するかもしれませんが、それはかなりまれな機会であり、Linux以外のシステムでのみ起こります。)
おそらくあなたの質問はこの意味です。
あなたが使いたいのなら:$python myscript.py
その行はまったく必要ありません。システムがpythonを呼び出してからpythonインタプリタがスクリプトを実行します。
しかし、あなたが使用するつもりなら:$./myscript.py
通常のプログラムやbashスクリプトのように直接呼び出すと、そのプログラムを実行するために使用するプログラムをシステムに指定するためにその行を書く必要があります(そしてchmod 755
で実行可能にします)。
技術的には、Pythonでは、これは単なるコメント行です。
この行は、pyスクリプトシェルから(コマンド行から)を実行した場合にのみ使用されます。これは "Shebang!"として知られています。 、そしてPythonスクリプトだけでなく、さまざまな状況で使用されます。
ここでは、シェルにPythonの特定のバージョンを起動するように指示します(ファイルの残りの部分を処理するため)。
これを行うための主な理由は、オペレーティング・システム環境全体スクリプトの移植をすることです。
Mingwの下例えば、Pythonスクリプトを使用します。
#!/c/python3k/python
そして、GNU/Linuxディストリビューションの下で、それはどちらかであります:
#!/usr/local/bin/python
または
#!/usr/bin/python
そして全て(OS/X)の最高の商用UNIXのSW/HWシステムの下で、それは次のようになります。
#!/Applications/MacPython 2.5/python
またはFreeBSD上で:
#!/usr/local/bin/python
しかし、すべてのこれらの違いは、使用してすべてにわたってスクリプトの移植を行うことができます。
#!/usr/bin/env python
Linuxカーネルのexec
システムコールはシェバン(#!
)をネイティブに理解します
あなたがbashをするとき:
./something
linuxでは、これはパス./something
でexec
システムコールを呼び出します。
カーネルのこの行はexec
に渡されたファイルで呼ばれます: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if((bprm-> buf [0]!= '#')||(bprm-> buf [1]!= '!'))
これはファイルの最初のバイトを読み込み、それらを#!
と比較します。
そうであれば、その行の残りの部分はLinuxカーネルによって解析され、最初の引数としてパス/usr/bin/env python
と現在のファイルを使用して別のexec呼び出しが行われます。
/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
システムコールは異なるハンドラを使用します。もう1つの最も重要な組み込みハンドラはELF実行可能ファイル用です。 https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 これはバイト7f 45 4c 46
をチェックします。 .ELF
のために人間が読めることもあります。これはELFファイルを読み、それを正しくメモリに入れ、そしてそれで新しいプロセスを開始します。以下も参照してください。 カーネルはLinuxで実行されている実行可能バイナリファイルをどのように取得しますか。
最後に、binfmt_misc
メカニズムを使ってあなた自身のShebangハンドラを追加することができます。たとえば、.jar
ファイルに カスタムハンドラを追加できます 。このメカニズムはファイル拡張子でハンドラをサポートします。別のアプリケーションは 透過的に異なるアーキテクチャの実行ファイルをQEMUで走らせることです 。
_ posix _ はshebangsを指定しているとは思わない: https://unix.stackexchange.com/a/346214/32558 、根拠のある節や形式では言及されているが "実行可能スクリプトがシステムでサポートされている場合は、何らかの問題が発生する可能性があります。 " macOSとFreeBSDもそれを実装しているようです。
PATH
検索動機
おそらく、shebangsが存在する大きな動機の1つは、Linuxでは、次のようにPATH
からコマンドを実行したいということです。
basename-of-command
の代わりに:
/full/path/to/basename-of-command
しかし、それでは、Shebangメカニズムがないと、Linuxはどのようにして各タイプのファイルを起動するのかを知ることができるでしょうか。
コマンドで拡張子をハードコーディングする:
basename-of-command.py
またはすべてのインタプリタにPATH検索を実装する:
python basename-of-command
可能性はあるでしょう、しかしこれは私達が今までにコマンドを別の言語にリファクタリングすることにした場合すべてが壊れるという大きな問題を抱えています。
Shebangsはこの問題を美しく解決します。
最も逃したことの1つを強調するのはおそらく理にかなっています、それは即時の理解を妨げるかもしれません。端末にpython
と入力すると、通常はフルパスを指定しません。代わりに、実行ファイルはPATH
環境変数で検索されます。逆に、Pythonプログラム/path/to/app.py
を直接実行したいときは、どのインタプリタを使うべきかをシェルに伝えなければなりません(hashbangを通して、他の貢献者は上で説明しています)。
Hashbangはインタプリタへのフルパス を期待します。したがって、Pythonプログラムを直接実行するには、特にvirtualenvの使用を考慮すると、大きく異なるPythonバイナリへのフルパスを指定する必要があります。移植性に対処するために、/usr/bin/env
のトリックが使用されています。後者はもともと環境をその場で変更し、その中でコマンドを実行することを目的としています。変更がない場合は、現在の環境でコマンドを実行します。これにより、効果的に同じPATH
ルックアップが実行されます。
これは推奨される方法です。ドキュメントで提案されています。
2.2.2。実行可能なPythonスクリプト
BSD系のUnixシステムでは、シェルスクリプトのようにPythonスクリプトを直接実行可能にすることができます。
#! /usr/bin/env python3.2
http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts から
これは、どのプログラムがスクリプトを実行できるかをシェルに指示するシェル規約です。
#!/ usr/bin/env python
pythonバイナリへのパスに解決されます。
あなたはvirtualenvを使ってこの問題を試すことができます
これがtest.pyです。
#! /usr/bin/env python
import sys
print(sys.version)
仮想環境を作成する
virtualenv test2.6 -p /usr/bin/python2.6
virtualenv test2.7 -p /usr/bin/python2.7
各環境をアクティブにしてから違いを確認する
echo $PATH
./test.py
その行がなくてもファイルは同じように動作するようです。
もしそうなら、おそらくあなたはWindows上でPythonプログラムを実行している? Windowsはその行を使用しません - 代わりに、ファイル拡張子に関連付けられたプログラムを実行するためにファイル名拡張子を使用します。
しかし 2011年に、 "Pythonランチャー" が開発されました。これは(ある程度)WindowsでのLinuxの動作を模倣しています。これは、どのPythonインタプリタを実行するかを選択することだけに限定されます。両方がインストールされているシステムでPython 2とPython 3のどちらかを選択します。ランチャーはオプションでPythonのインストールによってpy.exe
としてインストールされ、ランチャーがその行をチェックして指定されたPythonインタプリタバージョンを起動するように.py
ファイルに関連付けることができます。
これは、「実際の」答えよりも多くの履歴情報として意味されます。
当時、デザイナーはすべてのものを置く場所について独自の概念を持っていて、時にはPython、Perl、Bash、または他の多くのGNU /オープンソースのものat all。
これは、さまざまなLinuxディストリビューションにも当てはまりました。 Linuxでは、-FHS [1]より前に、/ usr/bin /または/ usr/local/bin /にpythonが含まれている場合があります。または、インストールされていない可能性があるため、独自にビルドして〜/ binに配置します
Solarisは、バークレーUnixからSystem Vへの移行の一部として、私が今まで取り組んだ中で最悪でした。一部のreally長いパスの場合。 Sunfreeware.comの各パッケージを独自のディレクトリにインストールしたことを思い出しましたが、バイナリが/ usr/binにシンボリックリンクされたかどうかは思い出せません。
ああ、時には/ usr/binがNFSサーバーにありました[2]。
そのため、env
ユーティリティはこれを回避するために開発されました。
次に、#!/bin/env interpreter
を記述し、パスが適切である限り、合理的な実行の機会がありました。もちろん、reasonableは(PythonおよびPerlの場合)適切な環境変数も設定したことを意味します。 bash/ksh/zshの場合、うまくいきました。
人々がシェルスクリプト(Perlやpythonなど)を渡していたため、これは重要でした。RedHat Linuxワークステーションで/ usr/bin/pythonをハードコーディングすると、SGIで問題が発生します。 、IRIXはpythonを正しい場所に置いたと思います。しかし、Sparcステーションではまったく実行されない場合があります。
Sparcステーションが恋しいです。しかし、多くはありません。さて、E-Bayでトローリングしました。バステージ。
[1]ファイルシステム階層標準。 https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2]はい、そして時々人々はまだそのようなことをします。いや、カブORのどちらかをベルトにつけていませんでした。
どのインタプリタを使いたいのかを指定するだけです。これを理解するには、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はprint演算子をサポートしていないためです。
それでは先に進み、コードの最初の行を次のように変更してください。
#!/usr/bin/env python2
python2はprint演算子をサポートしているので、test
をstdoutに出力してもうまくいきます。スクリプトインタプリタを切り替える方法を学びました。
スクリプトを仮想環境で実行している場合、たとえばvenv
、venv
を操作しながらwhich python
を実行すると、Pythonインタプリタへのパスが表示されます。
~/Envs/venv/bin/python
仮想環境の 名はPythonインタプリタへのパスに が埋め込まれていることに注意してください。したがって、スクリプト内でこのパスをハードコーディングすると、2つの問題が発生します。
したがって、 Jonathan の答えに付け加えると、理想的なShebangは#!/usr/bin/env python
です。OS間の移植性だけでなく、仮想環境間の移植性のためにも!
python2
とpython3
の間の移植性の問題を考慮すると、あなたのプログラムが両方と互換性がある場合を除き、常にどちらかのバージョンを指定するべきです。
一部のディストリビューションはしばらくの間python3
にシンボリックリンクされたpython
を出荷しています - python
がpython2
であることに頼らないでください。
これは PEP 394 によって強調されています。
プラットフォーム間の違いを許容するために、Pythonインタプリタを呼び出す必要があるすべての新しいコードは、pythonを指定するべきではなく、むしろpython2またはpython3(またはより具体的なpython2.xおよびpython3.xバージョン; 移行を参照)を指定するべきです。ノート )。この区別は、シェルスクリプトから呼び出すとき、system()呼び出しを介して呼び出すとき、または他のコンテキストで呼び出すときに行う必要があります。
それはあなたがpythonの複数のバージョンを持っているときにどのバージョンのpythonを使ってプログラムを実行するかをインタプリタに伝えます。