Python批量打印文件夹内的所有图片

周叙
周叙
发布时间:2026-11-04 | 7人浏览过
原创

详细介绍使用Python批量打印文件夹内所有图片的两种高效方案:Windows原生接口调用与跨平台多页PDF统一排版打印,包含自然排序、比例缩放、白边留白与打印队列防卡死完整代码与排错方法。

在 Python 中批量打印文件夹内的所有图片,主要有两种稳定可行的实现路径:一种是调用 Windows 原生外壳接口直接将图片逐张发送到默认打印机;另一种是使用图像处理库先将文件夹内的图片按纸张规格自动缩放、居中排版并合并为单份多页 PDF 文件,再统一推送打印。后者不仅彻底解决了跨平台兼容与图片长宽不一导致的错位拉伸问题,还能从根本上避免数十张图片直接并发冲击打印机队列造成的死锁与丢页。
Python批量打印文件夹内的所有图片
图 0:Python 批量打印核心流转架构(数据读取、批处理中枢与物理设备协同)

一、准备工作:图片检索与自然排序

实现批量打印的第一步是准确获取指定文件夹中的所有图片路径。在实际场景中,文件夹往往包含不同格式(如 .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)} 张有效图片")
Python批量打印文件夹内的所有图片
图 1:批量打印处理流水线的四个关键执行环节

二、方案一: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 张以内的小批量临时打印。

Python批量打印文件夹内的所有图片
图 2:原生 Shell 接口直接打印与 PDF 容器统一打印架构对比

三、方案二:跨平台合并多页 PDF 统一打印(工业级标准方案)

为了解决尺寸参差不齐、边距失真以及跨系统兼容等问题,生产环境中最通用的标准做法是:先将文件夹内所有图片按统一的纸张规格(如 A4、6寸照片纸)排版并合并生成单份多页 PDF,再由打印机统一输出该 PDF。

1. 排版与缩放自适应原理

真实世界中的图片宽高比各不相同。若直接拉伸铺满,图像必然发生形变;若不做缩放,高分辨率图片会被截断。正确的方法是:

  • 建立标准纸张尺寸的纯白背景底图(例如 A4 尺寸在 300 DPI 下为 2480 × 3508 像素);
  • 扣除安全装订白边(Margin),计算最大允许绘制区域;
  • 根据原图宽高比计算等比缩放因子,求出缩放后的宽与高;
  • 将缩放后的图片居中贴在纯白画板中央,多余区域自动形成规整白边。
Python批量打印文件夹内的所有图片
图 3:图片等比缩放与 A4 页面自适应居中算法原理

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 行),具备工业级容错性
Python批量打印文件夹内的所有图片
图 4:批量打印完整体系架构与常见高频故障应对全景图

五、常见问题与注意事项

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) 显式指定。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表