Генерация pdf-латекса с помощью скрипта Python
Я парень из колледжа, и в моем колледже, чтобы представить любую домашнюю работу, она должна иметь стандартную титульную страницу (с логотипом колледжа, названием курса, именем профессора, моим именем и бла-бла-бла).
Итак, у меня есть документ.tex, который генерирует мои стандартные страницы в формате pdf. Это выглядит примерно так:
...
\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}
...
Итак, мне было интересно, есть ли способ создать скрипт на Python, который запрашивает у меня название домашней работы, название курса и остальные строки и использует их для создания титульной страницы. После этого он должен скомпилировать.tex и сгенерировать pdf с предоставленной информацией.
Любые мнения, советы, фрагменты, библиотеки принимаются.
3 ответа
Вы можете начать с определения текстового файла шаблона в виде строки:
content = r'''\documentclass{article}
\begin{document}
...
\textbf{\huge %(school)s \\}
\vspace{1cm}
\textbf{\Large %(title)s \\}
...
\end{document}
'''
Далее используйте argparse
принять значения для курса, названия, имени и школы:
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')
Немного строкового форматирования - все, что нужно, чтобы вставить аргументы в content
:
args = parser.parse_args()
content%args.__dict__
После записи содержимого в файл cover.tex,
with open('cover.tex','w') as f:
f.write(content%args.__dict__)
вы могли бы использовать subprocess
звонить pdflatex cover.tex
,
proc = subprocess.Popen(['pdflatex', 'cover.tex'])
proc.communicate()
Вы можете добавить lpr
здесь также команда, чтобы добавить печать в рабочий процесс.
Удалить ненужные файлы:
os.unlink('cover.tex')
os.unlink('cover.log')
Сценарий может быть вызван так:
make_cover.py -c "Hardest Class Ever" -t "Theoretical Theory" -n Me
Собираем все вместе,
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')
Конечно, существуют системы шаблонов, такие как Jinja, но они, вероятно, излишни для того, что вы просите. Вы также можете отформатировать страницу с помощью RST и использовать ее для генерации LaTeX, но, опять же, это, вероятно, излишне. Черт возьми, автоматическая генерация страницы, вероятно, излишня для количества полей, которые вы должны определить, но с тех пор, когда излишняя остановка остановила нас!:)
Я сделал нечто похожее с форматированием строк в Python. Возьмите свой документ LaTeX выше и "токенизируйте" файл, поместив %(placeholder_name1)s
жетоны в документ. Например, если вы хотите, чтобы имя вашего класса пошло, используйте %(course_name)s
\textbf{\Large "%(homework_title)s" \\}
\vspace{1cm}
\textbf{\Large "%(course_name)s" \\}
Затем из Python вы можете загрузить этот шаблон и отформатировать его следующим образом:
template = file('template.tex', 'r').read()
page = template % {'course_name' : 'Computer Science 500',
'homework_title' : 'NP-Complete'}
file('result.tex', 'w').write(page)
Если вы хотите найти эти токены автоматически, следующее должно работать очень хорошо:
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')
Код будет перебирать токены и выводить на консоль приглашение, запрашивающее ввод для каждого токена. В приведенном выше примере вы получите два запроса (с примерами ответов):
Enter value for homework_title: NP-Complete
Enter value for course_name: Computer Science 500
Финальная линия звонков pdflatex
на результирующий файл и генерирует PDF из него. Если вы хотите пойти дальше, вы также можете попросить пользователя указать имя выходного файла или использовать его в качестве параметра командной строки.
Существует также класс Template (начиная с 2.4), позволяющий использовать $that
токен вместо %(thi)s
один.
Именно для этого есть библиотека Python: PyLaTeX. Следующий код взят прямо из документации:
from pylatex import Document, Section, Subsection, Command
from pylatex.utils import italic, NoEscape
def fill_document(doc):
"""Add a section, a subsection and some text to the document.
:param doc: the document
:type doc: :class:`pylatex.document.Document` instance
"""
with doc.create(Section('A section')):
doc.append('Some regular text and some ')
doc.append(italic('italic text. '))
with doc.create(Subsection('A subsection')):
doc.append('Also some crazy characters: $&#{}')
if __name__ == '__main__':
# Basic document
doc = Document('basic')
fill_document(doc)
doc.generate_pdf(clean_tex=False)
doc.generate_tex()
# Document with `\maketitle` command activated
doc = Document()
doc.preamble.append(Command('title', 'Awesome Title'))
doc.preamble.append(Command('author', 'Anonymous author'))
doc.preamble.append(Command('date', NoEscape(r'\today')))
doc.append(NoEscape(r'\maketitle'))
fill_document(doc)
doc.generate_pdf('basic_maketitle', clean_tex=False)
# Add stuff to the document
with doc.create(Section('A second section')):
doc.append('Some text.')
doc.generate_pdf('basic_maketitle2', clean_tex=False)
tex = doc.dumps() # The document as string in LaTeX syntax
Это особенно полезно для создания автоматических отчетов или слайдов.