2011-11-10 22 views
25

Tôi là một anh chàng đại học, và ở trường đại học của tôi, để trình bày bất kỳ bài tập về nhà nào, nó phải có trang bìa chuẩn (với logo đại học, tên khóa học, tên giáo sư, tên tôi và bla bla bla).Tạo pdf-latex với tập lệnh python

Vì vậy, tôi có tài liệu .tex, tạo trang bìa tiêu chuẩn của tôi là pdf. Nó đi một cái gì đó như:

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

Vì vậy, tôi đã tự hỏi nếu có một cách để làm cho một kịch bản Python hỏi tôi cho danh hiệu bài tập về nhà của tôi, tên khóa học và phần còn lại của chuỗi và sử dụng chúng để tạo ra trang bìa. Sau đó, cần biên dịch tệp .tex và tạo tệp pdf với thông tin đã cho.

Bất kỳ ý kiến, lời khuyên, đoạn trích, thư viện nào đều được chấp nhận.

+1

Trình chỉnh sửa văn bản nhanh hơn IMHO. Bạn vẫn phải nhập tiêu đề, tên khóa học, v.v. mỗi lần bạn in trang bìa. Tôi muốn chuyển đổi tệp PDF đó thành mẫu từ. Thử: http://www.pdftoword.com/ –

+1

Bạn chỉ có thể sử dụng một trình quản lý đoạn mã/mẫu trong một trình soạn thảo văn bản. –

+2

đó là ý tưởng hay! nhưng tôi đang tìm kiếm thứ gì đó tự chế tạo/geek. – juliomalegria

Trả lời

53

Bạn có thể bắt đầu bằng cách xác định tập tin tex mẫu như là một chuỗi:

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

Tiếp theo, sử dụng argparse để chấp nhận giá trị cho quá trình, tiêu đề, tên và trường học:

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

Một chút định dạng chuỗi là tất cả những gì cần để gắn các arg vào trong content:

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

Sau khi viết nội dung ra một tập tin, cover.tex,

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

bạn có thể sử dụng subprocess gọi pdflatex cover.tex.

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

Bạn cũng có thể thêm lệnh lpr vào đây để thêm in vào quy trình làm việc.

Remove file không cần thiết:

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

Kịch bản sau đó có thể được gọi như thế này:

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

Đưa nó tất cả cùng nhau,

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

giải pháp khá tốt và đơn giản! bây giờ tôi có một máy phát điện bao gồm tự động :) – juliomalegria

+0

Có cách nào để kiểm tra xem các pdf đã được tạo thành công? Tôi đã tìm thấy nếu tôi có một '&' hoặc '%' trong văn bản nó phá vỡ pdf. – Johan

+0

@Johan: Tập lệnh hiển thị đầu ra của lệnh gọi tới 'pdlatex'. Nếu có lỗi khi xử lý LaTeX, các thông báo lỗi đó sẽ cho bạn biết rằng bản pdf không được tạo thành công. '&' Không phải là một ký tự đặc biệt trong Python, nhưng nó nằm trong TeX, vì vậy bạn cần phải gạch chéo nó nếu bạn muốn một ký tự chữ cái: '\ &'. '%' Là một ký tự đặc biệt trong cả Python và TeX. Tùy thuộc vào vị trí '%' được định vị, nó có thể cần phải được thay đổi thành '\%' hoặc '%%'. – unutbu

5

Có tất cả các hệ thống tạo khuôn mẫu khóa học như Jinja, nhưng chúng có thể quá mức cần thiết cho những gì bạn đang yêu cầu. Bạn cũng có thể định dạng trang bằng cách sử dụng RST và sử dụng nó để tạo LaTeX, nhưng lại có thể là quá mức cần thiết. Heck, tự động tạo trang có thể quá mức cần thiết cho số trường bạn phải xác định, nhưng vì khi nào thì quá mức cần thiết ngăn chúng tôi! :)

Tôi đã thực hiện điều gì đó tương tự với định dạng chuỗi của Python. Lấy tài liệu LaTeX của bạn ở trên và "mã hóa" tệp bằng cách đặt mã số %(placeholder_name1)s vào tài liệu. Ví dụ, nếu bạn muốn tên lớp của bạn để đi, sử dụng %(course_name)s

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

Sau đó, từ Python, bạn có thể tải trong mẫu đó và định dạng nó như:

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

Nếu bạn muốn tìm những mã thông báo tự động, những điều sau đây nên thực hiện khá tốt:

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

Mã sẽ lặp qua mã thông báo và in dấu nhắc đến bảng điều khiển yêu cầu bạn nhập cho mỗi mã thông báo. Trong ví dụ trên, bạn sẽ nhận được hai nhắc nhở (với ví dụ câu trả lời):

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

Dòng cuối cùng gọi pdflatex vào file kết quả và tạo một file PDF từ nó. Nếu bạn muốn đi xa hơn, bạn cũng có thể yêu cầu người dùng cho một tên tập tin đầu ra hoặc lấy nó như là một tùy chọn dòng lệnh.

+0

Tôi cần thêm 'shell = True' vào cuộc gọi subprocess. – TimP

+0

Vì chúng tôi thích quá mức cần thiết, tôi muốn xem câu trả lời của Jinja! – sleblanc

3

Ngoài ra còn một là Template lớp học (kể từ 2.4) cho phép sử dụng mã thông báo $that thay vì %(thi)s một.

+0

Jinja2 cũng có thể được sử dụng: http://flask.pocoo.org/snippets/55/ – alexpirine