Python怎么用Pillow读取和显示本地图片
在 Python 中读取和显示一张本地图片,最直接且通用的方案是使用图像处理库 Pillow。只需两行核心代码即可完成基本操作:调用 Image.open() 加载图片文件,再调用 img.show() 调起查看器。然而在实际开发中,开发者常常会遇到导入包名混淆、大文件读取时的内存占用机制、不同系统下图片窗口调用的差异,以及路径相对解析错误等细节问题。本文将按实际操作路径,逐步解析 Pillow 读取与展示本地图片的标准步骤、底层机制与实用避坑技巧。
一、环境准备与模块导入
Pillow 是历史悠久的 PIL(Python Imaging Library)的分支与继任者。由于历史兼容性原因,终端安装命令与 Python 代码导入名称并不相同:安装时使用的包名为 pillow,而在 Python 代码中导入时使用的模块名仍为 PIL。
# 终端安装命令
pip install pillow
在 Python 脚本中,通常只需要导入 Image 模块:
from PIL import Image
完成导入后,整个图片处理的操作链路可以概括为四个清晰的阶段:环境就绪、路径加载、元信息核验与窗口渲染。
二、使用 Image.open() 读取本地图片
读取本地图片的核心接口是 Image.open()。该函数接受一个本地文件路径(可以是字符串形式,也可以是标准库 pathlib.Path 对象)。
推荐的读取范式:上下文管理器
推荐使用 with 语句(上下文管理器)来打开图片。这样可以确保在处理完毕后,Python 能够及时关闭底层文件流,避免因文件未释放而导致的“文件被占用”或句柄泄漏问题:
from PIL import Image
image_path = "sample.jpg"
try:
with Image.open(image_path) as img:
# 获取图片基础元信息
print("图片格式:", img.format) # 例如: JPEG, PNG, BMP
print("图片尺寸:", img.size) # 二元组 (宽度, 高度),单位为像素
print("色彩模式:", img.mode) # 例如: RGB, RGBA, L
# 将像素数据完整装载至内存
img.load()
except FileNotFoundError:
print(f"错误:未找到指定路径的图片文件 -> {image_path}")
except Exception as e:
print(f"打开图片失败: {e}")
理解 Image.open() 的“惰性加载”特性
Pillow 采用惰性加载(Lazy Loading)机制。当执行 Image.open(path) 时,Pillow 并不会立刻将所有像素解压进内存,而仅仅读取文件的头部数据块(Header),以快速获取图像的格式、分辨率和色彩通道等元数据。真正的像素解码会延迟到第一次需要具体像素数据时(如执行裁切、滤镜、旋转、调用 img.load() 或展示输出)。
如果在 with Image.open() as img: 代码块之外还需要继续操作该图片对象,必须在上下文结束前调用 img.load()。否则一旦跳出 with 作用域,文件已被关闭,后续访问未解码的像素数据将会抛出 ValueError: seek of closed file 异常。
三、显示本地图片的两种常用方式
读取到 Image 对象后,展示图片主要有两种路径:使用 Pillow 原生提供的 img.show(),或结合科学绘图库 matplotlib 进行受控窗口展示。
方式一:Pillow 原生自带的 img.show()
这是最省力、无需额外安装第三方依赖的测试方法:
from PIL import Image
img = Image.open("sample.jpg")
img.show()
底层工作原理:img.show() 本身并不在 Python 进程内部绘制任何 GUI 窗口。它的实现方式是将当前图片转换为临时文件(通常存储在系统的临时目录下,格式为 BMP、PNG 或 PPM),然后调用操作系统层面的默认看图软件(例如 macOS 的 Preview、Windows 的照片查看器、Linux 的 ImageMagick 或 xdg-open)来打开该临时文件。
适用场景与边界:
- 适合日常开发阶段快速确认图片内容。
- 属于非阻塞调用,Python 脚本会继续向下执行;如果脚本执行完后立即退出,某些系统下可能会导致刚打开的临时文件被清理或查看器窗口异常退出。
- 服务器无桌面环境(Headless)时无法正常调起窗口。
方式二:结合 Matplotlib 显示图片
当需要更稳定、可定制的展示体验(例如隐藏坐标轴、多图并排对比、在 Jupyter Notebook 内联展示)时,搭配 matplotlib.pyplot 是业界的标准做法:
from PIL import Image
import matplotlib.pyplot as plt
# 读取图片
img = Image.open("sample.jpg")
# 使用 matplotlib 渲染
plt.figure("图片预览")
plt.imshow(img)
plt.axis("off") # 隐藏坐标刻度轴
plt.tight_layout()
plt.show() # 阻塞并弹出受控图形窗口
四、常见问题排查与避坑指南
在实际编码中,很多初学者虽然掌握了基础语法,但经常因路径解析、色彩空间或资源未释放导致程序异常。以下是排查与预防这几类问题的具体方法:
1. 路径问题:找不到文件(FileNotFoundError)
直接传入 "image.jpg" 是基于当前终端所在的工作目录(Current Working Directory)进行查找的,而不是 Python 脚本文件所在的目录。当从工程根目录运行子目录脚本时,就会报 FileNotFoundError。
解决办法:使用标准库 pathlib.Path 基于脚本实际位置定位图片,构建绝对路径:
from pathlib import Path
from PIL import Image
# 获取当前脚本所在文件夹的绝对路径
current_dir = Path(__file__).resolve().parent
image_path = current_dir / "assets" / "sample.jpg"
if image_path.exists():
with Image.open(image_path) as img:
img.show()
else:
print(f"文件不存在: {image_path}")
2. 图像未识别错误(UnidentifiedImageError)
当文件后缀名是 .jpg 或 .png,但文件本身损坏,或者其实是一个包含报错信息的纯文本文件(例如从网络下载时返回了 404 HTML)时,Pillow 无法从文件头部提取合法的图像指纹,会抛出 PIL.UnidentifiedImageError。捕获此异常可以有效提升批处理脚本的健壮性。
3. 色彩通道与格式转换陷阱
如果读取的是带 Alpha 透明通道的 PNG 图像(mode="RGBA"),并尝试直接调用 img.save("output.jpg") 保存为 JPEG,Pillow 会直接报错 OSError: cannot write mode RGBA as JPEG。因为 JPEG 格式不支持透明通道。此时必须先做色彩空间转换:
# RGBA 转为 RGB 的安全做法
if img.mode in ("RGBA", "P"):
rgb_img = img.convert("RGB")
rgb_img.save("output.jpg")
五、总结
通过 Pillow 读取并显示本地图片是一项基础但极其高频的操作。要写出高效、稳定的代码,记住以下几条核心要点即可:
- 安装与导入:安装使用
pip install pillow,导入使用from PIL import Image。 - 安全读取:使用
with Image.open(path) as img:管理文件句柄,避免资源泄漏。 - 惰性加载认知:
Image.open()仅瞬时读取文件头,需长期持有数据或跨作用域时调用img.load()。 - 灵活展示:快速查看使用
img.show();需要精细控制窗口、隐藏坐标或数据可视化交互时,结合matplotlib.pyplot.imshow()。 - 稳妥路径:优先通过
pathlib.Path(__file__).parent构造相对脚本的稳固路径,防范FileNotFoundError。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









