如何在Python中无需先存图到磁盘就将PIL图片写入PDF
问题解决:内存中直接将PIL图片写入FPDF及磁盘损耗疑问
一、磁盘损耗的担忧是否多余?
完全多余。现代存储设备(SSD或HDD)的写入寿命远超个人日常使用需求:就算1500张截图每张10MB,总写入量也才15GB,而普通消费级SSD的TBW(总写入字节)通常在几百TB级别,HDD的机械损耗更不用考虑这类量级的写入。哪怕你每天跑一次这个脚本,也要数年才会对设备寿命产生可感知的影响,个人使用完全没必要纠结这点。
二、无需磁盘写入直接导入PIL图片到PDF的解决方案
方案1:升级到FPDF2(推荐)
你当前使用的旧版fpdf(即fpdf1)不支持直接传入BytesIO对象,而新版fpdf2已经修复了这个限制。先安装新版库:
pip install fpdf2
修改后的代码示例:
import pyscreenshot as ImageGrab from fpdf import FPDF import io def get_page_image(): return ImageGrab.grab(bbox=half_page_bbox) half_page_bbox = (249, 1, 1672, 1028) pdf = FPDF("P", "mm", "A4") pdf.add_page() page_image = get_page_image() # 内存中存储图片数据 tmp_file = io.BytesIO() page_image.save(tmp_file, format='PNG') tmp_file.seek(0) # 直接传入BytesIO对象,同时指定图片格式 pdf.image(tmp_file, 10, 10, 100, format='PNG') pdf.output("My pdf.pdf")
方案2:给BytesIO对象添加name属性(兼容旧版fpdf)
如果不想升级库,可以手动给BytesIO对象添加name属性——旧版fpdf会通过文件名后缀判断图片格式,添加后就能绕过检查:
import pyscreenshot as ImageGrab from fpdf import FPDF import io def get_page_image(): return ImageGrab.grab(bbox=half_page_bbox) half_page_bbox = (249, 1, 1672, 1028) pdf = FPDF("P", "mm", "A4") pdf.add_page() page_image = get_page_image() tmp_file = io.BytesIO() page_image.save(tmp_file, format='PNG') tmp_file.seek(0) # 给BytesIO对象添加带后缀的name属性 tmp_file.name = "temp.png" pdf.image(tmp_file, 10, 10, 100) pdf.output("My pdf.pdf")
内容的提问来源于stack exchange,提问作者Henry Ginn
相关产品推荐
相关产品推荐

