使用Python脚本生成pdf-latex

35 投票
4 回答
80921 浏览
提问于 2025-04-17 06:04

我是一名大学生,在我的学校,提交任何作业都必须有一个标准的封面(上面要有学校的标志、课程名称、教授的名字、我的名字等等)。

所以,我有一个 .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 文件。

欢迎任何意见、建议、代码片段或库的推荐。

4 个回答

5

还有一个叫做Template的类(从2.4版本开始就有),它可以让你用$that这个符号来代替%(thi)s这种写法。

7

当然,有像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。如果你想更进一步,还可以询问用户输出文件的名称,或者把它作为命令行选项来处理。

81

你可以先把模板的tex文件定义为一个字符串:

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

撰写回答