A LaTeX package to call Python from LaTeX.

250f54c6 added playground · by Franck Pommereau

PyTeX: a LaTeX package to call Python from LaTeX

(C) 2017 Franck Pommereau franck.pommereau@ibisc.univ-evry.fr

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.


PyTeX depends on psutil and optionally on Pygments to perform syntax highlighting.

Installation under Linux or MacOS is easy.

  1. Copy pytex.py as pytex somewhere in your PATH
  2. Make sure it is executable (chmod +x pytex)
  3. Copy pytex.sty somewhere in your TEXINPUTS

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.


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 file path that is expected to be Python code, and it outputs a LaTeX file that is included in main source if include=True, either inline or displayed depending on inline argument. If Pygments is not installed, the source code is used verbatim.
  • escape(text): returns a copy if string text 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, environment pycode 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 evaluates expression 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:

  1. latex jobname saves Python snippets
  2. pytex jobname executes Python snippets
  3. 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).