2012-04-22 25 views
12

Necesito generar más de 100 páginas de documentos PDF. El proceso requiere una gran cantidad de datos para procesar, y la generación todo en uno requiere más tiempo y memoria que puedo dar.Cómo generar documentos pdf página por página en tareas en segundo plano en App Engine

que han intentado algunos métodos diferentes para hackear mi camino a través de:

  • xhtml2pdf con la generación de HTML y conversión
  • rportlab para generar algunas páginas y
  • pyPdf para fusionar

Con resultados variables, lo puse en funcionamiento, pero es lento y requiere más memoria de la que debería (a veces toca el sof de la instancia t límite de memoria). Actualmente genero algunas secciones en diferentes tareas almacenando cada una en blobstore y las combino con pyPdf, pero se atasca en documentos más grandes.

El documento que estoy generando no es tan complicado, principalmente tablas y texto, sin referencias internas, sin TOC, sin nada que deba tener en cuenta el resto del documento. Puedo vivir con ornitorrincos para el diseño y no necesito una apariencia sofisticada de documento o conversión de HTML2PDF.

El objetivo es generar el documento tan rápido como lo permita el almacén de datos. La generación de páginas paralelas sería agradable, pero no es obligatorio.

Estaba pensando en la generación página por página con blobstore files api, donde cada tarea generaría una sola página y la última tarea finalizaría el archivo blobstore haciéndolo legible. Pero parece que no puedo encontrar cómo, detener la generación, almacenar PDF parcial para transmitir y reanudar la generación con esa secuencia para generar la página siguiente en una tarea diferente.

Así que mi pregunta es:

Cómo en la GAE generar una más grande que un documento PDF pocas páginas, la división de la generación de entre las solicitudes de tareas, a continuación, guardar el documento resultante en el almacén de blob?

Si la generación de división no es posible con ReportLab, ¿cómo minimizar la huella de la fusión de diferentes documentos PDF para que se ajuste a los límites establecidos por la solicitud de tarea de GAE?

ACTUALIZACIÓN: Alternativas a la API de conversión muy apreciada.

2nd UPDATE Conversion API se está retirando, por lo que no es una opción ahora.

3rd UPDATE ¿Puede la API de Pileline o MapReduce ayuda aquí?

+0

¿Tiene una forma de dividir los datos de origen en fragmentos de tamaño de página sin realizar la conversión real? Si es así, podrías escribir una función que use replortlab para generar páginas individuales y usar 'multiprocesamiento.Pool.map' para ejecutar eso en paralelo sobre una lista de fragmentos de todas tus entradas. Como último paso, use pyPdf para fusionar las páginas en un único documento. –

+0

Ya hago algo similar sin mucho éxito, la fusión lleva mucho tiempo para terminar durante la tarea (debe ser inferior a 10 min) para algunos documentos. Tal vez lo hago de la manera incorrecta, de todos modos me gustaría un ejemplo de código sobre cómo hacerlo correctamente. –

+1

La composición rápida de documentos grandes suena como un trabajo para TeX (posiblemente con los paquetes de macros LaTeX o ConTeXt). Sin embargo, tendrías que ejecutar eso en un servidor separado. –

Respuesta

1

Tome un vistazo a la nueva API de conversión: https://developers.google.com/appengine/docs/python/conversion/overview

+0

Hay un límite de 60 en, ¿Qué tamaño de documentos ha generado con eso? Creo que la persona antes que yo lo intentó y no logró buenos resultados. Esta API es bastante básica: ¿cómo se insertan saltos de página, por ejemplo? –

+0

Si lo ejecuta en una cola de tareas, entonces es un límite de 10 minutos: https://developers.google.com/appengine/articles/deferred –

+0

¿Está diciendo que [la fecha límite máxima de presentación de la solicitud de conversión es 60?] (Https: // developers. google.com/appengine/docs/python/conversion/overview#Limits) no se aplica si la API de conversión se utiliza desde una tarea. –

1

Sugiero instalar wkhtmltopdf en el motor de aplicación. Wkhtmltopdf es una herramienta de línea de comandos para procesar html en pdf.

Cree los archivos html y luego conviértalos a pdf uno por uno usando wkhtmltopdf.

En Windows, puede utilizar (en los sistemas basados ​​en Linux es algo similar):

def create_pdf(in_html_file=None, out_pdf_file=None, quality=None): 
    pathtowk = 'C:/wkhtmltopdf/bin/wkhtmltopdf.exe {0} {1} {2}'  

    if quality == 1: # super quality no compression 
     args_str = '--encoding utf-8 --disable-smart-shrinking --no-pdf-compression --page-size A4 --zoom 1 -q -T 15.24mm -L 25.4mm -B 20.32mm -R 33.02mm' 
    elif quality == 2: # moderate quality some compression 
     args_str = '--encoding utf-8 --disable-smart-shrinking --page-size A4 --zoom 1 -q -T 15.24mm -L 25.4mm -B 20.32mm -R 33.02mm' 
    else: # poor quality max compression 
     args_str = '--encoding utf-8 --page-size A4 --zoom 1 -q -T 15.24mm -L 25.4mm -B 20.32mm -R 33.02mm' 

    os.system(pathtowk.format(args_str, in_html_file, out_pdf_file)) 

alternativa, se puede utilizar para ejecutar subprocess.call(pathtowk.format(args_str, in_html_file, out_pdf_file)) wkhtmltopdf (es mejor mi opinión).

Cuando se completa el proceso de conversión, use PyPdf2 para fusionar los archivos PDF generados en un solo archivo.

Cuestiones relacionadas