当实际构建1个 Python 项目时,模块与包是我们面临的基础概念。
1、模块、包的概念
Python中的模块(Module), 就是一个单独的.py文件,其中包含变量定义,函数定义、类定义、以及其它可执行语句。模块是一个独立的代码单元,可以用解释器直接运行,可以导入到其他模块中。
另一方面,包是一个目录中所包含的模块集合。包允许我们将多个相关模块组合在一个公共命名空间下,从而更容易组织和构建我们的代码库。
将代码分解为模块和包可以带来巨大的好处:
- 可维护性。将代码分解为模块,有助于我们对整个应用程序的独立部分进行更改,而不会影响整个应用程序,因为模块的设计仅用于处理应用程序的一部分。
- 可重复使用性。这是软件开发的关键部分,我们只需编写一次代码,就可以根据需要在应用程序的许多不同部分中多次使用它。这使我们能够编写干净、简洁的代码。
- 方便分工合作。模块化代码,团队的不同开发者可以分别承担同一应用程序的不同部分(模块),而不会相互干扰。
- 可读性。将代码分解为模块和包可以提高代码的可读性。可以很容易地分辨出文件中不同代码的功能。例如,我们可能有一个名为databaseConnection. py的文件:仅从名称上我们就可以知道这个文件处理数据库连接。
2、模块详解
模块包含可执行语句及函数定义。这些语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行。 (文件作为脚本运行时,也会执行这些语句。)
每个模块都有自己的私有命名空间,它会被用作模块中定义的所有函数的全局命名空间。 因此,模块作者可以在模块内使用全局变量而不必担心与用户的全局变量发生意外冲突。 另一方面,如果你知道要怎么做就可以通过与引用模块函数一样的标记法 modname.itemname 来访问一个模块的全局变量。
2.1 创建模块的示例
打开IDE或文本编辑器,创建一个文件,将其命名为sample. py并输入以下代码:
# sample.py
# create a variable in the module
sample_variable = "This is a string variable in the sample.py module"
# A function in the module
def say_hello(name):
return f"Hello, {name} welcome to this simple module."
# This is another function in the module
def add(a, b):
return f"{a} + {b} is = {a+b}"
print(sample_variable)
print(say_hello("小明"))
print(add(2, 3))
上面的代码定义了一个名为sample. py的模块。它包含一个名为sample_variable的变量,其值是字符串“This is a string variable in the sample.py module”。此模块还包含两个函数定义。调用时,say_hello ()函数接收一个名称参数,如果我们将一个名称传递给它,它会返回一个欢迎消息。add ()函数返回传递给它的两个数字的和。
虽然模块是用于程序或应用程序的其他部分的,但我们可以单独运行它们。要运行此模块,我们需要在开发环境中安装Python。我们可以使用以下命令在终端上运行它:
python sample.py
或者
python3 sameple.py
运行结果
This is a string variable in the sample.py module
Hello, 小明 welcome to this simple module.
2 + 3 is = 5
我们可以将其作为独立模块运行,但大多数使用场景下,1个模块通常是导入其他模块或Python 主程序来使用的。因此,要在另一个模块中使用一个模块中的变量、函数和类,我们必须导入该模块。有不同的方法来导入模块,所以让我们来看看如何导入模块
2.2 import 语句
用import module_name 可将另1个模块内容导入到本模块中。如在 another_module.py中使用 import sample
# another_module.py
import sample
print(sample.sample_variable)
print(sample.say_hello(“John”))
print(sample.add(2, 3))
上面的代码展示了如何从sample.py模块导入函数,使它们可以在another_module.py中使用。注意,当导入模块时,不需要包括.py扩展名
2.3 使用 from … import … 语句
还可以使用from关键字来导入特定的函数或变量。假设一个模块中定义了大量的函数和变量,我们不想全部使用它们。可以使用from关键字指定要使用的函数或变量:
# another_module.py
from sample import add
print(add(10, 4))
上面的代码表明,我们已经从示例模块中专门导入了add()函数。
使用from关键字的另一个好处是,使用导入的函数时,无需对其进行命名或在其前面加上其父模块的名称。这将导致代码更加简洁易读。
2.4 使用 as 关键字
我们可以使用“as”为模块提供别名或备用名称。
有时,我们可能会定义相当长或不可读的模块名称。Python提供了一种为模块导入提供别名的方法,为此,我们将使用as关键字:
# another_module.py
import sample as sp
result = sp.add(5, 5)
print(result)
print(sp.say_hello("Jason"))
这段代码显示了样本模块的导入,其中模块被赋予别名sp
。使用sp与调用sample 完全相同。同样可以访问变量和函数。
使用上述三种方法,我们可以在另一个模块中使用一个模块的变量或函数,从而增强了应用程序的可读性,因为我们不需要将代码放在一个文件中。
在命名模块名称时,最好使用小写字母,两个词之间使用_
下列线分隔。例如,有一个用于处理数据库连接的模块,可以将其命名为database_connection.py。此外,请记住Python中的名称区分大小写,因此在导入时请确保使用正确的模块名称。
总的来说,使用模块,可以让我们以可读和可维护的方式创建和组织代码。
包的介绍
Python中的包是将相关模块组织到目录中的一种方式。它提供了一种更好的代码组织方式,通常对于完成同1功能,或属于同一组件的模块使用包来进行分组。
包是通过使用“.”点号来表示同1个包、模块、函数(全局变量)的层级关系。例如,模块名称A.B指定了名为A的包中名为B的子模块。
1) Package包, Module模块与文件的关系
Package(包), Module(模块), file(文件) 三者关系,
- Package由模块组成,相当于Modules 的命名空间
- Module, 包含功能代码的.py 代码文件也称为 module , 但不能把
config.py , __init__.py
称为模块。
2) 包与目录的关系
虽然在形式上,可以把1个包理解为1个目录,但并非是包含代码的目录都是包,
二者区分的关键是, 包目录包含 __init__.py
文件,不包含此文件的不能称之为包目录。
Package可以包含 sub package, 但其目录下也必须有__init__.py
使用时,用点号来表示层次关系
mypkg.mymodule.func_1()
3) 导入包,模块, 函数
对于当前项目 project_demo 来说,要导入的包 mypkg 是依赖库。必须要告知 mypkg 的路径。
如 sys.path.append(“d:/workplace/project_demo/mypkg”),否则导入包时可能会遇到一些问题。
示例:
from mypkg import mymodule
import mypkg.mymodule
from mypkg.mymodule import *
from mypkg.mymodule import func_1
二级结构的包,如何导入子包。
当项目 sound 包下面还有多个子包: filters, effects, formats 等子包。
绝对引用:
模块 sound.filters.vocoder需要使用 sound.effects 子包下的echo module, 这样引用:
from sound.effects import echo
相对引用
from . import echo 表示导入当前包下面的echo模块
from … import formats 表示从父目录下导入 formats 子包。
模块搜索路径
导入名为exam的模块时,解释器首先搜索具有该名称的内置模块。这些模块名称列在sys.builtin_module_names中。如果找不到,它将在变量sys.path给定的目录列表中搜索名为spam.py的文件。sys.path从以下位置初始化:
- 被命令行直接运行的.py脚本所在的目录(或未指定文件时的当前目录)。
- PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。
- 依赖于安装的默认值(按照惯例包括一个 site-packages 目录,由 site 模块处理)。
>>> import sys
>>> sys.path
['',
'C:\\opt\\Python36\\python36.zip',
'C:\\opt\\Python36\\DLLs',
'C:\\opt\\Python36\\lib',
'C:\\opt\\Python36',
'C:\\Users\\NanoDano\\AppData\\Roaming\\Python\\Python36\\site-packages',
'C:\\opt\\Python36\\lib\\site-packages',
'C:\\opt\\Python36\\lib\\site-packages\\win32',
'C:\\opt\\Python36\\lib\\site-packages\\win32\\lib',
'C:\\opt\\Python36\\lib\\site-packages\\Pythonwin']
更改sys.path的3种方式:
(1) appending a path
sys.path.append(``'C:/Users/Vanshi/Desktop'``)
(2) sys.path 初始化时会读python的系统变量 PYTHONPATH 。可以在启动脚本中修改PYTHONPATH, 语法与 环境变量path相同
set PYTHONPATH=C:\pypath1\;C:\pypath2\
python -c "import sys; print(sys.path)"
# Example output
['', 'C:\\pypath1', 'C:\\pypath2', 'C:\\opt\\Python36\\python36.zip', 'C:\\opt\\Python36\\DLL
set 变量名=值 是临时添加,关闭terminal 后则失效。
永久性添加可修改环境变量, 应小心使用
setx ENV_NAME env_value,
如:
setx -m PATH “%PATH%;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin”
Linux中添加环境变量命令
export PYTHONPATH=‘/some/extra/path’
(3) 使用site模块来修改sys.path
在程序代码中修改sys.path 变量, 这样系统启动时加载它,就可以找到相应模块了。
import site
import sys
site.addsitedir('/the/path') # Always appends to end
print(sys.path)