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

Tel*_*Why 58 python scripts

非常简单的问题:在 Linux 中,为什么 Python 需要该行

#!/usr/bin/python
Run Code Online (Sandbox Code Playgroud)

在 python 文件的开头,因为 Windows 没有?

它有什么作用?因为“Python 链接”的描述有点含糊......

Kyl*_*and 71

Python对 Linux 没有任何这样的特殊要求。它是Unix/Linux 上的程序加载器,它使用所谓的“shebang”行。这实际上是一个功能而不是限制,但我们稍后会谈到。“shebang”上的 Wiki 页面有更多详细信息,但我将尝试在此处提供概述以及与 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#!/usr/bin/env python)会发生什么?好吧,由于#是 Python 中的注释行,Python 解释器会忽略它。这就是 Unix/Linux 世界中使用的大多数脚本语言都用于#开始注释行的原因之一。

所以说Windows“不需要”这#!条线有点误导;Windows 没有看到#!行,实际上依靠文件扩展名来告诉它要做什么。这有几个缺点:

  • 必须.py在末尾命名 Python 脚本,以便自动识别它们。
  • 没有简单的方法可以区分 Python2 脚本和 Python3 脚本。
  • 如前所述,如果您更改.py文件类型的默认启动行为,Windows 将不再使用 Python 自动运行这些脚本。请注意,这可能是无意中完成的。

现在,让我们看看 Unix/Linux 如何启动脚本:

首先要注意的是,Unix/Linux 与 Windows 不同,不会尝试使用特定程序“打开”Python 脚本,至少在概念上是这样;操作系统知道脚本是可以执行的,因为它被称为“执行位”(这超出了本答案的范围)。因此,如果您不小心输入了#!/usr/bin/pthon而不是#!/usr/bin/python,您将收到一条包含以下文本的错误消息:

/usr/bin/pthon: bad interpreter: No such file or directory.
Run Code Online (Sandbox Code Playgroud)

“解释器”一词为我们提供了有关 shebang 行角色的线索(尽管从技术上讲,指定的程序可以不是解释器,例如cat或文本编辑器)。当您尝试执行文件时,会发生以下情况:

  • Unix/Linux 程序加载器查看该文件的前两个字节;如果这两个字节是#!,则加载程序将 shebang 行的其余部分(不包括 shebang 本身)解释为启动解释器的命令,通过该解释器将文件内容作为脚本运行。
  • 程序加载器启动指定的解释器,将原始文件的路径作为参数提供给它。

这有几个优点:

  • 脚本编写者可以更好地控制将使用哪个解释器(这解决了 Python2/Python3 问题),并且有时可以将额外的参数传递给解释器(有关详细信息,请参阅 Wiki 页面)。
  • 脚本的文件名被忽略,因此您可以随意命名 Python 脚本。

注意,最后,在Unix / Linux并没有 需要的家当线,以运行Python脚本。回想一下,shebang 行实际上所做的就是允许程序加载器选择一个解释器。但就像在 Windows 中一样,这可以手动完成:

python <myscript>
Run Code Online (Sandbox Code Playgroud)

  • 文件的元数据包括整个文件名、创建时间、访问位等。只有内容本身是数据而不是元数据。至于“多个解释器”,这确实是一个真正的问题,这正是为什么它_不应该_出现在shebang行中。如果你有 `/usr/bin/i686/python` 和 `/usr/bin/amd64/python` 怎么办?完全合理,但它破坏了对 `/usr/bin/python` 有硬编码假设的 python 脚本。解释器的选择不是脚本编写者的选择,而是脚本用户的选择,脚本编写者只能选择语言(方言)。 (3认同)

Tho*_*ard 42

您指示的行用于告诉计算机在直接运行文件/脚本时使用什么程序/解释器,以及在脚本运行时应传递给该程序的任何参数。但是,这不是Python的要求,如果您打算直接运行脚本(而不是通过以下语法将其传递给 Python),则这是 linux 内核/系统的要求。

如果您要执行python script.py或类似操作,则不需要它。仅当您打算直接运行脚本/文件时才需要它,而无需提供要使用的解释器(例如python)。


对于 Bash 脚本,它应该是这样的:

#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;
Run Code Online (Sandbox Code Playgroud)

这将向系统表明,当它运行时,它应该通过/bin/bash它是系统上的一种 shell/shell 脚本语言来运行。


但是,对于 Python 代码,在这里,您将希望通过 Python 运行可执行文件,因此您告诉它您打算在其中运行什么解释器。

#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()
Run Code Online (Sandbox Code Playgroud)

这与 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 等)执行或类似操作。)

上面的语法突出显示在每个部分中都是特定于语言的,尽管这并不重要。

  • @kos:我认为您可以准确指定一个额外的参数,当一个人(应该)使用`/usr/bin/env python` 来获得正确的 python 时,它就是一个 PITA。 (7认同)

hee*_*ayl 16

线路:

#!/usr/bin/python
Run Code Online (Sandbox Code Playgroud)

被称为“shebang”,它表示将用于解释文件中其余命令的解释器二进制文件的路径。它通常是脚本的第一行。

因此该行#!/usr/bin/python表示文件的内容将由python位于/usr/bin/python.

请注意,shebang 行由内核解析,然后脚本最终将作为参数调用:

python script_name
Run Code Online (Sandbox Code Playgroud)

类似的情况#!/bin/bash

bash script_name
Run Code Online (Sandbox Code Playgroud)

  • 我认为我从未在“shebang”中看到过连字符。因为这个词是由“hash”和“bang”组成的,你的拼写不是很清楚,因为它看起来像是**“she”**和“bang”的组合。 (2认同)

j0h*_*j0h 7

从技术上讲,它不需要它。它需要一个指向脚本执行环境的路径。你未来的脚本最好包含 /usr/bin/env 然后指定 python。这意味着无论 python 安装在哪里,您的脚本都可以在 python 环境中运行。出于兼容性原因,您想这样做,您无法确定与您共享代码的下一个人将在 usr/bin/python 中安装 python,或者他们是否有权访问这些系统文件。

这里有一个来自 stack overflow 的类似问答

在你的脚本中看起来是这样的:

#!/usr/bin/env python
Run Code Online (Sandbox Code Playgroud)

我也看到了一些关于如何指定 python3 的担忧。这是如何做到的:

#!/usr/bin/env python3
Run Code Online (Sandbox Code Playgroud)


小智 5

在 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.
>>>
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)
  • hello1.py 仅包含源代码。

    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
    
    Run Code Online (Sandbox Code Playgroud)
  • hello2.py 包含源代码和shebang行。

    #!/usr/bin/env python
    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
    
    Run Code Online (Sandbox Code Playgroud)
  • 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在文本编辑器中使用选项保存,即鼠标垫。

除此之外,用户将看到两种运行 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!
Run Code Online (Sandbox Code Playgroud)

两个版本的 Python 都能够成功运行脚本。因此,在shebang行经由运行Python脚本时,需要pythonpython3命令。

方法 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!
Run Code Online (Sandbox Code Playgroud)

前三个脚本失败了,因为这些脚本是不可执行的,无论是否有 shebang 行(有关支持证明,请参阅下面的附加示例)。最后两个脚本有 shebang 行并且是可执行的。

显然,如果没有 shebang 行,已经可以执行的脚本基本上是无用的。因此,在可执行脚本中运行 Python 代码时,需要 shebang 行并且脚本必须是可执行的。

当shebang不起作用时

在我准备和测试的示例中,hello3m.py作为可执行脚本运行失败并返回错误。

$  ./hello3m.py 
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory
Run Code Online (Sandbox Code Playgroud)

这是一个已知的限制,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,))'
Run Code Online (Sandbox Code Playgroud)

运行此脚本时,首先,鼠标光标将更改为加号,并且在外观上没有任何作用。在单击桌面或终端窗口之前,不会显示语法错误。然后,此脚本将sys在与脚本相同的目录中创建一个文件。

$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1
Run Code Online (Sandbox Code Playgroud)

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。