当前位置: 首页 > news >正文

【趣味阅读】Python 文件头的秘密:从编码声明到 Shebang

文章目录

    • 一、`# -*- coding: utf-8 -*-` 的用意是什么?
    • 二、编码声明的规范写法
    • 三、那 Python 3 就不需要编码声明了吗?
    • 四、shebang 行是干什么的?
    • 五、shebang 这个词从哪来的?
    • 六、总结
    • 七、思考

在日常写 Python 的时候,你可能见过这样的文件头:

# -*- coding: utf-8 -*-

或者:

#!/usr/bin/env python3

很多人照抄,却未必真的理解它们的来历和规范。今天我们就一步步探索,从带着疑问到豁然开朗,把背后的故事讲清楚。

一、# -*- coding: utf-8 -*- 的用意是什么?

一开始,我也只是机械地在文件头写上这行,后来才知道:

  • 这是告诉 Python 解释器编辑器:源文件采用 UTF-8 编码。
  • 在 Python 2 中,默认编码是 ASCII,所以写中文就必须加这一行,否则会报错。
  • 在 Python 3 中,默认编码已经是 UTF-8(见 [PEP 3120]),因此通常不需要写。

也就是说,如果你只写 Python 3,文件里又没有奇怪的编码,其实可以省略。

二、编码声明的规范写法

  1. 位置:必须放在文件的 前两行 之一。

    • 如果文件开头有 #!(shebang 行),那么编码声明要写在第二行;

      #!/usr/bin/env python3
      # -*- coding: utf-8 -*-
      
    • 如果没有 shebang 行,就写在第一行。

      # -*- coding: utf-8 -*-
      
    • 原因:解释器在扫描源码时,只读取前两行来决定文件编码。

  2. 格式:查了 PEP 263 之后,才知道 Python 解释器通过正则表达式识别的模式很严格:

    # -*- coding: utf-8 -*-
    # coding=utf-8
    

    这两种都行。

    而有些人写的:

    # encoding=utf-8
    # -*- encoding=utf-8 -*-
    

    抱歉,这其实不符合 PEP 263 规范!解释器根本不认。可能某些编辑器会看得懂,但 Python 解释器本身会忽略。

    所以,请坚持用 coding 而不是 encoding

  3. 大小写codingutf-8 不区分大小写,但社区习惯使用小写。

  4. 空格:PEP 263 对编码声明的正则表达式为 ^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)

    • # 前后可以有空格;
    • coding:= 之间,不允许空格;
    • 分隔符到编码名称之间,允许空格;
    • 编码名称内部,不允许空格(必须单个合法 token,如 utf-8ascii)。

    ✅合法例子

    # coding=utf-8
    # coding= utf-8
    #coding: utf-8
    # coding:utf-8
    # coding: utf-8
    # -*- coding: utf-8 -*- 
    #     coding: utf-8# coding: utf-8
    

    ❌ 不合法例子

    # coding = utf-8
    # coding : utf-8
    # coding: utf - 8
    

三、那 Python 3 就不需要编码声明了吗?

没错。Python 3 默认就是 UTF-8,因此:

  • 只写 Python 3:编码声明是冗余的。
  • 需要兼容 Python 2:那就老老实实写上 # -*- coding: utf-8 -*-

这时候我突然意识到:原来我们很多写法,其实是“历史遗留”!

四、shebang 行是干什么的?

再来看另一种常见的文件头:

#!/usr/bin/env python3

这叫 shebang 行(也叫 hashbang)。它的作用是:

  • 在 Linux / macOS 下,告诉操作系统用哪个解释器来运行脚本。
  • 如果脚本加了可执行权限(chmod +x script.py),就能直接 ./script.py 执行。
  • 如果没有 shebang,直接执行会报错(除非你显式写 python script.py)。

推荐的写法是:

#!/usr/bin/env python3
  • 而不是写死成 #!/usr/bin/python3,因为不同系统,路径可能不同。而env 会自动帮你在 PATH中找解释器。
  • 也不建议写成 #!/usr/bin/env python,因为可能会指向 Python2, 不建议再这样写。
  • 此外 #! 后面应该紧跟解释器路径,不能有前导空格,👉 保证在各种 Unix 系统上都能正确运行。
  • 在 现代 Linux / macOS 下,#! /usr/bin/env python3 这种写法虽然能跑,但依赖的是 “宽松实现”,并不是标准行为。
  • 因为主流 Linux 内核源码 fs/binfmt_script.c 会 skip_spaces(),自动跳过前导空格。

位置:

  • 必须在文件的第一行,并且必须以 #! 开头。

  • 因为这是操作系统内核(execve)在运行脚本时直接解析的,而不是 Python 自己处理的。
    如果前面有空行或注释,shebang 就失效了。

那现在的必要性如何呢?

  • Linux / macOS:如果希望脚本像普通命令一样直接运行,shebang 行仍然非常必要。
  • Windows:shebang 行不起作用,系统靠 .py 扩展名来决定解释器,但写上也不影响。

五、shebang 这个词从哪来的?

这部分特别有意思。

  1. 历史背景
    shebang 是 Unix 第七版(1979 年) 加入的功能,用来告诉内核脚本应该用哪个解释器运行。当时 shell 脚本是主流,这个设计解决了“脚本用什么解释器跑”的问题。

  2. 符号组成
    shebang 行的开头是:

    #!
    
    • # 号在 Unix 里叫 hash
    • ! 号在口语里常被叫做 bang(Unix 黑客传统用语,源自打印机和电传机时代)

    hash + bang 拼在一起,就成了 shebang

  3. she- 的由来
    这个前缀并不是“she 她”的意思,而是口语发音的简化:

    • “hash-bang” → “sharp-bang” → “sh-bang” → “shebang”

    • 后来逐渐就固定写成 shebang 了。

  4. 这两个的读音怎么来的

    • # 为什么叫 hash

      • Unix 黑客文化里,# 常被叫做 hash
        • “hash” 原意是“切碎、混合”,因为 # 符号看上去像格子网,被形象地称为 hash。
        • 这种叫法在程序员社区里流行开来,比如 hash mark
        • 另一部分人受音乐升半音符号(sharp sign) ♯ 的影响,自然而然将 # 读作 sharp。
        • 比如微软的 C#语言 (读作 C Sharp) 的命名就含有 “比 C 语言高半点” 的程序员幽默。
          music sharp sign
    • ! 为什么叫 bang

      • 在英语里,! 的正式名称是 exclamation markexclamation point

      • 但在早期 电传打字机(teletypewriters, TTY)Unix 黑客圈子里,大家更喜欢用短促的单词来念标点。

      • 当时 ! 常用于表示“激烈动作/爆炸声”,所以用 bang(拟声词)来念,既短又形象。

      • 其实我自己觉得也可以把!!形象地看成哆啦A梦两个小圆手拿着啦啦棒互相拍打发出 “Bang Bang” 响声:
        bang bang

      举个例子:

      • !! 在邮件或新闻组里就念作 “bang bang”
      • 早期的 UUCP 网络用 ! 分隔路径,host1!host2!user 就读成 “host1 bang host2 bang user”。
    • 组合起来

      • #! → 读作 hash bang

        后来为了更顺口,读音演变成 shebang(hash-bang → sharp-bang → sh-bang → shebang)。

于是 #! 就被念作 hash bang。久而久之,口语演变成了 shebang(sharp-bang → sh-bang → shebang)。

原来名字背后还有这种黑客幽默!

六、总结

一路探索下来,我们可以这样归纳:

  1. shebang 行
    • 让脚本在类 Unix 系统下可直接运行。
    • 推荐写法是 #!/usr/bin/env python3
    • 必须在文件的第一行,并且必须以 #! 开头。
    • #! 和解释器路径之间,推荐是不加空格。
    • 在 Linux/macOS 下必要,Windows 下可有可无。
    • 名字来源于 #(hash)和 !(bang)。
  2. 编码声明
    • Python 2 必须写,否则非 ASCII 会报错。
    • Python 3 默认 UTF-8,可以不写。
    • 规范写法是 # -*- coding: utf-8 -*-# coding=utf-8
    • coding:= 之间,编码名称utf-8字符之间,都不能加空格。
    • 必须在文件的前两行之一(一般紧跟在 shebang 后)。

是不是感觉以前机械抄写的几行注释,现在突然有了“灵魂”?😄

七、思考

其实很多编程习惯,背后都有 历史包袱黑客文化。今天我们把它拆开来看,像是解谜:从一行注释,到一段 Unix 传统,最后恍然大悟。

你平时在写 Python 文件头时,会选择 简洁派(不写编码,不写 shebang),还是 传统派(都写上,兼容性更强) 呢?

http://www.dtcms.com/a/362185.html

相关文章:

  • VisionProC#联合编程相机实战开发
  • 【云存储桶安全】怎么满足业务需求,又最大程度上满足信息安全要求呢?
  • 1792. 最大平均通过率
  • 学习:uniapp全栈微信小程序vue3后台-暂时停更
  • 本地没有公网ip?用cloudflare部署内网穿透服务器,随时随地用自定义域名访问自己应用端口资源
  • 液态神经网络:智能制造的新引擎
  • 【跨境电商】上中下游解释,以宠物行业为例
  • 洛谷 c++ P1177 【模板】排序 题解
  • AutoSar RTE介绍
  • 特征增强方法【特征构建】
  • MVC、三层架构
  • RT-DETR网络结构
  • 并发之线程
  • 【思考】WSL是什么
  • 一、SVN与svnbucket.com常见问题解答
  • 从组分到涌现:系统科学视域下结构、功能与层级的辨析及在人工智能中的应用
  • 设备管理软件正在成为制造业企业的战略重点_HawkEye智能运维平台_璞华大数据
  • 对比Mysql理解OceanBase中的租户设计
  • PostgreSQL 从入门到精通:一场与开源数据库的深度对话
  • 时序数据库国产的有哪些?
  • 利用棒棒糖图探索Office (US)的IMDB评分
  • 毕业项目推荐:64-基于yolov8/yolov5/yolo11的蝴蝶种类检测识别系统(Python+卷积神经网络)
  • 如何修复 Vercel 函数超时并大幅降低云函数成本
  • 计组(2)CPU与指令
  • 我的学习经历,个人能力说明书,求职书
  • 伺服器模拟输入控制电机转速
  • 华为云CCE
  • 【计算岗位解析:从代码到产品,这些角色如何“造”出数字世界?】
  • SpringBoot的基础介绍,用法和配置
  • 线上API接口响应慢?一套高效排查与定位问题的心法