如何使用Python 3.7 pdf2image库解决MemoryError?

Aak*_*asu 4 python out-of-memory data-conversion python-3.x

我正在使用Python PDF2Image库运行一个简单的PDF到图像的转换。我当然可以理解,此库正在越过最大内存阈值,从而导致出现此错误。但是,PDF是6.6 MB(大约),那么为什么要占用GB的内存来引发内存错误?

Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pdf2image import convert_from_path
>>> pages = convert_from_path(r'C:\Users\aakashba598\Documents\pwc-annual-report-2017-2018.pdf', 200)
Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Users\aakashba598\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\aakashba598\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\aakashba598\AppData\Local\Programs\Python\Python37-32\lib\subprocess.py", line 1215, in _readerthread
    buffer.append(fh.read())
MemoryError
Run Code Online (Sandbox Code Playgroud)

另外,对此可能的解决方案是什么?

更新:当我从convert_from_path函数中减小dpi参数时,它像一个超级按钮一样工作。但是产生的图片质量低(出于明显的原因)。有没有办法解决这个问题?就像逐批创建图像并每次清除内存一样。如果有办法,该怎么办?

nap*_*zba 5

每次将PDF转换为10页的块(1-10,11-20等)。

maxPages = pdf2image._page_count(pdf_file)
for page in range(1,maxPages,10) : 
   convert_from_path(pdf_file, dpi=200, first_page=page, last_page = min(page+10-1,maxPages))
Run Code Online (Sandbox Code Playgroud)


Bel*_*val 5

我对此有些迟,但是问题确实与进入内存的136页有关。您可以做三件事。

  1. 指定转换后的图像的格式。

缺省情况下,pdf2image使用PPM作为其图像格式,速度更快,但占用的内存也更多(每个图像超过30MB!)。解决此问题的方法是使用对内存更友好的格式,例如jpeg或png。

convert_from_path('C:\path\to\your\pdf', fmt='jpeg')
Run Code Online (Sandbox Code Playgroud)

那可能会解决问题,但这主要是因为压缩,并且在某些时候(例如,+ 500页PDF)问题会再次出现。

  1. 使用输出目录

这是我建议的,因为它允许您处理任何PDF。README页上的示例对此进行了很好的解释:

import tempfile

with tempfile.TemporaryDirectory() as path:
    images_from_path = convert_from_path('C:\path\to\your\pdf', output_folder=path)
Run Code Online (Sandbox Code Playgroud)

这会将图像临时写入计算机存储,因此您不必手动删除它。但是,请确保在退出with上下文之前进行所需的任何处理!

  1. 批量处理PDF文件

pdf2image 允许您定义要处理的第一页和最后一页。这就是说,对于您的情况,使用136页的PDF,您可以执行以下操作:

for i in range(0, 136 // 10 + 1):
    convert_from_path('C:\path\to\your\pdf', first=i*10, last=(i+1)*10)
Run Code Online (Sandbox Code Playgroud)


Bot*_*art 5

接受的答案有一个小问题。

maxPages = pdf2image._page_count(pdf_file)

不能再使用,因为_page_count已弃用。我找到了相同的工作解决方案。

from PyPDF2 import PdfFileWriter, PdfFileReader    
inputpdf = PdfFileReader(open(pdf, "rb"))
maxPages = inputpdf.numPages
for page in range(1, maxPages, 100):
    pil_images = pdf2image.convert_from_path(pdf, dpi=200, first_page=page,
                                                     last_page=min(page + 100 - 1, maxPages), fmt= 'jpg',
                                                     thread_count=1, userpw=None,
                                                     use_cropbox=False, strict=False)
Run Code Online (Sandbox Code Playgroud)

这样,无论文件有多大,它都会一次处理 100 个,并且 ram 使用量总是最小的。