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


50

一个很简单的问题:在Linux中,为什么Python需要该行

#!/usr/bin/python

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

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


28
下面的答案都是正确的,没有一个可以解决Windows不需要此行的原因。Windows取决于文件的扩展名(后面的部分.)来确定文件的类型。甚至Windows都在远离它:检查Microsoft Word文件的前几行,它会声明它实际上是Microsoft Word文件。
格林

9
房间里的麻烦之处在于,除非您与python 2和3兼容,否则切勿使用/ usr / bin / python。原因:arch将其链接到python3,PSF承认这一举动,PSF对此建议自己反对。
另一个用户

5
这是隐含的,但未在下面的答案中明确指出不是必需的。如果只想使用ts自己的名称执行脚本,则需要使用该脚本。您可以随时运行python myscript.py
克里斯H

3
@CharlesGreen我们不应该知道为什么Windows不这样做;-)这取决于SO。
Rinzwind

2
@YetAnotherUser距离Python 3发行已经6年11个月了,在这一点上,我认为人们最好不使用默认值3并在必要时明确指定使用2。
2015年

Answers:


58

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如何启动脚本:

首先要注意的是,与Windows不同,Unix / Linux至少在概念上没有尝试使用特定程序“打开” Python脚本。OS 知道脚本是可以执行的,因为有一个称为“执行位”的东西(不在此答案的范围之内)。因此,如果您不小心输入#!/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行实际上所做的只是允许程序加载器选择解释器。但是就像在Windows中一样,这可以手动完成:

python <myscript>

1
在Windows上,您可以轻松地拥有.py2.py3扩展Python 2 / Python 3脚本。因此,Linux(+ x位)和Windows(文件扩展名)都需要文件系统中的元数据。主要区别在于+ x位在传输中更容易丢失。这不一定是不利的。
MSalters 2015年

1
@MSalters执行位中还包含少得多的编码信息。并请注意,在给定的系统上可能有多个Python2解释器(在我的上一份工作中,Ruby和其他语言也存在类似情况);通过shebang行处理此问题几乎是微不足道的,而Windows上的情况变得越难处理,您尝试管理多个相似文件类型的尝试就越多。
凯尔·斯特兰德

另外,该扩展真的算作“元数据”吗?它只是文件名的一部分。
凯尔·斯特兰德

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

1
@MSalters好吧,这就是/usr/bin/env它的用途,以及env-setup脚本。Windows的版本是什么?regedit在启动.py文件之前立即运行脚本,以确保获得所需的解释器?
凯尔·斯特兰德

41

您所指示的行用于告诉计算机直接运行文件/脚本时使用什么程序/解释器,以及在脚本运行时应传递给该程序的所有参数。但是,这不是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等)执行类似操作。)

上面的语法高亮在每个部分中都是特定于语言的,尽管并不重要。


1
添加一个有趣的事情是,这是可能的家当自己后指定附加参数,在大多数以同样的方式对案件如果解释被直接调用(#!/bin/bash -x#!/usr/bin/perl -lan,等)。
kos 2015年

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

@progo不确定问题出在哪里env,但问题似乎在于参数的数量:#!/usr/bin/perl -l -a -n具有三个参数,但是可以使用。再次说明,我无法解决确切的问题。
kos 2015年

当以脚本作为参数显式调用解释器时,没有理由使后者以开头./。换句话说,公正python filename.pybash script.sh将工作正常。要包含./在命令行中的唯一原因是要告诉外壳程序不要搜索$PATH(它可能不会在当前目录中找到文件)而是采用原样指定的路径。但这不适用于命令参数。
Marc van Leeuwen 2015年

@kos:问题可能在于如何env从内核接收其余的参数。可以将它们全部假定为一个大参数,而不执行按空间分割。很抱歉表达清楚,我现在不记得这个细节了
unperson325680

16

该行:

#!/usr/bin/python

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

因此,该行#!/usr/bin/python表明文件的内容将由python位于的二进制文件解释/usr/bin/python

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

python script_name

在以下情况下类似#!/bin/bash

bash script_name

2
我认为我从未见过连字号shebang。由于该单词是由“哈希”和“爆炸”构成的,因此您的拼写不是很清楚,因为它看起来像是“她”和“爆炸”的组合。
凯尔·斯特兰德

您可以将其称为hashbang#=“ hash”)或shebang#=“ sharp”),具体取决于您如何命名#角色。但是,shebang确实更普遍。@KyleStrand
Byte Commander

7

从技术上讲,它不是必需的。它需要一个脚本执行环境的路径。您将来的脚本最好包含/ usr / bin / env,然后指定python。无论您在哪里安装python,这都可以确保您的脚本在python环境中运行。您出于兼容性原因要执行此操作,您不能确保与您共享代码的下一个人员将在usr / bin / python中安装python,或者他们将对这些系统文件具有权限。

这是来自堆栈溢出的类似问答

脚本中的内容如下:

#!/usr/bin/env python

我还对如何指定python3感到有些担忧。这是操作方法:

#!/usr/bin/env python3

5

在Linux中,Python可能需要也可能不需要#!(shebang)行。这取决于如何以Python交互模式或Python脚本运行代码来处理Python代码。

Python交互模式允许用户直接键入和运行Python代码,而无需使用shebang行。要运行交互模式,请打开终端,然后输入pythonPython 2.X或python3Python3.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脚本。两种方法已被证明如下。

方法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都能成功运行脚本。因此,在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!

前三个脚本失败了,因为这些脚本是不可执行的,无论是否具有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,))'

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

$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1

sys文件已被识别为PostScript文件,没有文件扩展名。可以在文档查看器(即Evince)中打开此文件,并且该文件实际上包含我之前单击的窗口的屏幕截图。以我的经验,该文件可以大到几兆字节。

再一次,shebang行是必需的,并且在将Python脚本作为可执行脚本运行时,脚本必须是可执行的。否则,脚本将无法正常运行,如上所述。

补充笔记

术语“可执行文件”或“必须可执行文件”是指运行脚本的权限。通过chmod +x FILENAME在终端中运行命令,或通过在文件管理器中的“ 属性”窗口中选中“允许此文件作为程序运行”选项或类似操作,可以完成此操作。

尽管其他现有答案几乎涵盖了所有内容,但此答案已通过使用实际示例来说明此问题而采用了不同的方法。代码语法的编写非常谨慎,因此示例可以直接在Python 2或Python 3上运行。

Python的代码已被改编自Windows上使用PythonUnix平台上使用Python,与无处不在的额外一行代码“你好,世界!” 程序。

所有代码和命令都经过了全面测试,并且可以在Xubuntu 14.04系统中运行,该系统默认情况下安装了Python 2.7和Python 3.4。


4

这意味着在执行该文件后,您的计算机便知道该程序可以执行该文件/usr/bin/python,这就是您将其与另一种语言(例如bash)区别开的地方#!/bin/bash。这样,您可以简单地运行:

./[file-to-execute]

而且它将知道执行哪个文件,而不需要您自己指定以下内容:

python ./[file-to-execute].py

#!部分通常称为“ Shebang”或“ Crunch bang”


2
也是一个哈希爆炸。
Naftuli Kay 2015年

1

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

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

此规则仅适用于基于UNIX的系统。


0

对于像Linux这样的OS很有帮助,而Linux 2.x仍然是标准配置,但大多数人还下载3.x。

2.x将默认运行。因此,我的3.x代码以#!/ usr / bin / env python3为前缀,以便3.x运行该代码。如果我选择使用beta版本或稍旧的版本,甚至可以指定次要版本(python 3.xyz)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.