为什么 Linux 中的 Python 需要 #!/usr/bin/python 这一行?

为什么 Linux 中的 Python 需要 #!/usr/bin/python 这一行?

一个非常简单的问题:在 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 脚本顶部有一个 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 行。要运行交互模式,请打开终端并输入pythonPython 2.X 或python3Python 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 行。

  1. 在可执行脚本中运行 Python 代码,即定义如何运行代码以及使用什么解释器;

  2. 运行与特定 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。

相关内容