代码之家  ›  专栏  ›  技术社区  ›  Tvde1

使用wand将图像转换为pdf在几个成功结果后失败

  •  2
  • Tvde1  · 技术社区  · 8 年前

    我的应用程序运行了几次,然后每个pdf都会出错。这是我收到的错误:

    Exception TypeError: TypeError("object of type 'NoneType' has no len()",) in <bound method Image.__del__ of <wand.image.Image: (empty)>> ignored
    

    这是我使用的函数:

    def read_pdf(file):
        pre, ext = os.path.splitext(file)
        filename = pre + '.png'
    
        with Image(filename=file, resolution=200) as pdf:
            amount_of_pages = len(pdf.sequence)
    
            image = Image(
                width=pdf.width,
                height=pdf.height * amount_of_pages
            )
    
            for i in range(0, amount_of_pages):
                image.composite(
                    pdf.sequence[i],
                    top=pdf.height * i,
                    left=0
                )
    
            image.compression_quality = 100
            image.save(filename=filename)
            logging.info('Opened and saved pdf to image: \'' + file + '\'.')
            return filename
    

    此函数将正确地将PDF转换为图像,但在两到三次之后,每次都会崩溃并引发该异常。如果我重新启动python脚本,它会再次工作几次。

    2 回复  |  直到 8 年前
        1
  •  5
  •   emcconville    8 年前

    该错误是由系统资源不足引起的。Wand调用ImageMagick库;然后,将解码工作传递给Ghostscript委托。Ghostscript非常稳定,但确实使用了大量资源,并且在并行运行时并不满意( 我的意见 ).

    有什么帮助吗?

    • 尝试设计一种解决方案,允许在PDF转换之间完全关闭。像队列工作人员一样,或 剧本最小的资源泄漏可能很快失控。
    • 避免调用 wand.image.Image.sequance . 报告了一些已知的内存泄漏问题。虽然许多任务已经修复,但PDF任务似乎仍然存在问题。

    从发布的代码来看,您似乎只是用给定PDF的所有页面创建了一个高图像。我建议移植 MagickAppendImages 直接地

    import ctypes
    from wand.image import Image
    from wand.api import library
    
    # Map C-API to python
    library.MagickAppendImages.argtypes = (ctypes.c_void_p, ctypes.c_bool)
    library.MagickAppendImages.restype = ctypes.c_void_p
    
    with Image(filename='source.pdf') as pdf:
        # Reset image stack
        library.MagickResetIterator(pdf.wand)
        # Append all pages into one new image
        new_ptr = library.MagickAppendImages(pdf.wand, True)
        library.MagickWriteImage(new_ptr, b'output.png')
        library.DestroyMagickWand(new_ptr)
    
        2
  •  0
  •   Tvde1    8 年前

    看来我创造了一个新形象,并没有破坏它。这填满了记忆。

    我只是不得不使用 with new Image(...) as img 而不是 img = new Image(...) .