【Python基础】模块

从实际的角度来看,模块往往对应于Python程序文件(或是用外部语言如C,Java或C#编写而成的扩展)。每一个文件都是一个模块,并且模块导入其他模块之后就可以使用导入模块定义的变量名。

模块可以由两个语句和一个重要的内置函数进行处理:

  • import —— 使导入者以一个整体获取一个模块
  • from —— 允许导入者从一个模块文件中获取特定的变量名
  • imp.reload —— 在不终止Python程序的情况下,提供了一种重新载入模块文件代码的方法

模块

在模块顶层指定的所有变量名都会变成其属性,并且可以导出供客户端来使用。

因为模块名在Python程序中会编程变量名(没有.py),因此,应该遵循普通变量名的命名规则。

当一个模块被导入时,Python会把内部模块名映射到外部文件名。

客户端可以执行import和from语句:import会读取整个模块,from将获取模块特定的变量名


标准库模块


import语句

程序第一次导入指定文件时,会执行三个步骤:

  1. 找到模块文件
  2. 编译成位码(需要时)
  3. 执行模块的代码来创建其所定义的对象

这三个步骤只在程序执行时,模块第一次导入时才会进行。在这之后,导入相同模块时,会跳过这三个步骤,而只提取内存中已加载的模块对象。从技术上讲,Python把载入的模块存储到一个名为sys,modules的表中,并在一次导入操作的开始检查该表。如果模块不存在,将会启动一个三个步骤的过程。

搜索

首先,Python必须查找到import语句所引用的模块文件。在标准的import中引入路径和后缀名等细节,从语法上讲是非法的,只能列出简单名称,路径和后缀是刻意省略的。

编译(可选)

导入之后,Python会检查文件的时间戳,如果发现字节码文件比源代码文件旧,就会在程序运行时自动重新生成字节代码。另一方面,如果发现.pyc字节码问价不比对应的.py源代码文件旧,就会跳过源代码到字节码的编译步骤。此外,如果Python在搜索路径上只发现了字节码文件,而没有源代码,就会直接加载字节码。

当文件导入时,就会进行编译。因此,通常不会看见程序顶层文件的.pyc字节码文件,除非这个文件也被其他文件导入:只有被导入的文件才会在机器上留下.pyc。顶层文件的字节码是在内部使用后就丢弃了。

运行

import模块的最后步骤是执行模块的字节码。文件中的所有语句都会依次执行。


模块变量名有两个不同目的:识别要被载入的外部文件,同时会生成脚本中的变量,在文件加载后,用来引用模块对象。

因为import使一个变量名引用整个模块对象,必须通过模块名称来得到该模块的属性。


from语句

from会把变量名复制到另一个作用域,所以它就可以让我们直接在脚本中使用复制后的变量名,而不需要通过模块:

>>>from module1 import printer
>>>printer('Hello world!')


我们可以直接使用变量名,而无须在嵌套模块名称之后。

from语句其实只是稍稍扩展了import语句而已,它照常导入了模块文件,但是多了一个步骤,将文件中的一个或多个变量名从文件中复制了出来。


from * 语句

当使用*时,会取得模块顶层所有赋了值的变量名的拷贝:

>>>from module1 import *
>>>printer('Hello world!')

import和from是赋值语句

就像def一样,import和from是可执行的语句,而不是编译期间的声明,而且它们可以嵌套在if测试中,出现在函数def之中等,直到执行程序时,Python执行到这些语句才会进行解析。

import和from都是隐形的赋值语句:

  • import将整个模块对象赋值给一个变量名
  • from将一个多个变量名赋值给另一个模块中同名的对象

模块路径

模块搜索路径

  • 程序的主目录

Python首先会在主目录内搜索导入的文件。当你运行一个程序的时候,这个入口是包含程序的顶层脚本文件的目录。当在交互模式下工作时,这一入口就是你当前工作的目录。

由于这个目录是先搜索的,其文件也将覆盖路径上的其他目录中具有同样名称的模块

  • PYTHONPATH目录(如果已经进行了设置)

之后,Python会从左至右搜索PYTHONPATH环境变量设置中罗列出的所有目录。

  • 标准链接库目录

Python会自动搜索标准模块安装在机器上的那些目录,这些通常是不需要添加到PYTHONPATH之中或包含到路径文件中的。

  • 任何.pth文件的内容(如果存在的话)

Python允许用户把有效的目录添加到模块搜索路径中去,也就是在后缀名为.pth的文本文件中一行一行地列出目录。

配置搜索路径

在Windows上,我们可能把PYTHONPATH设置为分号分隔开的一串目录,或者可以创建一个名为C:\Python30\pydirs.pth的文本文件。

sys.path列表

如果想看看模块搜索路径在机器上的实际配置,可以通过打印内置的sys.path列表来查看这个路径。

sys,path是模块搜索的路径,Python在程序启动时进行配置。

>>>import sys
>>>sys.path

模块文件(扩展名)选择

文件的后缀名是刻意从import语句中省略的。Pythin会选择在搜索路径中第一个符合导入文件名的文件。

import b形式的import可能会加载:

  • 源代码文件b.py
  • 字节码文件b.pyc
  • 目录b,包导入
  • 编译扩展模块,导入时使用动态连接
  • 用C编写的编译好的内置模块,并通过静态连接至Python
  • ZIP文件组件,导入时会自动解压缩
  • 内存内映像,对于frozen可执行文件
  • Java类,在Jython版本的Python中
  • .NET组件,在IronPython版本的Python中

对于导入者来说,完全忽略了需要加载的文件类型之间的差异,无论是在导入时或者是在读取模块的属性时都是这样的,客户端不在乎文件是什么。

distutils工具

前面对模块搜索路径设置的说明,主要是针对自己编写的用户定义的源代码。Python的第三方扩展,通常使用标准链接库中的distutils工具来自动安装,所以不需要路径设置,就能使用它们的代码。

使用distutils的系统一般都附带setup.py脚本,执行这个脚本可以进行程序的安装。这个脚本会导入并使用distutils模块,将这种系统发在属于模块自动搜索路径一部分的目录内(通常是在python安装目录下的lib/site-packages子目录中)。


模块命名空间

简而言之,模块就是命名空间,而存在于模块之内的变量名就是模块对象的属性。


重载模块

模块代码默认只对每个过程执行一次。要强制使模块代码重新载入并重新运行,得调用reload内置函数。

reload函数


模块包

除了模块名之外,导入也可以指定目录路径。Python代码的目录就称为包,因此,这类导入就称为包导入。事实上,包导入是把计算机上的目录编程另一个Python命名空间,而属性则对应与目录中所包含的子目录和模块文件。

包导入

在import语句中列举简单文件名的地方,可以改成列出路径的名称,彼此以点号相隔:

import dir1.dir2.mod
from dir1.dir2.mod import x

这些语句中点号路径是对应于机器上目录层次的路径,通过这个路径可以获得到文件mod,py。容器目录dir0 (dir0 \ dir1 \ dir2 \ mod.py)需要添加在模块搜索路径中。

import语句中目录路径只能是以点号间隔的变量,不能在import语句中使用任何平台特定的路径语法。


__init__.py包文件

如果选择使用包导入,就必须多遵循一条约束:包导入的路径中的每个目录内都必须有__init__.py这个文件,否则导入包会失败。也就是说,dir1, dir2内都必须包含__init__.py这个文件,容器目录 dir0不需要这类文件。

也就是说,像这样的目录结构:

dir0 \ dir1 \ dir2 \ mod.py

以及这种形式的import语句:

import dir1.dir2.mod

必须遵循下列规则:

  • dir1和dir2中必须都含有一个__init__.py文件
  • dir0是容器,不需要__init__.py文件,如果有的话,这个文件也会被忽略
  • dir0 必须列在模块搜索路径上


Python首次导入某个目录时,会自动执行该目录下__init__.py文件中的所有程序代码,文件的内容可以为空。


高级模块话题





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值