Обработка и отладка Reportlab 'LayoutError' - PullRequest
6 голосов
/ 18 июня 2010

Я работал с некоторыми сложными выводами PDF с reportlab. Обычно это нормально, но в некоторых случаях я получаю 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?
  • Любые другие предложения по общему улучшению, тестированию и решению подобных проблем.

У меня нет конкретного примера, так что его более общий совет, исключение, которое я рассмотрел выше, но в некотором роде методом проб и ошибок (читай, гадать и видеть, что происходит).

Ответы [ 2 ]

4 голосов
/ 25 августа 2010

Убедитесь, что вы не используете повторно какие-либо текучие объекты (например, рендеринг нескольких версий документа с использованием общих частей шаблона).Это не поддерживается ReportLab и может вызвать эту ошибку.

Причина, по-видимому, заключается в том, что ReportLab будет устанавливать атрибут для этих объектов при выполнении макета, чтобы указать, что необходимо было переместить их на отдельную страницу.,Если его нужно переместить дважды, он выдаст это исключение.Эти атрибуты не сбрасываются при рендеринге документа, поэтому может показаться, что объект был перемещен на отдельную страницу дважды, когда его на самом деле не было.

Я уже взломал это раньше, сбросив атрибут вручную(Я не могу вспомнить имя сейчас; оно было «_deferred» или что-то в этом роде), но правильный подход - выбросить любые объекты, которые вы использовали для рендеринга документа после его рендеринга.

2 голосов
/ 19 августа 2010

У нас была проблема при использовании 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 для сообщения об ошибке и исправьте ввод соответственно.

...