为什么人们在Python脚本的第一行编写#!/ usr / bin / env python?
在我看来,这些文件运行相同,没有这一行。
 如果您安装了多个版本的Python,则/usr/bin/env将确保使用的解释器是您环境的$PATH的第一个。 替代方法是硬编码像#!/usr/bin/python ; 没关系,但不太灵活。 
 在Unix中,一个可解释的可执行文件可以通过#!来指示要使用的解释器#! 在第一行的开始,然后是解释器(以及它可能需要的任何标志)。 
如果你在谈论其他平台,当然,这个规则并不适用(但是“shebang line”并没有什么坏处,如果你把这个脚本复制到一个Unix基础的平台,比如Linux,Mac等等)。
这就是所谓的三帮线 。 正如维基百科条目所解释的 :
在计算中,一个shebang(也被称为hashbang,hashbound,pound bang或crunchbang)是指字符“#!” 当它们是解释器指令中的前两个字符作为文本文件的第一行时。 在一个类似Unix的操作系统中,程序加载器将这两个字符作为文件是脚本的指示,并尝试使用文件第一行其余部分指定的解释器执行该脚本。
请参阅Unix FAQ条目 。
即使在Windows中,shebang行不确定要运行的解释器,也可以通过在shebang行中指定它们,将选项传递给解释器。 我发现在一次性脚本中保留一个通用的shebang行非常有用(比如我在回答问题时写的那些脚本),所以我可以在Windows和ArchLinux上快速testing它们。
env实用程序允许您在path上调用一个命令:
剩下的第一个参数指定要调用的程序名称; 它是根据
PATH环境variables进行search的。 任何剩余的参数都作为parameter passing给该程序。
 在其他答案上稍微扩展一下,下面是一些小小的例子,说明你的命令行脚本如何不小心使用/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 
Python 2.5中不存在json模块。
防范这种问题的一种方法是使用通常与大多数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脚本,我们需要告诉shell三件事情:
- 该文件是一个脚本
- 我们要执行脚本的解释器
- 说解释者的path
  shebang #! 完成(1.)。  shebang以#开头,因为#字符是许多脚本语言中的注释标记。 因此,shebang行的内容会被解释器自动忽略。 
  env命令完成(2.)和(3.)。 引用“grawity” 
env命令的一个常见用途是启动解释器,通过使用env将search$ PATH的命令来启动它。 由于shebang行需要指定绝对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中,这只是一条注释行。
只有从shell (从命令行)运行py脚本才能使用此行。 这被称为“ Shebang !” ,它在各种情况下使用,而不仅仅是Python脚本。
在这里,它指示shell启动特定版本的Python(以处理文件的其余部分。
也许你的问题在这个意义上说:
 如果你想使用: $python myscript.py 
你根本不需要那条线。 系统会调用python,然后python解释器会运行你的脚本。
 但是如果你打算使用: $./myscript.py 
 直接调用它就像一个正常的程序或bash脚本,你需要编写该行来指定系统使用哪个程序来运行它(也可以使用chmod 755来执行它) 
这样做的主要原因是使脚本跨操作系统环境可移植。
例如在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 
 强调大部分错过的东西可能是有意义的,这可能会阻止立即理解。 在terminal中键入python ,通常不会提供完整的path。 而是在PATH环境variables中查找可执行文件。 反过来,当你想直接执行一个Python程序/path/to/app.py ,必须告诉shell使用什么解释器(通过hashbang ,其他贡献者正在上面解释)。 
  Hashbang期待完全的解释。 因此要直接运行你的Python程序,你必须提供Python二进制文件的完整path,这个path显着不同,特别是考虑到了virtualenv的使用。 为了解决可移植性,使用/usr/bin/env的技巧。 后者原本是为了在原地改变环境,并在其中运行一个命令。 当没有提供修改的时候,它会在当前环境中运行这个命令,这有效地导致了相同的PATH查找。 
来自unix stackexchange
这是build议的方式,在文档中提出:
2.2.2。 可执行的Python脚本
在BSD的Unix系统上,Python脚本可以直接执行,比如shell脚本
#! /usr/bin/env python3.2
来自http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
  Linux内核的exec系统调用本地理解shebang( #! ) 
当你在bash上做:
 ./something 
 在Linux上,这将调用具有完整path的exec系统调用。 
 内核的这一行被传递给exec的文件调用: https : //github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25 
if((bprm-> buf [0]!='#')||(bprm-> buf [1]!='!'))
 这读取文件的第一个字节,并将它们与#!进行比较  。 
 如果是这样的话,那么剩下的内核就会被Linux内核parsing,这个内核会再次调用path/usr/bin/env python和当前文件作为第一个参数: 
 /usr/bin/env python /path/to/script.py 
 这适用于任何使用#作为注释字符的脚本语言。 
是的,你可以做一个无限循环:
 #!/a 
 并在/a的可执行文件 
 #! 只是碰巧是人类可读的,但这不是必需的。 
 如果文件以不同的字节开始,那么exec系统调用将使用不同的处理程序。 另一个最重要的内置处理程序是用于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文件添加一个自定义处理程序: 运行JAR文件而不直接调用java这个机制甚至通过文件扩展来支持处理程序。 
我不认为POSIX指定shebangs: https ://unix.stackexchange.com/a/346214/32558
这是一个shell规范,它告诉shell哪个程序可以执行脚本。
#!/ usr / bin / env python
parsing为Python二进制文件的path。
你可以用virtualenv来试试这个问题
这里是test.py
 #! /usr/bin/env python import sys print(sys.version) 
创build虚拟环境
 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行为。 这仅限于select运行哪个Python解释器 – 例如,在安装了两者的系统上selectPython 2和Python 3。 启动程序可以通过Python安装作为py.exe来安装,并且可以与.py文件关联,以便启动程序将检查该行,并启动指定的Python解释器版本。 
 如果你正在虚拟环境中运行你的脚本,比如说venv ,那么在venv上venv which python时候会显示Python解释器的path: 
 ~/Envs/venv/bin/python 
请注意, 虚拟环境的名称embedded到Python解释器的path中。 因此,在脚本中对此path进行硬编码将导致两个问题:
- 如果将脚本上传到存储库,则会强制其他用户使用相同的虚拟环境名称 。 这是如果他们首先确定问题。
- 即使您在其他虚拟环境中拥有所有必需的软件包,您也无法在多个虚拟环境中运行该脚本 。
 因此,为了增加Jonathan的回答,理想的shebang是#!/usr/bin/env python ,不仅仅是为了跨操作系统的可移植性,而且也是为了跨虚拟环境的可移植性! 
 考虑到python2和python3之间的可移植性问题,你应该总是指定任何一个版本,除非你的程序兼容两者。 
 有些发行版现在已经将python符号链接到python3了 – 不要依赖python作为python2 。 
PEP 394强调了这一点:
为了容忍跨平台的差异,所有需要调用Python解释器的新代码都不应该指定python,而应该指定python2或者python3(或者更具体的python2.x和python3.x版本;请参阅Migration Notes ) 。 这种区别应该在shebangs中进行,当从shell脚本调用时,通过system()调用调用时,或者在任何其他上下文中调用时。
 它只是指定你想要使用的解释器。 要理解这一点,通过touch test.py通过terminal创build一个文件,然后在该文件中键入以下内容: 
 #!/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支持打印操作符。 所以,现在你已经学会了如何在脚本解释器之间切换。 
它告诉解释器,当你有多个版本的python时,运行该程序的Python版本。
这告诉脚本在哪里是python目录!
 #! /usr/bin/env python