一个非常简单的问题:在 Linux 中,为什么 Python 需要以下行
#!/usr/bin/python
在 python 文件的开头,因为 Windows 没有?
它有什么作用?因为“链接到 Python”的描述有点模糊......
答案1
PythonLinux 上没有任何这样的特殊要求。这是程序加载器在 Unix/Linux 上,它使用所谓的“shebang”行。这实际上是一个功能,而不是限制,但我们稍后会讲到。维基百科上关于“shebang”的页面有更多详细信息,但我会尝试在这里给出一个概述以及与 Windows 的比较。
首先我们看一下Windows上的情况:
- 当您尝试打开或运行文件时,Windows 首先检查扩大该文件。这是最后的文件名的一部分以 开头
.
对于 Python 文件来说,这通常是.py
。 - Windows 根据文件扩展名查找要采取的操作。
- 此信息记录在 Windows 注册表中;安装 Python 时,它通常会告诉 Windows
.py
应使用新安装的应用Python(即Python解释器)。 - 几种文件类型具有内置行为;例如,可执行文件(例如 Python 解释器本身)必须以 结尾
.exe
,并且.bat
文件作为 Windows 批处理脚本执行。 - 针对特定文件类型采取的操作是可定制。例如,您可以告诉 Windows 不要
.py
使用 运行文件python.exe
,而是使用其他程序(如文本编辑器)打开它们notepad.exe
。- 在这种情况下,为了跑步Python 脚本,你需要手动调用
python <scriptname>.py
(或者编写一个.bat
文件来为您执行此操作)。
- 在这种情况下,为了跑步Python 脚本,你需要手动调用
- 此信息记录在 Windows 注册表中;安装 Python 时,它通常会告诉 Windows
现在,如果Python 脚本顶部有一个 shebang 行(#!/usr/bin/python
或),会发生什么情况?好吧,因为 Python 中是注释行,所以 Python 解释器会忽略它。这就是为什么 Unix/Linux 世界中使用的大多数脚本语言都以注释行开头的原因之一。#!/usr/bin/env python
#
#
所以说 Windows“不需要”这一行有点误导#!
;Windows 不需要看该#!
行,实际上依赖文件扩展名来告诉它该做什么。这有几个缺点:
- 你必须在末尾命名 Python 脚本
.py
,以便自动识别它们。 - 没有简单的方法可以区分 Python2 脚本和 Python3 脚本。
- 如前所述,如果您更改
.py
文件类型的默认启动行为,Windows 将不再自动使用 Python 运行这些脚本。请注意,这可能是无意中完成的。
现在,让我们看看Unix/Linux如何启动脚本:
首先要注意的是,与 Windows 不同,Unix/Linux 不会尝试使用特定程序“打开”Python 脚本,至少在概念上是这样;操作系统知道脚本之所以能够执行,是因为存在所谓的“执行位”(这超出了本回答的范围)。因此,如果您不小心输入了#!/usr/bin/pthon
而不是#!/usr/bin/python
,您将收到一条包含以下文本的错误消息:
/usr/bin/pthon: bad interpreter: No such file or directory.
“解释器”这个词为我们提供了有关 shebang 行的作用的线索(尽管从技术上讲,指定的程序可以是解释器以外的其他程序,例如cat
文本编辑器)。当您尝试执行文件时,会发生以下情况:
- Unix/Linux 程序加载器会查看该文件的前两个字节;如果这两个字节是
#!
,则加载器会将 shebang 行的其余部分(不包括 shebang 本身)解释为启动解释器将文件内容作为脚本运行。 - 程序加载器启动指定的解释器,并向其提供小路原始文件作为参数。
这有几个优点:
- 脚本编写者可以更好地控制使用哪个解释器(这解决了 Python2/Python3 问题)并且有时可以向解释器传递额外的参数(有关详细信息,请参阅 Wiki 页面)。
- 脚本的文件名是被忽略,因此你可以随意命名 Python 脚本。
最后请注意,Unix/Linux 确实不是 需要运行 Python 脚本时,需要使用 shebang 行。回想一下,shebang 行实际上所做的就是允许程序加载器选择解释器。但就像在 Windows 中一样,这可以手动完成:
python <myscript>
答案2
您指出的行用于告诉计算机在直接运行文件/脚本时要使用哪个程序/解释器,以及在脚本运行时应传递给该程序的任何参数。但这并不是Python,如果您打算直接运行该脚本(而不是通过以下语法将其传递给 Python),这是 Linux 内核/系统的要求。
如果您要执行python script.py
或类似操作,则不需要它。仅当您打算直接运行脚本/文件而不提供要使用的解释器(例如python
)时才需要它。
对于 Bash 脚本来说,它会有类似这样的内容:
#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;
这将向系统指示,当它运行时,它应该通过/bin/bash
系统上的某个 shell / shell 脚本语言来运行。
但是,对于 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 脚本,则python filename.py
如果没有该#!/usr/bin/python
行,则必须运行或类似操作。(对于 Bash 脚本,您必须执行bash script.sh
,或对于其他脚本/语言(如 Perl、Ruby 等)执行类似操作。)
上面的语法突出显示在每个部分中都是特定于语言的,尽管这并不重要。
答案3
以下行:
#!/usr/bin/python
被称为“shebang”,它指示将用于解释文件中其余命令的解释器二进制文件的路径。它通常是脚本的第一行。
因此该行表示该文件的内容将由位于的二进制文件#!/usr/bin/python
解释。python
/usr/bin/python
请注意,shebang 行由内核解析,然后脚本最终将作为参数被调用:
python script_name
同样的情况#!/bin/bash
:
bash script_name
答案4
在 Linux 中,Python 可能需要也可能不需要#!
(shebang) 行。这取决于如何处理 Python 代码,是在 Python 交互模式下运行代码还是在 Python 脚本中运行代码。
Python 交互模式允许用户直接输入并运行 Python 代码,无需 shebang 行。要运行交互模式,请打开终端并输入python
Python 2.X 或python3
Python 3.X。
$ 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
,只是通过将第一行重命名为 来适应与 Python 3 一起运行#!/usr/bin/env python3
。hello3e.py
包含相同内容hello3.py
并可执行。hello3m.py
包含相同内容hello3.py
并可执行,但Write Unicode BOM
使用文本编辑器中的选项(即 Mousepad)保存。
除此之外,用户将看到两种运行 Python 脚本的方法。两种方法均已演示如下。
方法一:用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 都能够成功运行该脚本。因此,shebang 行是不是python
通过或命令运行 Python 脚本时需要python3
。
方法 2:作为 Python 脚本运行
下面是使用 shebang 行运行源代码时的命令和输出,它们不适用于 Python 2 和 Python 3,包括不可执行和可执行的情况。
$ ./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!
前三个脚本失败了,因为这些脚本是不可执行的,无论是否有 shebang 行(有关支持证据,请参阅其他示例下面)。最后两个脚本有 shebang 行并且可以执行。
显然,如果没有 shebang 行,已设置为可执行的脚本基本上是无用的。因此,在可执行脚本中运行 Python 代码时,shebang 行是必需的,并且脚本必须是可执行的。
当 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,))'
运行此脚本时,首先,鼠标光标将变为加号,并且外观上没有任何反应。直到我单击桌面或终端窗口时,语法错误才会显示出来。然后,此脚本将sys
在与脚本相同的目录中创建一个文件。
$ file sys
sys: PostScript document text conforming DSC level 3.0, Level 1
该sys
文件已被识别为 PostScript 文件,没有文件扩展名。该文件可以在文档查看器(即 Evince)中打开,并且该文件实际上包含我之前单击的窗口的屏幕截图。根据我的经验,该文件可能最大为几兆字节。
再次强调,当将 Python 脚本作为可执行脚本运行时,shebang 行是必需的,并且脚本必须是可执行的。否则,脚本将出现如上所述的错误行为。
补充笔记
术语“使之可执行”或“必须可执行”是指运行脚本的权限。这可以通过chmod +x FILENAME
在终端中运行命令来完成,或者在特性窗口,在文件管理器内。
虽然其他现有答案几乎涵盖了所有内容,但这个答案采用了不同的方法,使用实际示例来解释问题。代码语法经过精心编写,因此示例可以使用 Python 2 或 Python 3 运行。
Python 代码改编自在 Windows 上使用 Python和在 Unix 平台上使用 Python,并附加了随处可见的“Hello, World!”程序的一行代码。
所有代码和命令都经过了充分测试,可以在 Xubuntu 14.04 系统上运行,该系统默认安装了 Python 2.7 和 Python 3.4。