问题描述
非常简单的问题:在Linux中,为什么Python需要该行
#!/usr/bin/python
在python文件的开头,因为Windows没有?
它有什么作用? ‘因为描述“链接到Python”有点模糊……
最佳解决方案
Python对Linux没有任何这样的特殊要求。它是Unix /Linux上的程序加载器,它使用”shebang”行,就像它所调用的那样。这实际上是一个功能而不是限制,但我们马上就会做到这一点。 The Wiki page on “shebang” has more details,但我会尝试在这里给出一个概述以及与Windows的比较。
首先,让我们看看Windows上的情况:
-
当您尝试打开或运行文件时,Windows首先检查该文件的扩展名。这是以
.
开头的文件名的最后一部分。对于Python文件,这通常是.py
。 -
Windows根据文件扩展名查找要执行的操作。
-
此信息记录在Windows注册表中;安装Python时,它通常告诉Windows应该使用newly-installed应用程序Python(即Python解释器)打开
.py
文件。 -
几种file-types具有内置行为;例如,可执行文件(例如Python解释器本身)必须以
.exe
结尾,而.bat
文件则作为Windows batch-scripts执行。 -
对特定file-type采取的措施是可定制的。例如,您可以告诉Windows使用
python.exe
而不是运行.py
文件,它应该使用其他程序打开它们,例如文本编辑器notepad.exe
。-
在这种情况下,为了运行Python脚本,您需要手动调用
python <scriptname>.py
(或编写.bat
文件来为您执行此操作)。
-
-
现在,如果在Python脚本的顶部有一个shebang行(#!/usr/bin/python
或#!/usr/bin/env python
)会发生什么?好吧,既然#
是Python中的注释行,那么Python解释器就会忽略它。这就是Unix /Linux世界中使用的大多数脚本语言使用#
来启动注释行的原因之一。
所以说Windows“不需要”#!
线有点误导; Windows没有看到#!
行,实际上依赖于file-extension来告诉它该怎么做。这有几个缺点:
-
您必须在最后使用
.py
命名Python脚本,以便自动识别它们。 -
没有简单的方法可以区分Python2脚本和Python3脚本。
-
如前所述,如果更改
.py
file-type的默认启动行为,Windows将不再使用Python自动运行这些脚本。请注意,这可能是无意中完成的。
现在,我们来看看Unix /Linux如何启动脚本:
首先要注意的是,与Windows不同,Unix /Linux并没有尝试使用特定程序来编写”open” Python脚本,至少在概念上是这样;操作系统知道脚本是可以执行的,因为有一些叫做”execute bit”的东西(超出了这个答案的范围)。因此,如果您不小心键入#!/usr/bin/pthon
而不是#!/usr/bin/python
,您将收到包含此文本的错误消息:
/usr/bin/pthon: bad interpreter: No such file or directory.
单词”interpreter”为我们提供了关于shebang行的作用的线索(虽然从技术上讲,指定的程序可以是解释器之外的其他东西,例如cat
或文本编辑器)。当您尝试执行文件时,会发生以下情况:
-
Unix /Linux程序加载器查看该文件的前两个字节;如果这两个字节是
#!
,则加载器将shebang行的其余部分(不包括shebang本身)解释为启动解释器的命令,使用该解释器将文件内容作为脚本运行。 -
程序加载器启动指定的解释器,将其作为参数提供给原始文件的路径。
这有几个好处:
-
script-writer可以更好地控制将使用哪个解释器(这解决了Python2 /Python3问题),并且有时可以向解释器传递额外的参数(有关详细信息,请参阅Wiki页面)。
-
脚本的文件名被忽略,因此您可以根据需要命名Python脚本。
最后,请注意,为了运行Python脚本,Unix /Linux不需要shebang行。回想一下,所有shebang行实际上都允许程序加载器选择一个解释器。但就像在Windows中一样,这可以手动完成:
python <myscript>
次佳解决方案
您指示的行用于告诉计算机直接运行文件/脚本时要使用的程序/解释器,以及脚本运行时应传递给该程序的任何参数。但是,这不是Python的要求,如果您打算直接运行脚本(而不是通过以下语法将其传递给Python),则需要Linux内核/系统。
如果要执行python script.py
或类似操作,则不需要它。只有在您打算直接运行脚本/文件时才需要它,而不需要提供解释器(例如python
)。
对于Bash脚本,它会有这样的东西:
#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;
这将向系统指示,当它运行时,它应该通过/bin/bash
运行,这是系统上的shell /shell-script语言之一。
但是对于Python代码,在这里,您将希望通过Python运行可执行文件,因此您可以告诉它您打算在其中运行哪些解释器。
#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()
这与Bash一样,表示应该使用/usr/bin/python
(这可能是Python 2或Python 3,具体取决于您的各个系统配置)。
这样,您可以直接运行./filename.py
或./executable
或./scripttorun
。
在开头没有该行,并假设您已将文件/脚本设置为可执行,并假设您正在使用Python脚本,如果您没有#!/usr/bin/python
行,则必须运行python filename.py
或类似行。 (对于Bash脚本,您必须执行bash script.sh
,或类似其他脚本/语言,如Perl,Ruby等)
上面的语法突出显示是每个部分中的language-specific,尽管它并不重要。
第三种解决方案
这条线:
#!/usr/bin/python
称为’shebang’,它指示解释器二进制文件的路径,该路径将用于解释文件中的其余命令。它通常是脚本的第一行。
因此,行#!/usr/bin/python
表示文件的内容将由位于/usr/bin/python
的python
二进制文件解释。
请注意,shebang行由内核解析,然后脚本最终将作为参数调用:
python script_name
同样在#!/bin/bash
的情况下:
bash script_name
第四种方案
从技术上讲,它不需要它。它需要一个指向脚本执行环境的路径。你的未来脚本最好包含/usr /bin /env然后指定python。无论python安装在何处,您都可以在python环境中运行脚本。出于兼容性原因,您希望这样做,您不能确定与您共享代码的下一个人将在usr /bin /python中安装python,或者他们将拥有这些系统文件的权限。
Here is a similar Q&A from stack overflow。
你的脚本中的样子是:
#!/usr/bin/env python
我也看到了如何指定python3的一些问题。这是怎么做的:
#!/usr/bin/env python3
第五种方案
在Linux中,Python可能需要也可能不需要#!
(shebang)行。这取决于如何处理Python代码,无论是在Python交互模式下运行代码还是在Python脚本中运行代码。
Python交互模式允许用户直接键入和运行Python代码,这不需要shebang行。要运行交互模式,请打开终端并为Python 2.X键入python
或为Python 3.X键入python3
。
$ python
Python 2.7.6 (default, Jun 22 2015, 18:00:18)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
$ python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Python脚本允许用户在纯文本文件中编写和保存Python代码,然后再运行代码。这可能需要也可能不需要shebang线。但是,在Linux中使用Python脚本需要shebang行时有两个已知的原因。
-
在可执行脚本中运行Python代码,即定义代码应该如何运行以及使用什么解释器;
-
根据特定版本的Python运行Python代码,即仅运行与Python 2.X或Python 3.X兼容的代码
用Python脚本练习
下面是文件的列表和内容,我用它来显示需要或不需要#!
(shebang)行的情况。
$ ls -ln *.py
-rw-rw-r-- 1 1000 1000 94 Dec 14 18:37 hello1.py
-rwxrwxr-x 1 1000 1000 116 Dec 14 18:37 hello2e.py
-rw-rw-r-- 1 1000 1000 116 Dec 14 18:37 hello2.py
-rwxrwxr-x 1 1000 1000 117 Dec 14 18:37 hello3e.py
-rwxrwxr-x 1 1000 1000 120 Dec 14 18:37 hello3m.py
-rw-rw-r-- 1 1000 1000 117 Dec 14 18:37 hello3.py
$ file *.py
hello1.py: ASCII text
hello2e.py: Python script, ASCII text executable
hello2.py: Python script, ASCII text executable
hello3e.py: Python script, ASCII text executable
hello3m.py: Python script, UTF-8 Unicode (with BOM) text executable
hello3.py: Python script, ASCII text executable
-
hello1.py
仅包含源代码。import sys sys.stdout.write("Hello from Python %s\n" % (sys.version,)) print("Hello, World!")
-
hello2.py
包含源代码和shebang行。#!/usr/bin/env python import sys sys.stdout.write("Hello from Python %s\n" % (sys.version,)) print("Hello, World!")
-
hello2e.py
包含与hello2.py
相同的并且可执行。 -
hello3.py
包含与hello2.py
相同的内容,但它适用于通过将第一行重命名为#!/usr/bin/env python3
来运行Python 3。 -
hello3e.py
包含与hello3.py
相同的并且可执行。 -
hello3m.py
包含与hello3.py
相同并且可执行,除了在文本编辑器(即Mousepad)中使用Write Unicode BOM
选项保存。
除此之外,还将向用户提供两种运行Python脚本的方法。两种方法都已经证明如下。
方法1:使用Python程序运行
下面是使用Python 2和Python 3运行源代码时的命令和输出。
$ python hello1.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18)
[GCC 4.8.2]
Hello, World!
$ python3 hello1.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09)
[GCC 4.8.4]
Hello, World!
两个版本的Python都能够成功运行脚本。因此,通过python
或python3
命令运行Python脚本时,不需要shebang行。
方法2:以Python脚本运行
下面是使用shebang行运行源代码时的命令和输出,它们既不适用于Python 2,也适用于Python 3,包括non-executable和可执行案例。
$ ./hello1.py
bash: ./hello1.py: Permission denied
$ ./hello2.py
bash: ./hello2.py: Permission denied
$ ./hello3.py
bash: ./hello3.py: Permission denied
$ ./hello2e.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18)
[GCC 4.8.2]
Hello, World!
$ ./hello3e.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09)
[GCC 4.8.4]
Hello, World!
前三个脚本失败,因为这些脚本是non-executable,无论是否有shebang行(有关支持证明,请参阅下面的附加示例)。最后两个脚本有shebang行并且是可执行的。
显然,如果没有shebang系列,已经可执行的脚本基本上是无用的。因此,shebang行是必需的,并且在可执行脚本中运行Python代码时脚本必须是可执行的。
当shebang不起作用
在我准备和测试的示例中,将hello3m.py
作为可执行脚本运行失败并返回错误。
$ ./hello3m.py
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory
这是一个已知的限制,即shebang不起作用或变得无效。当文件保存为Unicode BOM(字节顺序标记)时,它将无法作为可执行的Python脚本正常运行。
附加示例
此附加示例仅应视为支持证据。用户应该避免运行此示例,尽管结果是无害的。
我创建了另一个名为hello1e.py
的文件,其中包含与hello1.py
相同的文件并使其成为可执行文件。运行此脚本会返回语法错误。
$ ./hello1e.py
./hello1e.py: line 2: syntax error near unexpected token `"Hello from Python %s\n"'
./hello1e.py: line 2: `sys.stdout.write("Hello from Python %s\n" % (sys.version,))'
运行此脚本时,首先,鼠标光标将更改为plus-sign并且在外观上不执行任何操作。在我点击桌面或终端窗口之前,不会显示语法错误。然后,此脚本将在与脚本相同的目录中创建sys
文件。
$ file sys
sys: PostScript document text conforming DSC level 3.0, Level 1
sys
文件已被标识为PostScript文件,没有文件扩展名。此文件可以在文档查看器中打开,即Evince,文件实际上包含我之前单击过的窗口的屏幕截图。根据我的经验,该文件可以大到几兆字节。
再次,shebang行是必需的,并且在将Python脚本作为可执行脚本运行时,脚本必须是可执行的。否则,脚本将如上所述行为不当。
补充说明
术语”made executable”或“必须可执行”是指运行脚本的权限。这可以通过在终端中运行chmod +x FILENAME
命令,或通过在文件管理器中选中“允许此文件作为程序运行”或“属性”窗口中的类似内容来完成。
虽然其他现有答案几乎涵盖了所有内容,但这个答案采用了不同的方法,通过使用实际例子来解释这个问题。代码语法已经小心编写,因此示例可以使用Python 2或Python 3运行。
Python代码改编自Using Python on Windows和Using Python on Unix platforms,以及无处不在的“Hello,World!”的附加one-line代码。程序。
所有代码和命令都经过了全面测试,可以在Xubuntu 14.04系统中运行,默认安装了Python 2.7和Python 3.4。
第六种方案
这意味着当执行该文件时,您的计算机知道使用程序/usr/bin/python
执行它,这就是您如何区别于另一种语言,例如bash,您将执行#!/bin/bash
。这样你就可以简单地运行:
./[file-to-execute]
并且它将知道要执行它的文件,而不是你自己必须指定类似的东西:
python ./[file-to-execute].py
#!
部分通常被称为shebang或crunch bang。