我一直在使用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'
这真的没那么有用。我理想地想知道的是这类事情的最佳调试和测试策略。
我没有一个特别的例子,所以它更一般的建议,上面的例外我已经解决但是通过反复试验(阅读;猜测并看到会发生什么)。
答案 0 :(得分:4)
确保您不会重复使用任何可流动的对象(例如,使用常用模板部件呈现文档的多个版本)。 ReportLab不支持此功能,可能会导致此错误。
原因似乎是ReportLab在执行布局时会在这些对象上设置一个属性,以指示需要将它们移动到单独的页面。如果必须移动两次,它将抛出该异常。渲染文档时不会重置这些属性,因此当对象实际上没有被移动到另一个页面时,它可能会显示两次。
我之前通过手动重置属性(我现在不记得名称;它是'_deferred'或其他东西)来解决这个问题,但正确的做法是抛弃用于渲染的任何对象文件在呈现后。
答案 1 :(得分: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 & 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('"','"').replace("'", ''')
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中搜索错误消息并相应地修改输入。