2011-11-10 58 views
25

Soy un chico de la universidad, y en mi universidad, para presentar cualquier clase de tarea, tiene que tener una portada estándar (con el logotipo de la universidad, el nombre del curso, el nombre del profesor, mi nombre y bla bla bla).Generando pdf-latex con script de python

Por lo tanto, tengo un documento .tex, que genera mis páginas de tapa estándar pdfs. Es algo parecido a:

... 
\begin{document} 
%% College logo 
\vspace{5cm} 
\begin{center} 
\textbf{\huge "School and Program Name" \\} 
\vspace{1cm} 
\textbf{\Large "Homework Title" \\} 
\vspace{1cm} 
\textbf{\Large "Course Name" \\} 
\end{center} 
\vspace{2.5cm} 
\begin{flushright} 
{\large "My name" } 
\end{flushright} 
... 

Por lo tanto, me preguntaba si hay una manera de hacer un script en Python que me pide el título de mi tarea, el nombre del curso y el resto de las cuerdas y utilizarlos para generar la portada. Después de eso, debe compilar el .tex y generar el pdf con la información dada.

Cualquier opinión, consejo, fragmento, biblioteca, se acepta.

+1

El editor de texto es más rápido en mi humilde opinión. Aún debe ingresar el título, el nombre del curso, etc. cada vez que imprima una portada. Convertiría ese PDF a una plantilla de palabra. Pruebe: http://www.pdftoword.com/ –

+1

Puede usar un administrador de fragmentos/plantilla en un editor de texto. –

+2

¡esa es una buena idea! pero estaba buscando algo más hecho por mí mismo/friki. – juliomalegria

Respuesta

53

Puede empezar por definir el archivo tex plantilla como una cadena:

content = r'''\documentclass{article} 
\begin{document} 
... 
\textbf{\huge %(school)s \\} 
\vspace{1cm} 
\textbf{\Large %(title)s \\} 
... 
\end{document} 
''' 

A continuación, utilice argparse para aceptar los valores para el curso, título, nombre y escuela:

parser = argparse.ArgumentParser() 
parser.add_argument('-c', '--course') 
parser.add_argument('-t', '--title') 
parser.add_argument('-n', '--name',) 
parser.add_argument('-s', '--school', default='My U') 

Un poco del formato de cadena es todo lo que se necesita para pegar los argumentos en content:

args = parser.parse_args() 
content%args.__dict__ 

Después de escribir el contenido en un archivo, cover.tex,

with open('cover.tex','w') as f: 
    f.write(content%args.__dict__) 

se puede utilizar para llamar subprocesspdflatex cover.tex.

proc = subprocess.Popen(['pdflatex', 'cover.tex']) 
proc.communicate() 

Se podría añadir un comando lpr también aquí para agregar la impresión al flujo de trabajo.

eliminar archivos innecesarios:

os.unlink('cover.tex') 
os.unlink('cover.log') 

La secuencia de comandos que se podría llamar así:

make_cover.py -c "Hardest Class Ever" -t "Theoretical Theory" -n Me 

ponerlo todo junto,

import argparse 
import os 
import subprocess 

content = r'''\documentclass{article} 
\begin{document} 
... P \& B 
\textbf{\huge %(school)s \\} 
\vspace{1cm} 
\textbf{\Large %(title)s \\} 
... 
\end{document} 
''' 

parser = argparse.ArgumentParser() 
parser.add_argument('-c', '--course') 
parser.add_argument('-t', '--title') 
parser.add_argument('-n', '--name',) 
parser.add_argument('-s', '--school', default='My U') 

args = parser.parse_args() 

with open('cover.tex','w') as f: 
    f.write(content%args.__dict__) 

cmd = ['pdflatex', '-interaction', 'nonstopmode', 'cover.tex'] 
proc = subprocess.Popen(cmd) 
proc.communicate() 

retcode = proc.returncode 
if not retcode == 0: 
    os.unlink('cover.pdf') 
    raise ValueError('Error {} executing command: {}'.format(retcode, ' '.join(cmd))) 

os.unlink('cover.tex') 
os.unlink('cover.log') 
+5

¡solución bastante buena, y simple! ahora tengo un generador de portadas automático :) – juliomalegria

+0

¿Hay alguna manera de verificar si el pdf se generó con éxito? He encontrado que si tengo un '&' o '%' en el texto, rompe el pdf. – Johan

+0

@Johan: la secuencia de comandos muestra el resultado de la llamada a 'pdlatex'. Si hay un error procesando el LaTeX, esos mensajes de error le mostrarán que el pdf no se generó correctamente. El 'y' no es un personaje especial en Python, pero está en TeX, por lo que necesita hacer una barra invertida si quiere un símbolo comercial literal: '\ &'. El '%' es un carácter especial tanto en Python como en TeX. Dependiendo de dónde se encuentre el '%', es posible que deba cambiarse a '\%' o '%%'. – unutbu

5

Existen, por supuesto, sistemas de plantillas como Jinja, pero probablemente sean demasiado para lo que estás preguntando. También puede formatear la página usando RST y usarla para generar LaTeX, pero de nuevo, eso probablemente sea excesivo. Diablos, la generación automática de la página probablemente sea excesiva para la cantidad de campos que debe definir, pero desde cuándo nos detuvo el exceso. :)

He hecho algo similar con el formato de cadenas de Python. Tome su documento LaTeX arriba y "tokenize" el archivo colocando tokens %(placeholder_name1)s en el documento. Por ejemplo, cuando usted quiere que su nombre de la clase para ir, utilizar %(course_name)s

\textbf{\Large "%(homework_title)s" \\} 
\vspace{1cm} 
\textbf{\Large "%(course_name)s" \\} 

Entonces, desde Python, que puede cargar en esa plantilla y formato como:

template = file('template.tex', 'r').read() 
page = template % {'course_name' : 'Computer Science 500', 
        'homework_title' : 'NP-Complete'} 
file('result.tex', 'w').write(page) 

Si quiere encontrar a los fichas automáticamente, el siguiente debe hacer bastante bien:

import sys 
import re 
import subprocess 

template = file('template.tex', 'r').read() 
pattern = re.compile('%\(([^}]+)\)[bcdeEfFgGnosxX%]') 
tokens = pattern.findall(template) 

token_values = dict() 
for token in tokens: 
    sys.stdout.write('Enter value for ' + token + ': ') 
    token_values[token] = sys.stdin.readline().strip() 

page = template % token_values 
file('result.tex', 'w').write(page) 

subprocess.call('pdflatex result.tex') 

el código se repetirá a través de las fichas e imprimir un aviso para la consola que le pide una entrada por cada ficha. En el ejemplo anterior, obtendrá dos mensajes (con ejemplos de respuestas):

Enter value for homework_title: NP-Complete 
Enter value for course_name: Computer Science 500 

La última línea llama pdflatex en el archivo resultante y genera un PDF a partir de ella. Si desea ir más allá, también puede pedirle al usuario un nombre de archivo de salida o tomarlo como una opción de línea de comando.

+0

Necesitaba agregar 'shell = True' a la llamada de subproceso. – TimP

+0

¡Ya que nos gusta la exageración, quiero ver la respuesta de Jinja! – sleblanc

3

También hay una Template clase (desde 2.4) que permite usar el token $that en lugar de %(thi)s uno.

+0

Jinja2 también se puede usar: http://flask.pocoo.org/snippets/55/ – alexpirine

Cuestiones relacionadas