PyTeX: a LaTeX package to call Python from LaTeX
(C) 2017 Franck Pommereau franck.pommereau@ibisc.univ-evry.fr
https://forge.ibisc.univ-evry.fr/fpom/pytex
PyTeX allows one to call Python code from a LaTeX file and to use the
result directly as if computation has been done by LaTeX. To do so, it
calls an external script named pytex
that is responsible for
executing the code and various other tasks.
Installation
PyTeX depends on psutil and optionally on Pygments to perform syntax highlighting.
Installation under Linux or MacOS is easy.
- Copy
pytex.py
aspytex
somewhere in yourPATH
- Make sure it is executable (
chmod +x pytex
) - Copy
pytex.sty
somewhere in yourTEXINPUTS
PyTeX has not yet been tested under Windows, it should work in theory,
but I don't know how to call a program pytex
and have it execute the
Python script.
Usage
You may provide Python code as \pyx{x = 5}
for a snippet that should
be passed to Python exec
, or as \pyv{x+2}
for a snippet that
should be passed to Python eval
and the computed value integrated
into the LaTeX document. You may use also the corresponding
environments pyexec
and pyeval
.
An important feature of pytex
is that all the snippets are executed
in the same environment, so that you can do something like \pyx{x=5}
balh blah \pyv{x+2} % yields 7
. If you wish to forget about all
previous computation, use \pyx{reset()}
which clears the execution
environment.
A Python function tex(s, *args)
may be called from Python snippets
to generate some LaTeX code that will be inserted in the document
instead of the snippet (and, in the case of \pyv
, after its result).
Similarly to %
or str.format
, it substitutes each occurrence of
@
in string s
with a corresponding value in args
, ensuring that
this value is correctly escaped so that it does not contain LaTeX
special characters. Having @@
in s
inserts a single @
in the
result without using args
, option char='*'
allows to use *
instead of @
(or any other character). For instance:
tex("hello") => hello
tex(r"\foo{@}", "$") => \foo{\$}
tex("@@") => @
tex("@@@+@@@", "x", char="+") => @@@x@@@
So, string s
is not escaped for LaTeX special characters, only the
args
are. Other predefined Python functions are:
-
pygmentize(path, include=True, inline=False)
: typesets the content of filepath
that is expected to be Python code, and it outputs a LaTeX file that is included in main source ifinclude=True
, either inline or displayed depending oninline
argument. If Pygments is not installed, the source code is used verbatim. -
escape(text)
: returns a copy if stringtext
in which every LaTeX special character has been properly escaped.x
Two more LaTeX commands are available:
-
\pyc{pass}
inserts a pretty printed version of the Python snippet without evaluating it, environmentpycode
is similar but for a block of code that is not inserted inline -
\pyd{name}{expression}
is similar to\newcommand{\name}{\pyv{expression}}
but avoids to evaluatesexpression
only once instead of each time\name
is invoked. (And if you ask the question: no,\edef\name{\pyv{expression}}
does not work.)
When your source file is processed by LaTeX, the Python snippets are
saved into auxiliary files that may be processed after the LaTeX pass
or online if you've enabled -shell-escape
. Note that the security
issue of using -shell-escape
exists in both methods because
arbitrary Python code may be executed anyway.
Without shell escape
Compile in three passes, like a bibTeX:
-
latex jobname
saves Python snippets -
pytex jobname
executes Python snippets -
latex jobname
inserts the result of executing Python snippets
With shell escape
Just run latex -shell-escape jobname
. Pros: you use just one command
and the results are inserted on the fly so everything is immediately
consistent. Cons: it's slower (a server version of PyTeX is launched
and communication between latex
and the server takes some time, this
may be improved in the future if this is caused by PyTeX, but I
suspect it is \write18
mechanism that is slow).