【问题标题】:Reportlab 'LayoutError' handling and debuggingReportlab 'LayoutError' 处理和调试
【发布时间】:2011-03-05 09:36:17
【问题描述】:

我一直在使用 reportlab 处理一些复杂的 PDF 输出。这些通常都很好,但在某些情况下我仍然会遇到 LayoutErrors - 这些通常是因为 Flowables 在某些时候太大了。

事实证明,调试这些非常困难,因为我通常没有比这样更多的信息;

Flowable <Table@0x104C32290 4 rows x 6 cols> with cell(0,0) containing
'<Paragraph at 0x104df2ea8>Authors'(789.0 x 1176) too large on page 5 in frame 'normal'(801.543307087 x 526.582677165*) of template 'Later'

这真的没那么有用。我最想知道的是最好的调试和测试策略。

  • 有什么方法可以查看损坏的 PDF?即呈现布局错误,以便我可以更轻松地看到发生了什么。
  • 有没有一种方法可以添加一个钩子到 reportlab 以更好地处理这些错误?而不是让整个 PDF 失败?
  • 关于一般改进、测试和处理此类问题的任何其他建议。

我没有一个特定的例子,所以它是更一般的建议,我已经解决了上面的异常,但它有点通过反复试验(阅读;猜测并看看会发生什么)。

【问题讨论】:

    标签: python debugging testing reportlab


    【解决方案1】:

    我们在使用 Reportlab 格式化一些最初是 html 的内容时遇到了问题,有时 html 过于复杂。解决方案(我在这里不相信,这是来自 Reportlab 的人)是在错误发生时捕获错误并将其直接输出到 PDF 中。

    这意味着您可以在正确的上下文中看到问题的原因。您可以对此进行扩展以输出异常的详细信息,但在我们的例子中,由于我们的问题是将 html 转换为 rml,我们只需要显示我们的输入:

    预科生模板包含以下内容:

    {{script}}
    #This section contains python functions used within the rml.
    #we can import any helper code we need within the template,
    #to save passing in hundreds of helper functions at the top
    from rml_helpers import blocks
    {{endscript}}
    

    然后是模板的后面部分,例如:

        {{if equip.specification}}
     <condPageBreak height="1in"/> 
            <para style="h2">Item specification</para>
            {{blocks(equip.specification)}}
        {{endif}}
    

    在 rml_helpers.py 我们有:

    from xml.sax.saxutils import escape
    from rlextra.radxml.html_cleaner import cleanBlocks
    from rlextra.radxml.xhtml2rml import xhtml2rml
    
    def q(stuff):
        """Quoting function which works with unicode strings.
    
        The data from Zope is Unicode objects.  We need to explicitly
        convert to UTF8; then escape any ampersands.  So
           u"Black & Decker drill"
        becomes
           "Black &amp; Decker drill"
        and any special characters (Euro, curly quote etc) end up
        suitable for XML.  For completeness we'll accept 'None'
        objects as well and output an empty string.
    
        """
        if stuff is None:
            return ''
        elif isinstance(stuff,unicode):
            stuff = escape(stuff.encode('utf8'))
        else:
            stuff = escape(str(stuff))
        return stuff.replace('"','&#34;').replace("'", '&#39;')
    
    def blocks(txt):
        try:
            txt2 = cleanBlocks(txt)
            rml = xhtml2rml(txt2)
            return rml
        except:
            return '<para style="big_warning">Could not process markup</para><para style="normal">%s</para>' % q(txt)
    

    所以任何对xhtml2rml 来说太复杂而无法处理的东西都会引发异常,并在输出中被一个大警告“无法处理标记”替换,然后是导致错误的标记,转义,因此它显示为文字。

    那么我们要做的就是记住在输出 PDF 中搜索错误消息并相应地修复输入。

    【讨论】:

      【解决方案2】:

      确保您没有重复使用任何可流动的对象(例如,使用通用模板部分呈现文档的多个版本)。 ReportLab 不支持此功能,可能会导致此错误。

      原因似乎是 ReportLab 在执行布局时会在这些对象上设置一个属性,以指示需要将它们移动到单独的页面。如果它必须移动两次,它将抛出该异常。当您呈现文档时,这些属性不会重置,因此看起来一个对象被移动到单独的页面两次,而实际上并非如此。

      我之前通过手动重置属性解决了这个问题(我现在不记得名字;它是'_deferred'或其他东西),但正确的方法是扔掉你用来渲染的任何对象渲染后的文档。

      【讨论】:

      • 谢谢!由于这个我似乎无法解决的“随机”问题,我正准备放弃 ReportLab。但这正是我所需要的。
      猜你喜欢
      • 2010-12-22
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多