Python加载模块详解(2种方式)
编程其实并不难,就是用合适的语法告诉计算机,让它帮助完成某个工作。因此计算机能完成的事情,其实都是程序员预先告诉它的。
为了让 Python 能找到我们编写(或第三方提供) 的模块,可以用以下两种方式来告诉它:- 使用环境变量。
- 将模块放在默认的模块加载路径下。
下面详细介绍这两种方式。
使用环境变量
Python 将会根据 PYTHONPATH 环境变量的值来确定到哪里去加载模块。PYTHONPATH 环境变量的值是多个路径的集合,这样 Python 就会依次搜索 PYTHONPATH 环境变量所指定的多个路径,试图从中找到程序想要加载的模块。下面介绍在不同平台上设置环境变量的方式。
在 Windows 平台上设置环境变量
右击桌面上的“计算机”图标,出现右键菜单;单击“属性”菜单项,系统显示“控制面板\所有控制面板项\系统”窗口,单击该窗口左边栏中的“高级系统设置”链接,出现“系统属性”对话框,如图 1 所示。图 1 系统属性对话框
单击该对话框中“高级” Tab 页中的“环境变量”按钮,将看到如图 2 所示的“环境变量”对话框,通过该对话框可以添加或修改环境变量。
图 2 环境变量对话框
在如图 2 所示的对话框中,上面的“用户变量”部分用于设置当前用户的环境变量,下面的“系统变量”部分用于设置整个系统的环境变量。
一般建议设置“用户变量”即可,因为用户变量只对当前用户有效,而系统变量对所有用户有效。为了减少自己所做的修改对其他人的影响,故设置用户变量。对于当前用户而言,设置用户变量和系统变量的效果大致相同,不过系统变量的路径排在用户变量的路径之前。
单击用户变量中的“新建”按钮, 系统显示如图 3 所示的对话框。
图 3 新建PYTHONPATH环境变量
在“变量名”文本框内输入 PYTHONPATH,表明将要建立名为 PYTHONPATH 的环境变量;在“变量值”文本框内输入
.;d:\python_ module
,这就是该环境变量的值,该值其实包含了两条路径(分号为分隔符):
- 第一条路径为一个点(.),这个点代表当前路径,表明当运行 Python 程序时,Python 总能从当前路径加载模块;
-
第二条路径为
d:\python_ module
,表明当运行 Python 程序时,Python 总能从d:\python_ module
加载模块。
在成功设置了上面的环境变量之后,接下来只要把前面定义的模块(Python 程序)放在与当前所运行 Python 程序相同的路径中(或放在
d:\python_ module
路径下),该模块就能被成功加载了。在 Linux 上设置环境变量
启动 Linux 的终端窗口(命令行界面),进入当前用户的 home 路径下,然后在 home 路径下输入如下命令:ls - a
该命令将列出当前路径下所有的文件,包括隐藏文件。Linux 平台的环境变量是通过 .bash_profile 文件来设置的,使用无格式编辑器打开该文件,在该文件中添加 PYTHONPATH 环境变量。也就是为该文件增加如下一行:
#设置PYTHON PATH 环境变量
PYTHONPATH=.:/home/yeeku/python_module
/home/yeeku/python_module
(yeeku 是在 Linux 系统的登录名)。在完成了 PYTHONPATH 变量值的设置后,在 .bash_profile 文件的最后添加导出 PYTHONPATH 变量的语句。
#导出PYTHONPATH 环境变量
export PYTHONPATH
source .bash_profile
这两种方式都是为了运行该文件,使在文件中设置的 PYTHONPATH 变量值生效。在成功设置了上面的环境变量之后,接下来只要把前面定义的模块(Python 程序)放在与当前所运行 Python 程序相同的路径中(或放在
/home/yeeku/python_module
路径下),该模块就能被成功加载了。在Mac OS X 上设置环境变量
在 Mac OS X 上设置环境变量与 Linux 大致相同(因为 Mac OS X 本身也是类 UNIX 系统)。启动 Mac OS X 的终端窗口(命令行界面),进入当前用户的 home 路径下,然后在 home 路径下输入如下命令:ls -a
该命令将列出当前路径下所有的文件,包括隐藏文件。Mac OS X 平台的环境变量也可通过,bash_profile 文件来设置,使用无格式编辑器打开该文件,在该文件中添加 PYTHONPATH 环境变量。也就是为该文件增加如下一行:
#设置PYTHON PATH 环境变盘
PYTHONPATH=.:/Users/yeeku/python_module
/Users/yeeku/python_module
(yeeku 是作者在 Mac OS X 系统的登录名)。在完成了 PYTHONPATH 变量值的设置后,在 .bash_profile 文件的最后添加导出 PYTHONPATH 变量的语句。
#导出PYTHON PATH 环境变量
export PYTHONPATH
source .bash_profile
这两种方式都是为了运行该文件,使在文件中设置的 PYTHON PATH 变量值生效。在成功设置了上面的环境变量之后,接下来只要把前面定义的模块(Python 程序)放在与当前所运行 Python 程序相同的路径中(或放在
Users/yeeku/python_module
路径下),该模块就能被成功加载了。在设置好环境变量之后,下面编写一个程序来导入、使用前面定义的 module1 模块:
# 两次导入module1,并指定其别名为md import module1 as md import module1 as md print(md.my_book) md.say_hi('Charlie') user = md.User('孙悟空') print(user) user.walk()该程序位于
codes\09\9.2\
目录下,因此需要将前面的 module1.py 文件也拷贝到该目录下。上面代码中两次导入了 module1 模块,运行该程序,可以看到如下输出结果:
这是module 1
Python入门教程
Charlie,您好,欢迎学习Python
User[name=孙悟空]
孙悟空正在慢慢地走路
这里为什么要两次导入 module1 模块呢?其实完全没必要,此处两次导入只是为了说明一点:Python 很智能。虽然上面程序两次导入了 module1 模块,但最后运行程序,我们看到输出语句只输出一条“这是 module 1”,这说明第二次导入的 module1 模块并没有起作用,这就是 Python 的“智能”之处。
当程序重复导入同一个模块时,Python 只会导入一次。道理很简单,因为这些变量、函数、类等程序单元都只需要定义一次即可,何必导入多次呢?
相反,如果 Python 允许导入多次, 反而可能会导致严重的后果。比如程序定义了 foo 和 bar 两个模块,假如 foo 模块导入了 bar 模块,而 bar 模块又导入了 foo 模块,这似乎形成了无限循环导入,但由于 Python 只会导入一次,所以这个无限循环导入的问题完全可以避免。
默认的模块加载路径
如果要安装某些通用性模块,比如复数功能支持的模块、矩阵计算支持的模块、图形界面支持的模块等,这些都属于对 Python 本身进行扩展的模块,这种模块应该直接安装在 Python 内部,以便被所有程序共享,此时就可借助于 Python 默认的模块加载路径。Python 默认的模块加载路径由 sys.path 变量代表,因此可通过在交互式解释器中执行如下命令来查看 Python 默认的模块加载路径:
['C:\\Users\\mengma\\Desktop',
'D:\\python3.6\\Lib\\idlelib',
'D:\\python3.6\\python36.zip',
'D:\\python3.6\\DLLs',
'D:\\python3.6\\lib',
'D:\\python3.6',
'C:\\Users\\mengma\\AppData\\Roaming\\Python\\Python36\\site-packages',
'D:\\python3.6\\lib\\site-packages']
上面的运行结果就是 Python 3.x 默认的模块加载路径,这是因为作者将 Python 安装在了 d:\Python 路径下。如果将 Python 安装在其他路径下,上面的运行结果应该略有差异。
上面的运行结果列出的路径都是 Python 默认的模块加载路径,但通常来说,我们应该将 Python 的扩展模块添加在lib\site-packages
路径下,它专门用于存放 Python 的扩展模块和包。如果读者前面安装过矩阵计算支持的模块,则可以在
lib\site-packages
下找到一个 numpy 文件夹,这说明前面安装的 numpy 模块也是被放在 lib\site-packages
路径下的。下面编写一个 Python 模块文件,并将该文件复制在
lib\site-packages
路径下:
''' 简单的模块,该模块包含以下内容 my_list:保存列表的变量 print_triangle: 使用星号打印三角形的函数 ''' my_list = ['Python', 'Kotlin', 'Swift'] def print_triangle(n): '''使用星号打印一个三角形''' if n <= 0: raise ValueError('n必须大于0') for i in range(n): print(' ' * (n - i - 1), end='') print('*' * (2 * i + 1), end='') print('') # ====以下是测试代码==== def test_print_triangle(): print_triangle(3) print_triangle(4) print_triangle(7) if __name__ == '__main__': test_print_triangle()上面模块文件中定义了一个 print_triangle() 函数,把该模块文件拷贝到
lib\site-packages
路径下,就相当于为 Python 扩展了一个 print_ shape 模块,这样任何 Python 程序都可使用该模块。下面可直接在 Python 交互式解释器中测试该模块。在 Python 交互式解释器中输入如下命令:
>>> import print_shape
>>> print(print_shape,__doc__)
简单的模块,该模块包含以下内容
my_list:保存列表的变量
print_triangle:使用星号打印三角形的函数
>>> print_shape.print triangle.__doc__
'使用星号打印一个三角形'
接下来测试该模块中的 my_list 变量和 print_triangle() 函数。在交互式解释器中输入如下命令:
>>> print_shape.my_list[1]
'Kotlin'
>>> print_shape.print_triangle(4)
*
***
*****
*******
导入模块的本质
为了帮助大家更好地理解导入模块,下面定义一个新的模块,该模块比较简单,所以不再为之编写测试代码。该模块代码如下(编写在 fk_module.py 文件中):'一个简单的测试模块: fkmodule' print("this is fk_module") name = 'fkit' def hello(): print("Hello, Python") 接下来,在相同的路径下定义如下程序来使用该模块: import fk_module print("================") # 打印fk_module的类型 print(type(fk_module)) print(fk_module)由于前面在 PYTHONPATH 环境变量中已经添加了点(.),因此 Python 程序总可以加载相同路径下的模块。所以,上面程序可以导入相同路径下的 fk_module 模块。运行上面程序,可以看到如下输出结果:
this is fk_module
================
<class 'module'>
<module 'fk_module' from 'G:\\publish\\codes\\09\\9.2\\fk_module.py'>
fkit
<function hello at 0x0000000001EABAE8>
使用“import fk_module”导入模块的本质就是,将 fk_module.py 中的全部代码加载到内存并执行,然后将整个模块内容赋值给与模块同名的变量,该变量的类型是 module,而在该模块中定义的所有程序单元都相当于该 module 对象的成员。
下面再试试使用
from...import
语句来执行导入,例如使用如下程序来测试该模块:
from fk_module import name, hello print("================") print(name) print(hello) # 打印fk_module print(fk_module)运行上面程序,可以看到如下输出结果:
this is fk_module
================
fkit
<function hello at 0x0000000001E7BAE8>
Traceback (most recent call last):
File "fk_module_test2.py", line 22, in <module>
print(fk_module)
NameError: name 'fk_module' is not defined
from...import
只导入模块中部分成员,该模块中的输出语句也会在 import 时自动执行,这说明 Python 依然会加载并执行模块中的代码。使用“from fk_module import name, hello”导入模块中成员的本质就是将 fk_module.py 中的全部代码加载到内存并执行,然后只导入指定变量、函数等成员单元,并不会将整个模块导入,因此上面程序在输出 fk_module 时将看到错误提示:
name 'fk module' is not defined
。在导入模块后,可以在模块文件所在目录下看到一个名为“__pycache__”的文件夹,打开该文件夹,可以看到 Python 为每个模块都生成一个 *.cpython-36.pyc 文件,比如 Python 为 fk_module 模块生成一个 fk_ module.cpython-36.pyc 文件,该文件其实是 Python 为模块编译生成的字节码,用于提升该模块的运行效率。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算