6

我一直在使用 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?
  • 有关一般改进、测试和处理此类问题的任何其他建议。

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

4

2 回答 2

4

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

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

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

于 2010-08-25T14:09:12.990 回答
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}}

然后是一些模板,如:

    {{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 中搜索错误消息并相应地修复输入。

于 2010-08-19T15:05:37.877 回答