人们为什么在Python脚本的第一行上编写#!/ usr / bin / env python shebang?

问题:人们为什么在Python脚本的第一行上编写#!/ usr / bin / env python shebang?

在我看来,如果没有该行,文件运行相同。

It seems to me like the files run the same without that line.


回答 0

如果您安装了多个版本的Python,请/usr/bin/env确保使用的解释器是您环境中的第一个解释器$PATH。另一种方法是对类似的东西进行硬编码#!/usr/bin/python;可以,但是不太灵活。

在Unix中,要解释的可执行文件可以通过#!在第一行的开头加上,然后是解释器(及其可能需要的任何标志)来指示要使用的解释器。

当然,如果您在谈论其他平台,则此规则不适用(但“ shebang行”没有害处,并且如果您将该脚本复制到具有 Unix基础的平台(例如Linux,Mac),将有帮助等)。

If you have several versions of Python installed, /usr/bin/env will ensure the interpreter used is the first one on your environment’s $PATH. The alternative would be to hardcode something like #!/usr/bin/python; that’s ok, but less flexible.

In Unix, an executable file that’s meant to be interpreted can indicate what interpreter to use by having a #! at the start of the first line, followed by the interpreter (and any flags it may need).

If you’re talking about other platforms, of course, this rule does not apply (but that “shebang line” does no harm, and will help if you ever copy that script to a platform with a Unix base, such as Linux, Mac, etc).


回答 1

那就是shebang线。如Wikipedia条目所述

在计算中,shebang(也称为“ hashbang”,“ hashhpling”,“ bang bang”或“ crunchbang”)是指字符“#!”。当它们是解释器指令中的前两个字符作为文本文件的第一行时。在类似Unix的操作系统中,程序加载器将这两个字符的存在指示为文件是脚本,并尝试使用文件中第一行其余部分指定的解释器执行该脚本。

另请参见Unix FAQ条目

即使在Windows上,shebang行不能确定要运行的解释程序,也可以通过在shebang行上指定选项来将选项传递给解释程序。我发现在一次性脚本中保留通用的shebang行很有用(例如我在回答SO问题时编写的脚本),因此我可以在Windows和ArchLinux上快速对其进行测试。

使用env实用程序可以在路径上调用命令:

剩下的第一个参数指定要调用的程序名称;根据PATH环境变量进行搜索。任何剩余的参数将作为参数传递给该程序。

That is called the shebang line. As the Wikipedia entry explains:

In computing, a shebang (also called a hashbang, hashpling, pound bang, or crunchbang) refers to the characters “#!” when they are the first two characters in an interpreter directive as the first line of a text file. In a Unix-like operating system, the program loader takes the presence of these two characters as an indication that the file is a script, and tries to execute that script using the interpreter specified by the rest of the first line in the file.

See also the Unix FAQ entry.

Even on Windows, where the shebang line does not determine the interpreter to be run, you can pass options to the interpreter by specifying them on the shebang line. I find it useful to keep a generic shebang line in one-off scripts (such as the ones I write when answering questions on SO), so I can quickly test them on both Windows and ArchLinux.

The env utility allows you to invoke a command on the path:

The first remaining argument specifies the program name to invoke; it is searched for according to the PATH environment variable. Any remaining arguments are passed as arguments to that program.


回答 2

进一步扩展其他答案,这是一个小示例,说明了如何谨慎使用/usr/bin/envshebang行会导致命令行脚本出现问题:

$ /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中不存在。

防止此类问题的一种方法是使用大多数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")

Expanding a bit on the other answers, here’s a little example of how your command line scripts can get into trouble by incautious use of /usr/bin/env shebang lines:

$ /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

The json module doesn’t exist in Python 2.5.

One way to guard against that kind of problem is to use the versioned python command names that are typically installed with most Pythons:

$ cat my_script.py 
#!/usr/bin/env python2.6
import json
print "hello, json"

If you just need to distinguish between Python 2.x and Python 3.x, recent releases of Python 3 also provide a python3 name:

$ cat my_script.py 
#!/usr/bin/env python3
import json
print("hello, json")

回答 3

为了运行python脚本,我们需要告诉shell三件事:

  1. 该文件是一个脚本
  2. 我们要执行哪个解释器的脚本
  3. 口译员的路径

射手#!完成(1.)。shebang以a开头,#因为该#字符在许多脚本语言中都是注释标记。因此,解释器会自动忽略shebang行的内容。

env命令完成(2.)和(3.)。引用“草率”

env命令的常见用法是通过利用env将在$ PATH中搜索被告知要启动的命令的事实来启动解释器。由于shebang行需要指定绝对路径,并且由于各种解释器(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系统上发生。)

In order to run the python script, we need to tell the shell three things:

  1. That the file is a script
  2. Which interpreter we want to execute the script
  3. The path of said interpreter

The shebang #! accomplishes (1.). The shebang begins with a # because the # character is a comment marker in many scripting languages. The contents of the shebang line are therefore automatically ignored by the interpreter.

The env command accomplishes (2.) and (3.). To quote “grawity,”

A common use of the env command is to launch interpreters, by making use of the fact that env will search $PATH for the command it is told to launch. Since the shebang line requires an absolute path to be specified, and since the location of various interpreters (perl, bash, python) may vary a lot, it is common to use:

#!/usr/bin/env perl  instead of trying to guess whether it is /bin/perl, /usr/bin/perl, /usr/local/bin/perl, /usr/local/pkg/perl, /fileserver/usr/bin/perl, or /home/MrDaniel/usr/bin/perl on the user’s system…

On the other hand, env is almost always in /usr/bin/env. (Except in cases when it isn’t; some systems might use /bin/env, but that’s a fairly rare occassion and only happens on non-Linux systems.)


回答 4

也许您的问题是这样的:

如果要使用: $python myscript.py

您根本不需要那条线。系统将调用python,然后python解释器将运行您的脚本。

但是,如果您打算使用: $./myscript.py

像普通程序或bash脚本一样直接调用它,您需要编写该行以向系统指定运行该程序的程序(并使其通过可执行chmod 755

Perhaps your question is in this sense:

If you want to use: $python myscript.py

You don’t need that line at all. The system will call python and then python interpreter will run your script.

But if you intend to use: $./myscript.py

Calling it directly like a normal program or bash script, you need write that line to specify to the system which program use to run it, (and also make it executable with chmod 755)


回答 5

execLinux内核的系统调用#!本身了解shebangs()

当您进行bash操作时:

./something

在Linux上,这会exec使用path 调用系统调用./something

内核的这一行在传递给exec以下文件的文件上调用:https : //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)。让我们通过读取的4个前字节来确认/bin/ls,这是ELF可执行文件:

head -c 4 "$(which ls)" | hd 

输出:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

因此,当内核看到这些字节时,它将获取ELF文件,将其正确地放入内存,并使用它开始一个新进程。另请参阅:内核如何获取在Linux下运行的可执行二进制文件?

最后,您可以使用该binfmt_misc机制添加自己的shebang处理程序。例如,您可以.jarfiles添加自定义处理程序。该机制甚至通过文件扩展名支持处理程序。另一个应用程序是使用QEMU透明地运行不同体系结构的可执行文件

我不认为POSIX指定了shebangs:https ://unix.stackexchange.com/a/346214/32558 ,尽管它在基本原理部分中确实提到了,并且形式为“如果系统支持可执行脚本,则可能发生”。macOS和FreeBSD似乎也实现了它。

PATH 搜索动机

可能存在shebang的一个主要动机是,在Linux中,我们经常希望从以下命令运行命令PATH

basename-of-command

代替:

/full/path/to/basename-of-command

但是,如果没有shebang机制,Linux如何知道如何启动每种类型的文件?

在命令中对扩展进行硬编码:

 basename-of-command.py

或在每个解释器上实施PATH搜索:

python basename-of-command

这样做是有可能的,但这是一个主要问题,如果我们决定将命令重构为另一种语言,那么一切都会中断。

Shebangs很好地解决了这个问题。

The exec system call of the Linux kernel understands shebangs (#!) natively

When you do on bash:

./something

on Linux, this calls the exec system call with the path ./something.

This line of the kernel gets called on the file passed to exec: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

It reads the very first bytes of the file, and compares them to #!.

If the comparison is true, then the rest of the line is parsed by the Linux kernel, which makes another exec call with path /usr/bin/env python and current file as the first argument:

/usr/bin/env python /path/to/script.py

and this works for any scripting language that uses # as a comment character.

And yes, you can make an infinite loop with:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash recognizes the error:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! just happens to be human readable, but that is not required.

If the file started with different bytes, then the exec system call would use a different handler. The other most important built-in handler is for ELF executable files: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 which checks for bytes 7f 45 4c 46 (which also happens to be human readable for .ELF). Let’s confirm that by reading the 4 first bytes of /bin/ls, which is an ELF executable:

head -c 4 "$(which ls)" | hd 

output:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

So when the kernel sees those bytes, it takes the ELF file, puts it into memory correctly, and starts a new process with it. See also: How does kernel get an executable binary file running under linux?

Finally, you can add your own shebang handlers with the binfmt_misc mechanism. For example, you can add a custom handler for .jar files. This mechanism even supports handlers by file extension. Another application is to transparently run executables of a different architecture with QEMU.

I don’t think POSIX specifies shebangs however: https://unix.stackexchange.com/a/346214/32558 , although it does mention in on rationale sections, and in the form “if executable scripts are supported by the system something may happen”. macOS and FreeBSD also seem to implement it however.

PATH search motivation

Likely, one big motivation for the existence of shebangs is the fact that in Linux, we often want to run commands from PATH just as:

basename-of-command

instead of:

/full/path/to/basename-of-command

But then, without the shebang mechanism, how would Linux know how to launch each type of file?

Hardcoding the extension in commands:

 basename-of-command.py

or implementing PATH search on every interpreter:

python basename-of-command

would be a possibility, but this has the major problem that everything breaks if we ever decide to refactor the command into another language.

Shebangs solve this problem beautifully.


回答 6

从技术上讲,在Python中,这只是一条注释行。

仅当您从外壳程序(从命令行)运行py脚本时才使用此行。这就是众所周知的射帮!” ,它可用于各种情况,而不仅限于Python脚本。

在这里,它指示shell启动特定版本的Python(以照顾文件的其余部分。

Technically, in Python, this is just a comment line.

This line is only used if you run the py script from the shell (from the command line). This is know as the Shebang!”, and it is used in various situations, not just with Python scripts.

Here, it instructs the shell to start a specific version of Python (to take care of the rest of the file.


回答 7

这样做的主要原因是使脚本可跨操作系统环境移植。

例如在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

The main reason to do this is to make the script portable across operating system environments.

For example under mingw, python scripts use :

#!/c/python3k/python 

and under GNU/Linux distribution it is either:

#!/usr/local/bin/python 

or

#!/usr/bin/python

and under the best commercial Unix sw/hw system of all (OS/X), it is:

#!/Applications/MacPython 2.5/python

or on FreeBSD:

#!/usr/local/bin/python

However all these differences can make the script portable across all by using:

#!/usr/bin/env python

回答 8

强调大多数人错过的一件事可能是有道理的,这可能会阻止立即理解。当您输入python终端时,通常不会提供完整路径。而是在PATH环境变量中向上查找可执行文件。反过来,当您想直接执行Python程序时/path/to/app.py,必须告诉Shell使用什么解释器(通过hashbang,上面其他贡献者在解释什么)。

Hashbang希望有完整的口译员。因此,要直接运行Python程序,您必须提供Python二进制文件的完整路径,该路径有很大差异,尤其是考虑到使用virtualenv时。为了解决可移植性,/usr/bin/env使用了技巧。后者最初旨在就地更改环境并在其中运行命令。如果未提供任何更改,它将在当前环境中运行该命令,从而有效地导致执行该操作的相同PATH查找。

来自unix stackexchange的来源

It probably makes sense to emphasize one thing that the most have missed, which may prevent immediate understanding. When you type python in terminal you don’t normally provide a full path. Instead, the executable is up looked in PATH environment variable. In turn, when you want to execute a Python program directly, /path/to/app.py, one must tell the shell what interpreter to use (via the hashbang, what the other contributors are explaining above).

Hashbang expects full path to an interpreter. Thus to run your Python program directly you have to provide full path to Python binary which varies significantly, especially considering a use of virtualenv. To address portability the trick with /usr/bin/env is used. The latter is originally intended to alter environment in-place and run a command in it. When no alteration is provided it runs the command in current environment, which effectively results in the same PATH lookup which does the trick.

Source from unix stackexchange


回答 9

这是一个Shell约定,它告诉Shell哪个程序可以执行脚本。

#!/ usr / bin / env python

解析为Python二进制文件的路径。

This is a shell convention that tells the shell which program can execute the script.

#!/usr/bin/env python

resolves to a path to the Python binary.


回答 10

建议的方法,在文档中提出:

2.2.2。可执行Python脚本

在BSD式的Unix系统上,可以将Python脚本像shell脚本一样直接执行,方法是:

#! /usr/bin/env python3.2

来自http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts

It’s recommended way, proposed in documentation:

2.2.2. Executable Python Scripts

On BSD’ish Unix systems, Python scripts can be made directly executable, like shell scripts, by putting the line

#! /usr/bin/env python3.2

from http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts


回答 11

您可以使用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

You can try this issue using virtualenv

Here is test.py

#! /usr/bin/env python
import sys
print(sys.version)

Create virtual environments

virtualenv test2.6 -p /usr/bin/python2.6
virtualenv test2.7 -p /usr/bin/python2.7

activate each environment then check the differences

echo $PATH
./test.py

回答 12

它只是指定您要使用的解释器。要理解这一点,可以通过在终端上创建一个文件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

并且可以正常工作,并打印test到stdout,因为python2支持print运算符。因此,现在您已经了解了如何在脚本解释器之间切换。

It just specifies what interpreter you want to use. To understand this, create a file through terminal by doing touch test.py, then type into that file the following:

#!/usr/bin/env python3
print "test"

and do chmod +x test.py to make your script executable. After this when you do ./test.py you should get an error saying:

  File "./test.py", line 2
    print "test"
               ^
SyntaxError: Missing parentheses in call to 'print'

because python3 doesn’t supprt the print operator.

Now go ahead and change the first line of your code to:

#!/usr/bin/env python2

and it’ll work, printing test to stdout, because python2 supports the print operator. So, now you’ve learned how to switch between script interpreters.


回答 13

在我看来,如果没有该行,文件运行相同。

如果是这样,那么也许您正在Windows上运行Python程序?Windows不使用该行,而是使用文件扩展名来运行与文件扩展名关联的程序。

但是在2011年,开发了“ Python启动器”,在某种程度上模仿了Windows的Linux行为。仅限于选择运行哪个Python解释器-例如,在同时安装了Python 2和Python 3的系统上进行选择。启动器可以选择py.exe通过Python安装进行安装,并且可以与.py文件关联,以便启动器将检查该行,然后启动指定的Python解释器版本。

It seems to me like the files run the same without that line.

If so, then perhaps you’re running the Python program on Windows? Windows doesn’t use that line—instead, it uses the file-name extension to run the program associated with the file extension.

However in 2011, a “Python launcher” was developed which (to some degree) mimics this Linux behaviour for Windows. This is limited just to choosing which Python interpreter is run — e.g. to select between Python 2 and Python 3 on a system where both are installed. The launcher is optionally installed as py.exe by Python installation, and can be associated with .py files so that the launcher will check that line and in turn launch the specified Python interpreter version.


回答 14

这意味着更多的历史信息,而不是“真实的”答案。

请记住,在过去,您有很多像操作系统一样的unix操作系统,其设计人员都对放置内容有自己的看法,有时甚至根本不包括Python,Perl,Bash或许多其他GNU /开源内容

甚至在不同的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来说,它才有效。

这很重要,因为人们正在传递shell脚本(例如perl和python),并且如果您在Red Hat Linux工作站上对/ usr / bin / python进行硬编码,那么在SGI上会很糟糕…嗯,不,我认为IRIX将python放在了正确的位置。但是在Sparc工作站上,它可能根本不运行。

我想念我的sparc站。但不是很多。好的,现在您已经让我在E-Bay上四处走动。卑鄙的人

[1]文件系统层次结构标准。https://zh.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

[2]是的,有时人们仍然会做类似的事情。不,我没有在皮带上戴萝卜或洋葱。

This is meant as more of historical information than a “real” answer.

Remember that back in the day you had LOTS of unix like operating systems whose designers all had their own notion of where to put stuff, and sometimes didn’t include Python, Perl, Bash, or lots of other GNU/Open Source stuff at all.

This was even true of different Linux distributions. On Linux–pre-FHS[1]-you might have python in /usr/bin/ or /usr/local/bin/. Or it might not have been installed, so you built your own and put it in ~/bin

Solaris was the worst I ever worked on, partially as the transition from Berkeley Unix to System V. You could wind up with stuff in /usr/, /usr/local/, /usr/ucb, /opt/ etc. This could make for some really long paths. I have memories of the stuff from Sunfreeware.com installing each package in it’s own directory, but I can’t recall if it symlinked the binaries into /usr/bin or not.

Oh, and sometimes /usr/bin was on an NFS server[2].

So the env utility was developed to work around this.

Then you could write #!/bin/env interpreter and as long as the path was proper things had a reasonable chance of running. Of course, reasonable meant (for Python and Perl) that you had also set the appropriate environmental variables. For bash/ksh/zsh it just worked.

This was important because people were passing around shell scripts (like perl and python) and if you’d hard coded /usr/bin/python on your Red Hat Linux workstation it was going to break bad on a SGI…well, no, I think IRIX put python in the right spot. But on a Sparc station it might not run at all.

I miss my sparc station. But not a lot. Ok, now you’ve got me trolling around on E-Bay. Bastages.

[1] File-system Hierarchy Standard. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

[2] Yes, and sometimes people still do stuff like that. And no, I did not wear either a turnip OR an onion on my belt.


回答 15

如果您是在虚拟环境中运行脚本,请说venv,然后在执行which python时执行venv将显示Python解释器的路径:

~/Envs/venv/bin/python

请注意,虚拟环境名称嵌入在Python解释器的路径中。因此,在脚本中对此路径进行硬编码将导致两个问题:

  • 如果将脚本上载到存储库,则将强制其他用户使用相同的虚拟环境名称。这是他们首先发现问题的方法。
  • 将无法运行在多个虚拟环境中的脚本,即使你有在其他虚拟环境中所有需要的软件包。

因此,要补充Jonathan的答案,理想的shebang是#!/usr/bin/env python,不仅是跨OS的可移植性,而且是跨虚拟环境的可移植性!

If you’re running your script in a virtual environment, say venv, then executing which python while working on venv will display the path to the Python interpreter:

~/Envs/venv/bin/python

Note that the name of the virtual environment is embedded in the path to the Python interpreter. Therefore, hardcoding this path in your script will cause two problems:

  • If you upload the script to a repository, you’re forcing other users to have the same virtual environment name. This is if they identify the problem first.
  • You won’t be able to run the script across multiple virtual environments even if you had all required packages in other virtual environments.

Therefore, to add to Jonathan‘s answer, the ideal shebang is #!/usr/bin/env python, not just for portability across OSes but for portability across virtual environments as well!


回答 16

考虑到python2和之间的可移植性问题python3,除非您的程序与两者兼容,否则应始终指定任何一个版本。

一些分布航运python符号链接到python3现在一段时间-不要依赖pythonpython2

PEP 394强调了这一点:

为了容忍平台之间的差异,所有需要调用Python解释器的新代码都不应指定python,而应指定python2或python3(或更具体的python2.x和python3.x版本;请参阅迁移说明) 。从shell脚本调用时,通过system()调用调用时或在任何其他上下文中调用时,都应在shebang中进行区分。

Considering the portability issues between python2 and python3, you should always specify either version unless your program is compatible with both.

Some distributions are shipping python symlinked to python3 for a while now – do not rely on python being python2.

This is emphasized by PEP 394:

In order to tolerate differences across platforms, all new code that needs to invoke the Python interpreter should not specify python, but rather should specify either python2 or python3 (or the more specific python2.x and python3.x versions; see the Migration Notes). This distinction should be made in shebangs, when invoking from a shell script, when invoking via the system() call, or when invoking in any other context.


回答 17

当您有多个python版本时,它会告诉解释器与哪个版本的python一起运行程序。

It tells the interpreter which version of python to run the program with when you have multiple versions of python.


回答 18

它允许您选择要使用的可执行文件。如果您可能安装了多个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())

It allows you to select the executable that you wish to use; which is very handy if perhaps you have multiple python installs, and different modules in each and wish to choose. e.g.

#!/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())

回答 19

这告诉脚本python目录在哪里!

#! /usr/bin/env python

this tells the script where is python directory !

#! /usr/bin/env python