2010-06-18 3 views
6

Ho lavorato con alcune uscite PDF complesse con reportlab. Questi sono generalmente soddisfacenti, ma ci sono alcuni casi ancora dove ottengo LayoutErrors - questi sono di solito perché i Flowable sono troppo grandi ad un certo punto.Reportlab 'LayoutError' gestione e debug

È abbastanza difficile eseguire il debug di questi perché spesso non ho più informazioni di qualcosa del genere;

Flowable <[email protected] 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' 

Non è molto utile. Quello che vorrei idealmente sapere sono le migliori strategie di debugging e test per questo genere di cose.

  • C'è un modo per visualizzare un PDF danneggiato? cioè reso con gli errori di layout in modo da poter vedere cosa sta succedendo più facilmente.
  • C'è un modo per aggiungere un hook a reportlab per gestire meglio questi errori? Piuttosto che fallire l'intero PDF?
  • Altri suggerimenti su come migliorare, testare e gestire in generale problemi come questi.

Non ho un particolare esempio quindi il suo consiglio più generale, l'eccezione sopra ho risolto ma è un po 'per tentativi ed errori (leggi, indovinare e vedere cosa succede).

risposta

2

Si è verificato un problema durante l'utilizzo di Reportlab per formattare un contenuto che era in origine html e talvolta l'html era troppo complesso. La soluzione (e non mi prendo alcun merito qui, questo è stato dai ragazzi di Reportlab) è stato quello di catturare l'errore quando si è verificato e l'output direttamente nel PDF.

Ciò significa che è possibile vedere la causa del problema nel giusto contesto. Si potrebbe approfondire questo per i dettagli di uscita del l'eccezione, ma nel nostro caso, in quanto il nostro problema è stato la conversione html a RML abbiamo appena avuto per visualizzare il nostro contributo:

Iil modello preppy contiene questo:

{{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}} 

e poi bit successive di modello come:

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

in rml_helpers.py abbiamo:

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) 

Quindi tutto ciò che è troppo complesso per xhtml2rml per gestire genera un'eccezione e viene sostituito nell'output da un avvertimento di grandi dimensioni 'Impossibile elaborare il markup' seguito dalla marcatura che ha causato l'errore, sfuggito in modo che appaia letterale.

Quindi tutto quello che dobbiamo fare è ricordare di cercare il PDF di output per il messaggio di errore e correggere l'input di conseguenza.

4

Assicurarsi di non riutilizzare nessuno degli oggetti scorrevoli (come in, esecuzione di più versioni di un documento utilizzando parti di modello comuni). Questo non è supportato da ReportLab e può causare questo errore.

Il motivo sembra essere che ReportLab imposterà un attributo su questi oggetti quando si esegue il layout per indicare che era necessario spostarli in una pagina separata. Se deve essere spostato due volte, genererà quell'eccezione. Questi attributi non vengono ripristinati quando si esegue il rendering di un documento, quindi può sembrare che un oggetto sia stato spostato in una pagina separata due volte quando in realtà non lo era.

Ho aggirato questo problema reimpostando manualmente l'attributo (non riesco a ricordare il nome in questo momento, era "_deferred" o qualcosa del genere), ma l'approccio corretto è quello di eliminare tutti gli oggetti che hai usato per il rendering un documento dopo che è stato reso.

+0

Certo risolto il mio problema. Grazie! Spero che abbia aiutato anche l'OP. – arikb

+0

Grazie! Ero quasi pronto a rinunciare a ReportLab a causa di questo "casuale" che non riuscivo a risolvere. Ma questo è quello di cui avevo bisogno. – MinchinWeb