You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pillow+multiprocessing批量处理图片通道时程序卡住无报错

问题说明

使用pillow和multiprocessing批量处理图片时,程序无报错但长时间挂起无法结束:

  • 需求:遍历目录下数百张JPEG图片,拆分RGB通道后用ImageChops.add合并绿色通道、蓝色通道,结果保存为新文件
  • 运行环境:macOS 10.16 x86_64
  • 初始代码如下:
import platform
from PIL import Image
from PIL import ImageChops
import glob
from multiprocessing import Pool

print(platform.platform())
# macOS-10.16-x86_64-i386-64bit

def get_processed_im(f):
    im = Image.open(f)
    im_r, im_g, im_b = im.split()
    im_rf = ImageChops.add(im_g, im_b)
    # save images
    im_rf.save("RF_"+f, "JPEG")


if __name__ == '__main__':
    # Create a pool of processes to check files
    p = Pool()

    # Create a list of files to process
    files = [f for f in glob.glob("*.jpeg")]

    print(f'Files to process: {len(files)}')
    
    print(files)

    p.map(get_processed_im, files)
  • 运行输出:
Files to process: 4
['im1.jpeg', 'im2.jpeg', 'im3.jpeg', 'im4.jpeg']

输出以上内容后程序无报错,但长时间运行无法结束。

问题原因

挂起由两个因素共同导致:

  1. macOS平台下Python 3.8+版本的multiprocessing默认使用spawn模式启动子进程,该模式下Pillow的C扩展初始化逻辑存在死锁风险,子进程启动后会卡在资源初始化步骤无法执行实际任务
  2. 代码未显式回收进程池资源,且打开的图片对象未手动释放,文件句柄泄漏会进一步加剧进程挂起概率
修复方案

按以下步骤调整代码即可正常运行:

  • 显式设置多进程启动模式为fork,避开spawn模式下的C扩展死锁问题
  • 用上下文管理器打开图片,处理完成后自动释放文件句柄
  • 进程池使用完成后显式调用close()和join(),确保所有子进程任务执行完成后资源正常回收
  • 增加文件过滤逻辑,排除之前运行生成的RF_开头的结果文件,避免重复处理

修复后的完整可运行代码:

import platform
from PIL import Image
from PIL import ImageChops
import glob
from multiprocessing import Pool, set_start_method

def get_processed_im(f):
    with Image.open(f) as im:
        _, im_g, im_b = im.split()
        im_rf = ImageChops.add(im_g, im_b)
        im_rf.save(f"RF_{f}", "JPEG")
    print(f"Finish processing: {f}")


if __name__ == '__main__':
    set_start_method('fork', force=True)
    print(platform.platform())
    
    # 可根据CPU核心数调整进程数,建议设为物理核心数
    p = Pool(processes=4)
    # 过滤已生成的结果文件
    files = [f for f in glob.glob("*.jpeg") if not f.startswith("RF_")]

    print(f'Files to process: {len(files)}')
    print(files)

    p.map(get_processed_im, files)
    p.close()
    p.join()
    print("All tasks completed.")
额外说明

如果调整后仍有异常,可以先把多进程逻辑注释掉,用普通for循环串行处理文件,确认Pillow的图片处理逻辑本身没有问题后,再开启多进程加速。

内容的提问来源于stack exchange,提问作者olveraa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:27:08