⚙️ 第七章 程序在怎样的环境下运行
📄 一句话概括

拿到程序有两条路:现成的可执行文件或拿源码自己编;源码安装多花一道编译,换来的是能改、能换平台、能自己调。

📝 本节和前面几节的关系

7.3 讲的是系统的差异,这一节换到使用者的角度:程序要怎么弄到自己的机器上。

一、两条路

第一条:直接用可执行文件。 复制过去就能跑,简单但换平台就得等别人出包。 第二条:拿源代码自己编译。 多一道工序,但能改、能换平台、能针对自己的环境调优。 开源软件多半走第二条路——因为源码是公开的,编与不编由你决定。 这两条路的取舍,本质上是【省事】和【掌控】之间的选择。

二、源码安装多出来的那道工序:编译

编译做的事只有一件:把给人看的源码,翻成给机器看的代码。 但这一步往往不是一行命令:要先装编译器、装依赖库、配好参数,再等它编完。 所以源码安装最常卡住的地方不是编译本身,而是环境和依赖。 这也是它最被诟病的一点:明明只是想装个软件,却先要解决一堆前置问题。

三、Python 也有【编译】这一步

只不过程序员通常感觉不到,因为它是自动做的。 Python 把源码翻成字节码——一种给解释器看的中间产物,存在缓存文件里。 所以第二次运行同一个程序会快一点,因为字节码已经编好了。 注意这个产物不是本机代码:它换一台 CPU 照样能用,真正跟 CPU 打交道的活儿由解释器干。

四、这一节的落点

两条路的选择,可以按三句话来判断: 只想用 → 装可执行文件。 省时省事。 要用在别的平台上 → 拿源码编。 或者等别人编好。 想改、想调优、想跟进去看 → 只能走源码。 而【编译出来的产物是不是给 CPU 看的】,决定了这个程序能不能跨平台——这正是下一节的主题。

五、动手 Demo:使用源代码进行安装

拿到一个程序,两条路:用现成的可执行文件,或者拿源代码自己编。 Python 也有编译这一步,只是它的产物是字节码。

import dis
src = "total = 0" + chr(10)
src += "for i in range(1, 6):" + chr(10)
src += "    total = total + i" + chr(10)
src += "print(total)" + chr(10)
code = compile(src, "<demo>", "exec")
print("指令条数", len(list(dis.get_instructions(code))))

实跑输出:

--------------------------------------------------------------------
使用源代码进行安装
--------------------------------------------------------------------

拿到一个程序,两条路:**用现成的可执行文件**,或者**拿源代码自己编。**

  对比项       用可执行文件         用源代码
  -------------------------------------------------------
  要装什么     复制过去就能用       还得装编译器、依赖库
  快不快       立刻可用             要编几分钟到几小时
  换平台       要等别人出新版本     自己重新编一遍就行
  能不能改     改不了               想改哪行改哪行

  源码安装的核心就一步:**编译——把给人看的源码翻成给机器看的代码。**
  Python 也有这一步,只不过它的产物是【字节码】,**由解释器在运行时执行。**

  拿一段三行的源码走一遍:

    源码字符数    67
    源码行数      4(含末尾空行)
    编出来        code 对象,共 24 条指令
    它是给谁看的  给解释器看的中间产物,**不是本机代码**

  编译出来的指令:

    RESUME                 0
    LOAD_CONST             0
    STORE_NAME             total
    LOAD_NAME              range
    PUSH_NULL
    LOAD_CONST             1
    LOAD_CONST             6
    CALL                   2

  **注意最后一行:这个产物换一台 CPU 照样能跑——**
  因为它交给的是【解释器】,**真正跟 CPU 打交道的活儿由解释器干。**
  这正是下一页要讲的虚拟机。

67 个字符的源码编成了 24 条指令——这就是【字节码】。 它是给解释器看的中间产物,不是本机代码:换一台 CPU 照样能用。

30 秒实验

  1. 找一段开源的 C 程序,看看它的安装说明里第一步要装什么。
  2. 把同一段 Python 源码在笔记本和树莓派上各跑一次,看看字节码是不是通用的。

常见误区

  1. 以为源码安装只是【多一步】。它还要准备编译器、依赖库和环境。
  2. 以为字节码就是本机代码。它给解释器看,换 CPU 也不用改。
自测三问(点开对答案) 1. 源码安装比可执行文件多出哪一步? —— 编译——把源码翻成机器(或解释器)能执行的形式。 2. 源码安装最容易卡在哪? —— 编译器、依赖库和环境配置,而不是编译本身。 3. Python 的字节码是什么性质? —— 给解释器看的中间产物,不是本机代码,因此跨 CPU 仍然可用。

相关笔记