繁体   English   中英

PyPDF2:串联内存中的pdf

[英]PyPDF2: Concatenating pdfs in memory

我希望在纯python的内存中有效地串联(附加)一堆小pdf。 具体来说,通常情况是将500张单页pdf合并为一个,每个pdf大小约为400 kB。 假设pdf可作为内存中的可迭代对象使用,例如一个列表:

my_pdfs = [pdf1_fileobj, pdf2_fileobj, ..., pdfn_fileobj]  # type is BytesIO

其中每个pdf_fileobj均为BytesIO类型。 然后,基本内存使用量约为200 MB(500 pdfs,每个400kB)。

理想情况下,我希望以下代码总共使用不超过400-500 MB的内存(包括my_pdfs )进行连接。 但是,情况似乎并非如此,最后一行的调试语句表明以前的最大内存接近700 MB。 此外,使用Mac os x资源监视器,当到达最后一行时,分配的内存指示为600 MB。

运行gc.collect()可以将其减少到350 MB(几乎太好了?)。 在这种情况下,为什么我必须手动运行垃圾收集来摆脱合并垃圾? 我已经(可能)看到了这种情况,可能会导致内存积聚,但情况略有不同,我将略过。

import PyPDF2
import io
import resources  # For debugging

def merge_pdfs(iterable):
    ''' Merge pdfs in memory '''
    merger = PyPDF2.PdfFileMerger()
    for pdf_fileobj in iterable:
        merger.append(pdf_fileobj)

    myio = io.BytesIO()
    merger.write(myio)
    merger.close()

    myio.seek(0)
    return myio

my_concatenated_pdf = merge_pdfs(my_pdfs)

# Print the maximum memory usage
print('Memory usage: %s (kB)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)

问题总结

  • 为什么上面的代码需要近700 MB的内存来合并200 MB的pdf文件? 400 MB +开销不够吗? 我如何优化它?
  • 当有问题的变量应该已经超出范围时,为什么我需要手动运行垃圾回收来摆脱PyPDF2合并垃圾?
  • 那一般的方法呢? 这种情况适合使用BytesIO吗? 鉴于所有发生在ram中, merger.write(myio)运行速度似乎确实很慢。

谢谢!

问: 为什么上面的代码需要近700 MB的内存来合并200 MB的pdf? 400 MB +开销不够吗? 我如何优化它?

答:因为.append创建了一个新的流对象,然后您使用了merger.write(myio) ,它创建了另一个流对象,并且您的内存中已经有200 MB的pdf文件,所以3 * 200 MB。


问:当有问题的变量应该已经超出范围时,为什么我需要手动运行垃圾回收来摆脱PyPDF2合并垃圾?

答:这是PyPDF2中的一个已知问题


问:这种一般方法呢? 这种情况适合使用BytesIO吗?

答:考虑到内存问题,您可能需要尝试其他方法。 也许一个接一个地合并,将文件临时保存到磁盘,然后从内存中清除已经合并的文件。

PyMuPdf库也可以很好地替代PDFMergerPyPDF2的性能问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM