0% found this document useful (0 votes)
12 views3 pages

Tb125ziegenhagen Python

.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views3 pages

Tb125ziegenhagen Python

.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

126 TUGboat, Volume 40 (2019), No.

Combining LATEX with Python class Person:


Uwe Ziegenhagen def __init__(self, name, age):
self.name = name
Abstract self.age = age
Even older than Java, Python has achieved a lot
of popularity in recent years. It is an easy-to-learn def print_age(self):
print(self.name + ', ' + str(self.age))
general purpose programming language, with strong
capabilities, including in state-of-the-art topics such john = Person('John', 50)
as machine learning and artificial intelligence. In john.print_age()
this article we want to present scenarios where LATEX
and Python can work jointly. We will show examples Listing 4: Using object-oriented programming
where LATEX documents are automatically generated Excellent literature is available for Python learn-
by Python or receive content from Python scripts. ers on- and offline; we can recommend [1].
1 Introducing Python 2 Writing LATEX files with Python
Python has steadily grown to be one of the most After that brief introduction we will now focus on
widely used programming languages. Invented in the creation of LATEX files using Python. The rec-
1991 by Guido van Rossum at the Centrum Wiskunde ommended approach is to use a so-called “context
& Informatica in the Netherlands, Version 1.0 ap- managers”, as it will handle the management of the
peared in 1994. The current versions are 2.7 and 3.x. file references as well as errors in case the file is not
For people who wish to start with Python, Python 3 accessible or writable.
is strongly recommended. Listing 5 shows an example on how to write a
print('Hello' + ' ' + 'World') simple LATEX file. Backslashes need to be escaped,
the line endings need to be added. Depending on the
Listing 1: The unavoidable “Hello World” example platform the code is executed, they will be replaced
by the system’s line ending. The resulting file is then
Python has a strong emphasis on code readabil-
UTF-8-encoded and can easily be processed further.
ity by making whitespace significant. In contrast to
other programming languages, Python uses white- with open('sometexfile.tex','w') as file:
space and indentation to define code blocks; a first file.write('\\documentclass{article}\n')
example is in Listing 2. file.write('\\begin{document}\n')
file.write('Hello Palo Alto!\n')
def addTwo(a, b): file.write('\\end{document}\n')
return a+b
Listing 5: Writing a TEX file
print(addTwo(5,3)) # gives 8 Processing, e. g., the compilation by pdfLATEX and
print(addTwo('U','S')) # gives 'US'
display by the system’s PDF viewer can also be trig-
Listing 2: Basic function definition example gered from Python, as Listing 5 shows. We create
the LATEX file and use Python’s subprocess module
Python supports various programming para- to call pdfLATEX. When this process has a non-error
digms, such as procedural, object-oriented and func- exit code, the platform’s PDF viewer is launched.
tional programming. Listing 3 shows an example
import subprocess, os
for the functional programming paradigm, using a
with open('sometexfile.tex','w') as file:
lambda function to filter those integers from a list file.write('\\documentclass{article}\n')
that are divisible by 2. file.write('\\begin{document}\n')
my_list = [1, 2, 3, 4, 5, 6, 7, 8] file.write('Hello Palo Alto!\n')
result = filter(lambda x: x % 2 == 0, my_list) file.write('\\end{document}\n')
print(list(result))
x = subprocess.call('pdflatex sometexfile.tex')
Listing 3: Using functional programming to filter a if x != 0:
list print('Exit-code not 0, check result!')
else:
Listing 4 shows an example for the OO-programming os.system('start sometexfile.pdf')
paradigm. Here we define a class with two properties
that is then instantiated. Listing 6: Writing & processing TEX files

Uwe Ziegenhagen
TUGboat, Volume 40 (2019), No. 2 127

When LATEX files are created programmatically the


import os
goal is often to create bulk letters or other dynami- import jinja2 as j
cally adjusted documents. Python offers various ways
to assist in this process. The most intuitive way is latex_env = j.Environment(
probably to use search & replace to eplace placehold- block_start_string = '\BLOCK{',
block_end_string = '}',
ers with text; Listing 7 shows an example for this variable_start_string = '\VAR{',
approach. The example should be self-explaining, variable_end_string = '}',
note the nested context managers to read and then comment_start_string = '\#{',
write the LATEX file. comment_end_string = '}',
line_statement_prefix = '%-',
place = 'Palo Alto' line_comment_prefix = '%#',
trim_blocks = True,
autoescape = False,
with open('place.tex','r') as myfile: loader = j.FileSystemLoader(os.path.abspath('.'))
text = myfile.read() )
text_new = text.replace('$MyPlace$', place)
The following Listing 9 shows an excerpt from the
with open('place_new.tex', 'w') as output: final code. It loads the template, fills the placehold-
output.write(text_new) ers and writes the final document to the disk. One
Listing 7: Replacing text advantage of this approach is that it allows the tem-
plate to be separated from the program logic that fills
While this approach works fine, it is not recom- it; in more complex situations, the built-in scripting
mended when more complicated documents need comes very handy.
to be created. Fortunately Python offers a variety template = latex_env.get_template('jinja-01.tex')
of template engines — either built-in or easily instal- document = template.render(place='Palo Alto')
lable with the help of Python’s package manager — with open('final-02.tex','w') as output:
that improve the workflow and avoid “re-inventing output.write(document)
the wheel”. Among the different template engines, Listing 9: Rendering the document
we have successfully worked with Jinja2. It offers
full Unicode support, sandboxed execution, template 3 Running Python from LATEX
inheritance and many more useful features. Listing 8
shows a non-LATEX example for Jinja2, which tells In this section we want to address the reverse: not the
us the following: creation of LATEX code but the execution of Python
code from within LATEX. Several packages and tools
1. Syntax is (easily) understandable
are available to support this. Here we want to demon-
2. Jinja2 brings its own notation for looping, etc. strate two of them. One is derived from code posted
3. Extensive use of {, %, } to tex.stackexchange.com, the other, pythontex, is
a well-maintained LATEX package.
from jinja2 import Template
The idea for the code given below came from
mytemplate = Template("Hello {{place}}!") the fact, that LATEX is a) able to write the content
print(mytemplate.render(place="Palo Alto")) of environments to external files and b) is able to
run external commands when --shell-escape is
mytemplate = Template("Some numbers: {% for n enabled. One just needs need to combine both to
in range(1,10) %}{{n}}{% endfor %}") write and run external files. Based on our question on
print(mytemplate.render()) TSX, an easily implementable solution was given;2
it is shown in Listing 10. When Python code is
Listing 8: A non-LATEX Jinja2 template example
placed in a pycode environment inside a document,
So, to make Jinja2 work well with LATEX we need LATEX writes the code to the filename specified in
to modify the way a template is defined. Listing 2 the parameter of the environment, runs Python on
shows1 how this reconfiguration can be made. In- this file and pipes its output to a .plog file. This
stead of braces, we use two LATEX commands, \BLOCK .plog file is then read by LATEX and typeset with
and \VAR. Both commands will later be defined as syntax highlighting provided by the minted package
empty LATEX commands in the LATEX file to have the (which also uses Python internally).
file compile without errors. The advantage of this approach is that it can
1 Source: https://web.archive.org/web/
be adjusted easily to different external programs, as
20121024021221/http://e6h.de/post/11/ 2 https://tex.stackexchange.com/questions/116583

Combining LATEX with Python


128 TUGboat, Volume 40 (2019), No. 2

long as they are able to run in batch mode. One can


\documentclass[12pt]{article}
easily adjust the way the code is included, e.g., we \usepackage[utf8]{inputenc}
have worked successfully with a two-column setup \usepackage[T1]{fontenc}
in Beamer, where the left column shows the source \usepackage{pythontex}
code and the right column the result of the code \usepackage{booktabs}
\begin{document}
execution. One disadvantage is that the programs
are executed each time the LATEX code is compiled. \pyc{from yahoo_fin import stock_info as si}

\usepackage{minted} \begin{tabular}{lr}
\setminted[python]{frame=lines, framesep=2mm, \toprule
baselinestretch=1.2, bgcolor=colBack, Company & Latest quote \\
fontsize=\footnotesize, linenos} \midrule
\setminted[text]{frame=lines, framesep=2mm, Apple & \py{round(si.get_live_price("aapl"),2)} \\
baselinestretch=1.2, bgcolor=colBack, Amazon & \py{round(si.get_live_price("amzn"),2)} \\
fontsize=\footnotesize, linenos} Facebook & \py{round(si.get_live_price("fb"),2)} \\
\bottomrule
\usepackage{fancyvrb} \end{tabular}
\makeatletter \end{document}
\newenvironment{pycode}[1]%
{\xdef\d@tn@me{#1}% Listing 11: Using pythontex to retrieve stock prices
\xdef\r@ncmd{python #1.py > #1.plog}%
\typeout{Writing file #1}%
\VerbatimOut{#1.py}%
}%
{\endVerbatimOut %
Company Latest quote
\toks0{\immediate\write18}%
\expandafter\toks\expandafter1%
\expandafter{\r@ncmd}%
Apple 203.43
\edef\d@r@ncmd{\the\toks0{\the\toks1}}%
\d@r@ncmd
Amazon 1832.89
\noindent Input
\inputminted{python}{\d@[email protected]}%
Facebook 190.16
\noindent Output
\inputminted{text}{\d@[email protected]}%
}%
\makeatother Figure 1: Output resulting from Listing 11

Listing 10: The pycode environment The pythontex package provides many more fea-
tures, among them even symbolic computation. It
The pythontex package [2] uses a more advanced
can thus be highly recommended.
approach: it can detect if the Python code has been
edited or not. Only if an edit took place is the 4 Summary
Python code rerun, thus saving time especially with We have shown how easy LATEX documents can be
more complicated Python code. The workflow is the enriched by Python, a scripting language that is easy
following: first the LATEX engine of your choice is to learn and fun to work with. Accompanying this
run, followed by the pythontex executable, followed article is the more extensive presentation held at
by another latex run. The package offers various TUG 2019, for which the interested reader is directed
LATEX commands and corresponding environments; to the slides at www.uweziegenhagen.de.
see the package documentation.
Let us show with an example (Listing 11) how References
the package can be applied. After loading the pack- [1] M. Lutz. Learning Python. O’Reilly, 2013.
age pythontex we use the \pyc command, which [2] G. M. Poore. PythonTEX: Reproducible
only executes code and does not typeset it, for the documents with LATEX, Python, and
first line of Python code. Here we instruct Python more. Comput. Sci. Disc. 8(1), 2015.
to load a function from the yahoo_fin library which ctan.org/pkg/pythontex
allows us to retrieve stock information from Yahoo,
given that an Internet connection is available.  Uwe Ziegenhagen
In the following table we then use \py com- Escher Str. 221
mands to specify which stock quote to be retrieved. 50739 Cologne, Germany
This command requires the executed Python code ziegenhagen (at) gmail dot com
to return a single expression. www.uweziegenhagen.de

Uwe Ziegenhagen

You might also like