DAY 30 模块和库的导入

今天聊模块和库的导入。这玩意儿刚开始学的时候觉得挺简单,真正用起来才发现到处都是坑------尤其是那个路径问题,简直能把人搞疯。

一、先说清楚几个概念

模块 就是一个.py文件,比如你写了个utils.py,里面放了一些常用的函数,这个文件就是一个模块。

其实就是个文件夹,里面放了一堆模块,还得有个__init__.py文件(就算它是空的也行)。比如你建了个tools文件夹,里面放了calculator.pyvalidator.py,那tools就是个包。

标准库 是Python自带的,比如ossys这些,不用安装就能用。

第三方库 得用pip安装,比如requestspandas这些。

二、三种导入方式,到底用哪个?

1. 最老实的写法

复制代码
import math
result = math.sqrt(16)

这么写的好处是清楚------一看就知道sqrt是从math来的,不会跟别的函数搞混。缺点是写起来有点啰嗦。

2. 直接拿过来用

复制代码
from math import sqrt, pi
result = sqrt(16)

这样写代码清爽多了,但有风险------万一你别的文件里也有个sqrt函数,那就冲突了。我吃过这个亏,调试了半天才发现是命名冲突。

3. 起个小名

复制代码
import numpy as np
import pandas as pd

这已经是行业惯例了。尤其是做数据分析的,没人会写numpy.array(),都是np.array()。代码短了,还不会冲突。

三、自定义模块导入的坑

场景1:同一个文件夹里

复制代码
我的项目/
├── main.py
└── utils.py

这种情况最简单:

复制代码
# main.py里直接写
import utils

搞定。

场景2:模块在子文件夹里

复制代码
我的项目/
├── main.py
└── 工具集/
    ├── __init__.py
    └── 计算器.py

这时候你得:

复制代码
from 工具集 import 计算器
# 或者
import 工具集.计算器

注意那个__init__.py文件必须有,哪怕是空的。这是Python识别"这是个包"的标志。

场景3:想从上级目录导入(这个最坑!)

假设你的目录结构是这样的:

复制代码
项目根目录/
├── 配置/
│   └── config.py
└── 源代码/
    └── main.py

你在main.py里想用config.py,直接导入肯定报错。得这么搞:

复制代码
import sys
import os

# 先把上级目录加到Python的搜索路径里
sys.path.append(os.path.dirname(os.path.dirname(__file__)))

from 配置 import config

每次看到这种代码都觉得挺丑陋的,但没办法,Python就是这么找模块的。

四、Python到底怎么找模块?

你可以在代码里打印一下:

复制代码
import sys
print(sys.path)

你会看到一个列表,Python就按这个顺序找模块:

  1. 先找当前脚本所在的目录
  2. 再找环境变量PYTHONPATH设置的路径
  3. 然后找Python安装目录下的标准库
  4. 最后找第三方库(通常都在site-packages里)

关键问题来了 :Python解释器认为的"当前目录",跟你命令行里pwd看到的可能不一样!这就是很多导入错误的根源。

比如你在/home/user/project里执行:

复制代码
cd /home/user
python project/main.py

Python会认为当前目录是/home/user,不是/home/user/project。所以如果你的模块在project文件夹里,它就找不到了。

五、几个实用技巧

1. 导入顺序有讲究

我习惯这么排:

复制代码
# 1. 标准库
import os
import sys

# 2. 第三方库  
import requests
import pandas as pd

# 3. 自己的模块
from mytools import utils

这样代码看起来清楚,也容易维护。

2. 避免循环导入

两个文件互相导入,Python就懵了:

复制代码
# a.py
import b  # 导入b

# b.py  
import a  # 又导入a,死循环了!

解决方案要么重新设计代码结构,要么把导入语句放到函数里面去。

3. __init__.py不只是个标记

这个文件可以很有用:

复制代码
# tools/__init__.py
from .calculator import add, multiply
from .validator import is_email

# 这样在外面就可以直接:
from tools import add, is_email
# 而不用:
from tools.calculator import add
from tools.validator import is_email

六、真实项目中的经验

1. 相对导入 vs 绝对导入

在包内部,可以用相对导入:

复制代码
# 在tools/advanced.py里
from .calculator import add  # 从同级目录导入
from ..utils import helper   # 从上级目录导入

但在项目入口文件里(比如main.py),最好用绝对导入:

复制代码
from tools.calculator import add

2. 动态导入

有些特别大的模块,如果一开始就导入,启动会很慢。可以等用到的时候再导:

复制代码
def process_data():
    # 只有调用这个函数时才会导入pandas
    import pandas as pd
    data = pd.read_csv('file.csv')
    # ...

不过别滥用,代码会显得很乱。

七、常见错误和解决

"ModuleNotFoundError: No module named 'xxx'"

这是最常遇到的。先检查:

  • 文件名字拼对了吗?(它对大小写很敏感!)
  • 文件在Python能搜到的路径里吗?
  • 如果是包,有__init__.py吗?

"ImportError: cannot import name 'xxx' from 'yyy'"

可能是:

  • 循环导入了
  • 模块里确实没有这个函数/类
  • 有语法错误导致模块加载失败

"AttributeError: module 'xxx' has no attribute 'yyy'"

通常是:

  • 你写错了函数/类名
  • 导入的模块不对(同名模块?)
相关推荐
TAN-90°-11 分钟前
Deep Learning for Computer Vision——Large Scale Distributed Training
人工智能·深度学习·神经网络·算法·机器学习·计算机视觉·语言模型
ECT-OS-JiuHuaShan38 分钟前
哲学是迭代学,数学是拓扑学
开发语言·人工智能·学习·算法·机器学习·php·拓扑学
维克兜率天1 小时前
【维克】一个极端值,毁掉了整个因子
大数据·人工智能·python·算法·机器学习
船厂电气自动化ai大模型1 小时前
AI大模型与数学 第75课 基、维度、向量空间坐标
数据结构·线性代数·算法·机器学习·推荐算法
找方案13 小时前
AI视频生成对决:Sora vs 可灵 vs Veo,谁能定义未来
人工智能·机器学习·音视频
面朝大海,春不暖,花不开19 小时前
Buat New Trenches, Kalian Bisa Baca Panduan Meta Ini
人工智能·机器学习
VL——MOESR21 小时前
【具身智能】Cosmos Policy论文阅读随笔
论文阅读·人工智能·机器学习·具身智能·cosmospolicy
haon11221 天前
树模型在信贷风控怎么用——从决策树到 XGBoost
大数据·人工智能·算法·决策树·机器学习·数据挖掘
阳明山水1 天前
从相关到因果:预测科学的因果转向与可识别性挑战
人工智能·深度学习·算法·机器学习·架构
宣宣猪的小花园.1 天前
【嵌入式】故障与降级:看门狗、保护机制和工程可靠性的底线
开发语言·人工智能·嵌入式硬件·机器学习