Python包导入指南:从菜鸟到专家的import魔法
Python包导入指南:从菜鸟到专家的import魔法
对话实录
小白:(崩溃)我装了包却ImportError,救命!
专家:(掏出魔法书)掌握包导入功能,告别导入噩梦!
import导入基础三连击
概念
解释
import
即导入,就是在import的位置将代码文件拷贝过去。
模块(module)
python中一个.py文件定义为一个模块。
常用的几种模块导入方式:
import module_name
import module_name.function_nameimport module_name.class_name
from module_name import *
from module_name import func_name,class_name
from module_name import *
包(package)
指软件包,包含__init__.py、modules、及子目录等。
常用的几种导入方式:
import package_name
import package_name as p
import package.module
import package.module as pm
from package.module import *
from package import module1, module2, module3, ... ...
from package import *
包的导入和模块导入基本一致,只不过导入包时会先执行包内的__init__.py。如果只是导入一个包import package而不指定导入任何模块,且包中的__init__.py文件中没有定义其他的初始化操作,那么包下面的模块是无法被自动导入的。
Import导入时搜索路径
装载module代码时python解释器需要先搜索到对应的.py文件,搜索顺序为:
搜索内存中sys.modules中已经加载好的模块搜索python的内置模块搜索sys.path路径中的python模块和包
sys.path:包含了当前脚本的路径和其他查找包(系统库、第三方库等)的路径,我们也可以在代码中通过sys.path.append()动态添加需要的搜索路径PYTHONPATH:查看默认路径,比如Linux下为/usr/local/lib/python/
实战案例
为了形象地解释,建一个test文件夹,其中文件夹A和B的目录结构,如下:
案例1 在A_B.py中定义__all__用来模糊导入from moduleA import *
专家:python文件中设置了 __all__ 的值,那么则按照 __all__ 指定的子包或者模块进行加载。
示例:定义A_B.py文件,__all__中增加A_B 和C_D函数,不包含E_F函数
在A目录的__init__.py中通过from A_B import *时,E_F函数并不会被导入,上述执行后会报错
案例2 配置sys.path,在B文件夹的run.py文件下导入A包中的模块。
在run.py中import A,并执行run.py,发现报错如下:
问题:上面的例子中__init__.py文件执行时不报错,而在B文件夹执行run.py就会报错找不到A_B模块,
原因:执行python文件时在本目录下,或者在搜索路径中并未找到A_B模块,所以报错。
解决:在run.py中将A目录增加到sys.path中,执行正常
import sys
sys.path.append("/Volumes/UNTITLED/test/A")
import A
执行结果:
开始导入A_B模块
使用A_B函数
使用E_F函数
案例 3:相对导入(包内)
在一个 Python 包内部,我们可以使用相对导入来引用其他模块。假设项目结构如下:
mypackage/
├── __init__.py
├── utils.py
└── core.py
在core.py中,可以这样导入utils.py:
# 从当前目录导入utils模块
from . import utils
# 从上级目录的subpkg目录导入tools模块
from ..subpkg import tools
案例 4:条件导入
当我们希望使用某个高性能模块,但该模块可能未安装时,可以采用条件导入。
try:
# 尝试导入rapidjson,它比标准json模块更快
import rapidjson as json
except ImportError:
# 如果导入失败,使用标准json模块作为回退方案
import json
案例 5:动态导入
在某些情况下,我们需要在运行时动态决定导入哪个模块,这时可以使用__import__函数。
module_name = "os"
module = __import__(module_name)
print(module.path.exists("/"))
血泪陷阱
循环导入
循环导入是指两个或多个模块相互导入,这会导致死循环。
# a.py
from b import func
# b.py
from a import other_func # ❌ 形成死循环
命名冲突
当导入的模块或函数具有相同的名称时,会发生命名冲突。
from mylib import sqrt
from math import sqrt # ❌ 后者会覆盖前者
# 正确做法,通过别名区分
import math
from mylib import sqrt as my_sqrt
专家工具箱
1. 虚拟环境管理
虚拟环境是 Python 项目管理的重要工具,以下是常见的虚拟环境操作:
# 创建名为myenv的虚拟环境
python -m venv myenv
# 激活虚拟环境(Linux/Mac)
source myenv/bin/activate
# 激活虚拟环境(Windows)
myenv\Scripts\activate
2. 依赖管理
在项目开发过程中,我们需要记录项目的依赖关系,以便在其他环境中安装相同的包。
# 生成requirements.txt文件,记录当前环境中安装的所有包及其版本
pip freeze > requirements.txt
# 从requirements.txt文件中安装所有依赖包
pip install -r requirements.txt
小白:(献上键盘)原来包导入这么讲究
专家:(扶起小白)记住:好的包管理是项目成功的一半!
常用命令清单
pip list:查看已安装的包
pip show:查看包的详细信息
pip uninstall:卸载包
python -m site:查看包的搜索路径