2011-11-10 28 views
25

Sono un ragazzo del college, e nel mio college, per presentare qualsiasi tipo di compiti a casa, deve avere una copertina standard (con il logo del college, il nome del corso, il nome del professore, il mio nome e bla bla bla).Generazione pdf-latex con script python

Quindi, ho un documento .tex, che genera i miei pdf delle pagine di copertina standard. Va qualcosa come:

... 
\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} 
... 

Così, mi chiedevo se c'è un modo per fare uno script Python che mi chiede per il titolo del mio lavoro, il nome del corso e il resto delle corde e li usa per generare il frontespizio. Dopo di ciò, dovrebbe compilare .tex e generare il pdf con le informazioni fornite.

Qualsiasi opinione, consiglio, frammento, biblioteca, è accettato.

+1

L'editor di testo è più veloce IMHO. Devi comunque inserire il titolo, il nome del corso, ecc. Ogni volta che stampi una copertina. Convertirei quel PDF in un modello di parole. Prova: http://www.pdftoword.com/ –

+1

Potresti semplicemente usare un gestore di frammenti/un sistema di template in un editor di testo. –

+2

questa è una buona idea! ma stavo cercando qualcosa di più autodidatta/geek. – juliomalegria

risposta

53

Si può iniziare con la definizione del file di tex modello come una stringa:

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

Successivamente, utilizzare argparse per accettare i valori per il corso, il titolo, il nome e la scuola:

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 po ' della formattazione delle stringhe è sufficiente per inserire gli argomenti in content:

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

Dopo aver scritto il contenuto in un file, cover.tex,

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

si potrebbe usare subprocess per chiamare pdflatex cover.tex.

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

Si potrebbe aggiungere un comando lpr anche qui per aggiungere la stampa al flusso di lavoro.

rimuovere i file non necessari:

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

Lo script potrebbe allora essere chiamati in questo modo:

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

mettere tutto insieme,

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

soluzione abbastanza buona, e semplice! ora ho un generatore di copertine automatico :) – juliomalegria

+0

C'è un modo per verificare se il pdf è stato generato con successo? Ho trovato se ho un '&' o '%' nel testo rompe il pdf. – Johan

+0

@Johan: lo script mostra l'output della chiamata a 'pdlatex'. Se si verifica un errore durante l'elaborazione di LaTeX, tali messaggi di errore mostreranno che il file PDF non è stato generato correttamente. '&' Non è un carattere speciale in Python, ma è in TeX, quindi è necessario eseguire il backslash se si desidera una e commerciale letterale: '\ &'. '%' È un personaggio speciale sia in Python che in TeX. A seconda di dove si trova '%', potrebbe essere necessario cambiarlo in '\%' o '%%'. – unutbu

5

Ci sono naturalmente sistemi di template come Jinja, ma probabilmente sono eccessivi per quello che chiedi. Puoi anche formattare la pagina usando RST e usarla per generare LaTeX, ma di nuovo probabilmente è eccessivo. Diamine, la generazione automatica della pagina è probabilmente eccessiva per il numero di campi che devi definire, ma da quando l'overkill ci ha fermato! :)

Ho fatto qualcosa di simile con la formattazione delle stringhe di Python. Prendi il documento LaTeX sopra e "tokenize" il file inserendo nel documento i token %(placeholder_name1)s. Per esempio, dove si desidera che il nome della classe per andare, usare %(course_name)s

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

Poi, da Python, è possibile caricare in quel modello e formattarlo come:

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

Se si vuole trovare quelli gettoni automaticamente, il seguente dovrebbe fare abbastanza bene:

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') 

il codice sarà iterare attraverso i gettoni e stampare un prompt alla console voi per chiedere un ingresso per ogni gettone. Nell'esempio di cui sopra, si otterrà due prompt (con l'esempio le risposte):

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

L'ultima riga chiama pdflatex sul file risultante e genera un file PDF da esso. Se vuoi andare oltre, puoi anche chiedere all'utente un nome di file di output o prenderlo come opzione da riga di comando.

+0

Avevo bisogno di aggiungere 'shell = True' per subprocess call. – TimP

+0

Dato che ci piace troppo, voglio vedere la risposta Jinja! – sleblanc

3

C'è anche una Template classe (dal 2.4) che consente di utilizzare il token $that anziché %(thi)s.

+0

Si può usare anche Jinja2: http://flask.pocoo.org/snippets/55/ – alexpirine