Python包导入指南:从菜鸟到专家的import魔法

liftword3周前 (04-09)技术文章3

对话实录

小白:(崩溃)我装了包却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文件,搜索顺序为:

  1. 搜索内存中sys.modules中已经加载好的模块
  2. 搜索python的内置模块
  3. 搜索sys.path路径中的python模块和包
  • sys.path:包含了当前脚本的路径和其他查找包(系统库、第三方库等)的路径,我们也可以在代码中通过sys.path.append()动态添加需要的搜索路径
  • PYTHONPATH:查看默认路径,比如Linux下为/usr/local/lib/python/

实战案例

为了形象地解释,建一个test文件夹,其中文件夹AB的目录结构,如下:

案例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

隐藏的 pip 缓存

pip会缓存已下载的包,这可能导致安装旧版本的包。

# 错误示范,可能安装缓存中的旧版本包
pip install package

# 正确做法,禁止使用缓存并升级包
pip install --no-cache-dir --upgrade package

专家工具箱

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:查看包的搜索路径

(此处已添加书籍卡片,请到今日头条客户端查看)

相关文章

了解 Python 最常见的内置函数

Python 的内置函数基础Python 的内置函数是该语言不可或缺的一部分,无需额外的库即可提供基本功能。这些函数始终可用,无需导入任何模块即可使用。它们是在 C for CPython(标准 Py...

8-Python内置函数

Python 提供了丰富的内置函数,这些函数可以直接使用而无需导入任何模块。以下是一些常用的内置函数及其示例:1-print()1-1-说明输出指定的信息到控制台。1-2-例子2-len()2-1-说...

Python用内置模块来构建REST服务、RPC服务

1写在前面和小伙伴们分享一些Python 网络编程的一些笔记,博文为《Python Cookbook》读书后笔记整理博文涉及内容包括: TCP/UDP服务构建 不使用框架创建一个REST风格的HTTP...

一文掌握Python 内置数据结构

列表Python 没有数组数据结构(大小固定),相反,它有一个列表数据结构,它是一个动态数组,可以存储混合数据类型的值。与传统数组相比,它具有优势,例如不必指定大小和混合数据类型。当创建列表时,内部会...

这就是Python 模块

1. 模块简介1.1 什么是模块编写较长程序时,建议用文本编辑器代替解释器,执行文件中的输入内容,这就是编写 脚本 。随着程序越来越长,为了方便维护,最好把脚本拆分成多个文件。编写脚本还一个好处,不同...

Python常用的内置函数介绍

Python提供了许多内置函数,这些函数可以直接使用而无需导入任何模块。下面是一些常用的Python内置函数的介绍:1. `print()`用于将指定的内容输出到控制台。可以打印文本、变量、表达式等。...