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'"

通常是:

  • 你写错了函数/类名
  • 导入的模块不对(同名模块?)
相关推荐
白日做梦Q2 小时前
深度学习与机器学习的3个关键区别
人工智能·深度学习·机器学习
free-elcmacom2 小时前
机器学习入门<6>BP神经网络揭秘:从自行车摔跤到吃一堑长一智的AI智慧
人工智能·python·深度学习·神经网络·机器学习
代码输入中...2 小时前
大模型项目实战:多领域智能应用开发
人工智能·机器学习·ai编程
TextIn智能文档云平台3 小时前
怎么批量将扫描件变成文档?
人工智能·机器学习
xiaozi41205 小时前
Ruey S. Tsay《时间序列分析》Python实现笔记:综合与应用
开发语言·笔记·python·机器学习
黎茗Dawn5 小时前
DDPM-KL 散度与 L2 损失
人工智能·算法·机器学习
老欧学视觉6 小时前
0013机器学习聚类算法(无监督算法)
算法·机器学习·聚类
Maxwell_li16 小时前
pandas数据合并
机器学习·数据分析·numpy·pandas·matplotlib
小白狮ww7 小时前
lammps 教程:npt 控温估计 FCC Cu 熔点
人工智能·深度学习·机器学习·分子动力学·lammps·npt·材料建模