#!/ usr / bin / python3的目的

时间:2011-10-06 04:29:17

标签: python scripting

我已经注意到了几种脚本语言,但在这个例子中,我使用的是python。在许多教程中,它们将从第一行的#!/usr/bin/python3开始。我不明白为什么我们有这个。

  • 操作系统不应该知道它是一个python脚本(显然它已经安装,因为你正在引用它)。
  • 如果用户使用的操作系统不是基于unix的
  • ,该怎么办?
  • 语言因任何原因安装在不同的文件夹中
  • 用户拥有不同的版本。特别是当它不是完整版本号(如Python3与Python32)时

如果有的话,由于上面列出的原因,我可以看到这打破了python脚本。

7 个答案:

答案 0 :(得分:184)

#!/usr/bin/python3 shebang line

shebang行定义了解释器所在的位置。在这种情况下,python3解释程序位于/usr/bin/python3。一个shebang行也可以是bashrubyperl或任何其他脚本语言的解释器,例如:#!/bin/bash

如果没有shebang行,操作系统就不会知道它是一个python脚本,即使你在脚本上设置执行标志并像./script.py那样运行它。要使脚本在python3中默认运行,请将其作为python3 script.py调用或设置shebang行。

如果他们在不同的位置安装了语言解释器,您可以使用#!/usr/bin/env python3在不同系统中实现可移植性。

答案 1 :(得分:18)

这叫做哈希爆炸。如果从shell运行脚本,它将检查第一行以确定应该启动什么程序来解释脚本。

非基于Unix的操作系统将使用自己的规则来确定如何运行脚本。例如,Windows将使用文件扩展名,#将导致第一行被视为注释。

如果Python可执行文件的路径错误,那么脚本自然会失败。从标准约定指定的任何位置创建实际可执行文件的链接很容易。

答案 2 :(得分:10)

此行有助于查找将运行脚本的程序可执行文件。这种shebang符号在大多数脚本语言中都是相当标准的(至少在成人操作系统中使用)。

这一行的一个重要方面是指定将使用哪个解释器。例如,在许多以开发为中心的Linux发行版中,同时安装多个版本的python是正常的。

Python 2.x和Python 3不是100%兼容的,因此这种差异非常重要。因此#! /usr/bin/python#! /usr/bin/python3不一样(并且与#! /usr/bin/env python3完全相同,如本页其他地方所述。

答案 3 :(得分:5)

  1. 此行如何

  2. 被忽略。

  3. 它将无法运行,应更改为指向正确的位置。或者应该使用env

  4. 它无法运行,无论如何都无法在不同的版本下运行。

答案 4 :(得分:2)

要弄清shebang行在Windows中的工作原理,请从3.7 Python doc

  • 如果脚本文件的第一行以#!开头,则称为“ shebang”行。 Linux和其他类似Unix的操作系统对此行具有本地支持,它们通常在此类系统上用于指示应如何执行脚本。
  • Windows的Python启动器允许Windows上的Python脚本使用相同的功能
  • 为了允许Python脚本中的shebang行在Unix和Windows之间可移植,启动器支持许多“虚拟”命令来指定要使用的解释器。支持的虚拟命令是:
    • / usr / bin / env python
      • shebang行的/ usr / bin / env格式还有另一个特殊属性。在查找已安装的Python解释器之前,此表单将在可执行文件PATH中搜索Python可执行文件。这与Unix env程序的行为相对应,该程序执行PATH搜索。
    • / usr / bin / python
    • / usr / local / bin / python
    • python

答案 5 :(得分:1)

Linux 内核的 exec 系统调用本机理解 shebangs (#!)

当你使用 bash 时:

./something

在 Linux 上,这将调用 exec 系统调用,路径为 ./something

内核的这一行在传递给 exec 的文件上被调用:https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

它读取文件的第一个字节,并将它们与 #! 进行比较。

如果比较结果为真,则该行的其余部分由 Linux 内核解析,这将再次调用 exec,以路径 /usr/bin/python3 和当前文件作为第一个参数:

/usr/bin/python3 /path/to/script.py

这适用于任何使用 # 作为注释字符的脚本语言。

类似地,如果您决定改用 env,您可能应该始终这样做,以便在 python3 位于不同位置(特别是 pyenv)的系统上工作,另请参阅this question,shebang:

#!/usr/bin/env python3

以类似方式结束调用:

/usr/bin/env python3 /path/to/script.py

执行您对 env python3 的期望:在 PATH 中搜索 python3 并运行 /usr/bin/python3 /path/to/script.py

是的,您可以使用以下方法进行无限循环:

printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a

Bash 识别出错误:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! 恰好是人类可读的,但这不是必需的。

如果文件以不同的字节开始,那么 exec 系统调用将使用不同的处理程序。另一个最重要的内置处理程序是针对 ELF 可执行文件的:https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305,它检查字节 7f 45 4c 46(对于 .ELF,它也恰好是人类可读的)。让我们通过读取 /bin/ls 的前 4 个字节来确认,这是一个 ELF 可执行文件:

head -c 4 "$(which ls)" | hd 

输出:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

因此,当内核看到这些字节时,它会获取 ELF 文件,将其正确放入内存中,并使用它启动一个新进程。另见:How does kernel get an executable binary file running under linux?

最后,您可以使用 binfmt_misc 机制添加您自己的 shebang 处理程序。例如,您可以添加 custom handler for .jar files。这种机制甚至支持文件扩展名的处理程序。另一个应用是transparently run executables of a different architecture with QEMU

我不认为 POSIX 指定了 shebangs 但是: https://unix.stackexchange.com/a/346214/32558 ,尽管它确实在基本原理部分中提到,并且以“如果系统支持可执行脚本,可能会发生某些事情”的形式出现。不过 macOS 和 FreeBSD 似乎也实现了它。

PATH 搜索动机

很可能,shebangs 存在的一大动机是在 Linux 中,我们经常希望从 PATH 运行命令,就像:

basename-of-command

代替:

/full/path/to/basename-of-command

但是,如果没有 shebang 机制,Linux 怎么知道如何启动每种类型的文件?

在命令中硬编码扩展:

 basename-of-command.py

或在每个解释器上实现 PATH 搜索:

python3 basename-of-command

有可能,但这有一个主要问题,如果我们决定将命令重构为另一种语言,一切都会中断。

Shebangs 很好地解决了这个问题。

另见:Why do people write #!/usr/bin/env python on the first line of a Python script?

答案 6 :(得分:0)

实际上,确定文件的文件类型非常复杂,因此现在操作系统不能仅仅知道。它可以根据-

做出很多猜测
  • 扩展名
  • UTI
  • MIME

但是命令行并不打扰所有这一切,因为它在有限的向后兼容层上运行,从那一刻开始,废话毫无意义。如果您双击确定,现代操作系统可以解决这一问题,但是如果您从终端运行它,则不会,因为终端并不关心您的操作系统特定的文件键入API。

关于其他要点。这很方便,也可以运行

python3 path/to/your/script

如果您的python不在指定的路径中,则它将不起作用,但是我们倾向于安装一些东西来使诸如此类的东西起作用,而不是相反。您是否在* nix下实际上并不重要,因为这是shellcode,所以是否要考虑此行取决于您的外壳。因此,例如,您可以在Windows下运行bash

实际上您可以完全省略此行,这仅意味着调用方将必须指定解释器。另外,请勿将您的口译员放在非标准位置,然后尝试在不提供口译员的情况下调用脚本。