Python批量打印文件夹内的所有图片
详细介绍使用Python批量打印文件夹内所有图片的两种高效方案:Windows原生接口调用与跨平台多页PDF统一排版打印,包含自然排序、比例缩放、白边留白与打印队列防卡死完整代码与排错方法。
一、准备工作:图片检索与自然排序
实现批量打印的第一步是准确获取指定文件夹中的所有图片路径。在实际场景中,文件夹往往包含不同格式(如 .jpg、.png、.bmp、.webp)以及大小写不一的扩展名。同时,操作系统对文件名的排序规则默认为字符字典序,这会导致类似 "1.jpg"、"10.jpg"、"2.jpg" 的逆向排序问题,打印出来的纸质文件顺序将彻底被打乱。
1. 依赖库安装
本项目主要依赖 Python 官方推荐的图像处理库 Pillow。如果选择在 Windows 环境下直接调用本地系统打印机驱动,还需安装 pywin32:
pip install Pillow pywin32
2. 图片扫描与自然排序实现
通过 pathlib.Path 检索文件,并利用正则表达式对文件名中的连续数字段提取为整型,实现与人类认知一致的自然排序(Natural Sorting):
import re
from pathlib import Path
def get_sorted_images(folder_path):
"""
扫描文件夹内的支持图片,并按自然数字顺序排序
"""
supported_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff'}
folder = Path(folder_path)
if not folder.exists() or not folder.is_dir():
raise FileNotFoundError(f"指定的目录不存在: {folder_path}")
# 过滤指定后缀(忽略大小写)
image_paths = [
p for p in folder.iterdir()
if p.is_file() and p.suffix.lower() in supported_extensions
]
# 正则提取文件名中的数字与非数字片段,实现自然排序
def natural_key(path_obj):
return [int(text) if text.isdigit() else text.lower()
for text in re.split(r'(\d+)', path_obj.name)]
image_paths.sort(key=natural_key)
return image_paths
# 示例:获取目录图片
if __name__ == "__main__":
imgs = get_sorted_images("./input_images")
print(f"成功扫描到 {len(imgs)} 张有效图片")
二、方案一:Windows 原生 Shell 接口逐张直接打印
如果开发环境与运行终端均为 Windows 系统,且机器上已正确配置好默认打印机,可以直接借助 Windows 系统的 ShellExecute 接口,调用系统默认关联的照片查看器执行 "print" 动词动作。
1. 核心打印代码
遍历图片列表,每次发起一个系统打印调用。为了防止短时间内大量任务压垮系统的 Windows Spooler(打印后台处理服务),必须在每次调用之间加入必要的延迟:
import os
import sys
import time
def print_images_windows_native(image_paths, delay_seconds=2.0):
"""
调用 Windows 默认打印动作批量输出图片
:param image_paths: 图片文件 Path 列表
:param delay_seconds: 每个任务推入队列后的保护延迟(秒)
"""
if sys.platform != "win32":
raise OSError("该方法依赖 Windows 系统外壳接口,无法在其它操作系统运行。")
import win32api
import win32print
default_printer = win32print.GetDefaultPrinter()
print(f"当前使用的默认打印机为: {default_printer}")
for index, img_path in enumerate(image_paths, start=1):
abs_path = str(img_path.resolve())
print(f"[{index}/{len(image_paths)}] 正在发送至打印机: {img_path.name}")
# 0: 父窗口句柄
# "print": 执行打印动作
# abs_path: 目标文件路径
# None: 附加参数
# ".": 工作目录
# 0: 后台静默/隐藏窗口启动
win32api.ShellExecute(0, "print", abs_path, None, ".", 0)
# 关键节流延时:让系统处理进程将任务完整提交至缓冲池
time.sleep(delay_seconds)
print("所有打印作业已全部提交至 Windows 打印队列。")
1. 排版格式无法精细控制:该方式本质上是委托 Windows 照片应用打印,纸张边距、缩放方式取决于系统的默认设置,遇到不同分辨率的图片容易出现画面被裁剪或边缘留白不均。
2. 高并发队列溢出:如果文件夹内有数百张图片,一次性发起数百次 Shell 进程可能导致打印服务无响应,甚至部分任务被跳过。因此更适合数量在 20 张以内的小批量临时打印。
三、方案二:跨平台合并多页 PDF 统一打印(工业级标准方案)
为了解决尺寸参差不齐、边距失真以及跨系统兼容等问题,生产环境中最通用的标准做法是:先将文件夹内所有图片按统一的纸张规格(如 A4、6寸照片纸)排版并合并生成单份多页 PDF,再由打印机统一输出该 PDF。
1. 排版与缩放自适应原理
真实世界中的图片宽高比各不相同。若直接拉伸铺满,图像必然发生形变;若不做缩放,高分辨率图片会被截断。正确的方法是:
- 建立标准纸张尺寸的纯白背景底图(例如 A4 尺寸在 300 DPI 下为 2480 × 3508 像素);
- 扣除安全装订白边(Margin),计算最大允许绘制区域;
- 根据原图宽高比计算等比缩放因子,求出缩放后的宽与高;
- 将缩放后的图片居中贴在纯白画板中央,多余区域自动形成规整白边。
2. 图片合成为规范 PDF 的完整实现
需要注意,透明 PNG(RGBA 模式)如果直接转成 PDF,可能会导致透明背景被默认渲染为刺眼的纯黑色,因此必须在代码中将 Alpha 通道与纯白底板复合为标准 RGB 模式:
from PIL import Image, ImageOps
def create_printable_pdf(image_paths, output_pdf_path, dpi=300, margin_mm=10):
"""
将多张图片按标准 A4 规格自适应居中排版,导出为单份多页 PDF
"""
# A4 尺寸定义(毫米),转换为指定 DPI 下的像素点数
mm_to_inch = 1 / 25.4
page_w_px = int(210 * mm_to_inch * dpi) # 约 2480 像素
page_h_px = int(297 * mm_to_inch * dpi) # 约 3508 像素
margin_px = int(margin_mm * mm_to_inch * dpi)
content_w_px = page_w_px - (margin_px * 2)
content_h_px = page_h_px - (margin_px * 2)
processed_pages = []
for img_path in image_paths:
with Image.open(img_path) as img:
# 1. 自动纠正手机拍摄带来的 EXIF 旋转属性
img = ImageOps.exif_transpose(img)
# 2. 转换色彩模式,处理透明图层(避免黑底)
if img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info):
rgba = img.convert('RGBA')
base_white = Image.new('RGBA', rgba.size, (255, 255, 255, 255))
img = Image.alpha_composite(base_white, rgba).convert('RGB')
else:
img = img.convert('RGB')
# 3. 计算等比缩放比例
orig_w, orig_h = img.size
scale = min(content_w_px / orig_w, content_h_px / orig_h)
new_w = max(1, int(orig_w * scale))
new_h = max(1, int(orig_h * scale))
# 采用高质量采样算法缩放
resized_img = img.resize((new_w, new_h), Image.Resampling.LANCZOS)
# 4. 创建 A4 纯白画板,并将图片粘贴到中央
page_canvas = Image.new('RGB', (page_w_px, page_h_px), (255, 255, 255))
offset_x = (page_w_px - new_w) // 2
offset_y = (page_h_px - new_h) // 2
page_canvas.paste(resized_img, (offset_x, offset_y))
processed_pages.append(page_canvas)
if not processed_pages:
raise ValueError("没有可供处理的图片页面。")
# 5. 保存为多页 PDF
first_page = processed_pages[0]
first_page.save(
output_pdf_path,
save_all=True,
append_images=processed_pages[1:],
resolution=dpi
)
print(f"成功生成标准化多页打印文档: {output_pdf_path},共 {len(processed_pages)} 页")
3. 打印生成的 PDF 文档
生成 PDF 之后,打印机只需接收单个任务文档,彻底避免了任务拥堵。针对不同平台,可采用以下命令或接口执行物理打印:
-
Windows 系统无头静默打印:推荐使用轻量开源工具
SumatraPDF或调用win32api.ShellExecute(0, "print", "output.pdf", None, ".", 0):# 命令行静默推送到指定物理打印机 SumatraPDF.exe -print-to "HP_LaserJet_Pro" output.pdf -
macOS / Linux 系统通用打印:系统原生提供标准的 CUPS 打印系统,使用
lpr命令即可一行搞定:# 查看可用打印机列表 lpstat -p # 推送 PDF 到默认打印机 lpr output.pdf # 推送 PDF 到指定打印机 lpr -P "Printer_Name" output.pdf
四、两套方案的选型对比
| 对比维度 | 方案一:Windows 原生 Shell 逐张打印 | 方案二:先合并多页 PDF 再统一打印 |
|---|---|---|
| 跨平台支持 | 仅支持 Windows | 全平台通用(Windows / macOS / Linux) |
| 排版与页面控制 | 不可控,由系统默认查看器设置决定 | 精准可控(可定义 A4/A3、安全边距、居中对齐) |
| 打印队列安全性 | 较弱,多图连续推入易造成队列死锁或跳页 | 极高,单份文档原子推入,物理出纸连续稳定 |
| 打印预览能力 | 无直接预览,易浪费纸张 | 生成后可直接双击 PDF 确认版面无误后再打印 |
| 实现代码量 | 非常少(约 20 行) | 适中(约 50 行),具备工业级容错性 |
五、常见问题与注意事项
1. 为什么透明背景的 PNG 打印出来背景全是黑色?
大部分物理打印机驱动只能识别 CMYK 或 RGB 颜色模型,不支持 Alpha 透明通道。若直接将含透明图层的 PNG 发送给打印模块,驱动程序会将透明像素(Alpha=0)默认解释为全黑(RGB=0,0,0)。在脚本中,必须先创建一个相同尺寸的白色背景画布,通过 Image.alpha_composite 或 paste 遮罩将透明内容复合为标准不透明 RGB 图像。
2. 图片方向颠倒或横竖颠倒是什么原因?
智能手机或现代单反相机在拍摄照片时,传感器通常以固定物理角度记录像素,而将设备的实际旋转角度存储在 EXIF 元数据的 Orientation 标签中。许多基础图片库在读取文件时不解析该标签,从而展示出倒立或旋转 90 度的错误图像。使用 Pillow 处理时,务必在最开始调用 ImageOps.exif_transpose(img) 对方向做物理像素级的预校正。
3. 网络打印机无响应或权限报错如何排查?
若使用局域网共享打印机,需在终端运行 python -c "import win32print; print(win32print.GetDefaultPrinter())" 查看 Python 进程当前捕获的打印机名称是否与系统设置一致。若返回名称含有未知主机名或未连接状态,可进入系统的“打印机和扫描仪”设置面板将目标打印机设为默认,或在代码中通过 win32print.SetDefaultPrinter(printer_name) 显式指定。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













