Reportlab'LayoutError'处理和调试

Ora*_*Box 6 python testing debugging reportlab

我一直在使用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'
Run Code Online (Sandbox Code Playgroud)

这真的没那么有用.我理想地想知道的是这种事情的最佳调试和测试策略.

  • 有没有办法可以查看损坏的PDF?即使用布局错误渲染,所以我可以看到更容易发生的事情.
  • 有没有办法可以为reportlab添加一个钩子来更好地处理这些错误?而不只是失败整个PDF?
  • 关于一般改进,测试和处理这些问题的任何其他建议.

我没有一个特别的例子,所以它更一般的建议,上面的例外我已经解决了但它有点通过试验和错误(阅读;猜测和看到会发生什么).

Dun*_*can 2

我们在使用 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}}
Run Code Online (Sandbox Code Playgroud)

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

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

在 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)
Run Code Online (Sandbox Code Playgroud)

因此,任何过于复杂而xhtml2rml无法处理的内容都会引发异常,并在输出中被一个大警告“无法处理标记”替换,后跟导致错误的标记,经过转义,因此它显示为文字。

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