[Tex/LaTex] Embedding python in tikz

pythontikz-pgf

I just discovered the python package, and I'm trying to use it in Tikz code. Unfortunately, this doesn't work:

\documentclass[oneside]{memoir}
\usepackage{pgfplots}
\usepackage{python}

\begin{document}
\begin{figure}[H]
\centering
\begin{tikzpicture}
    \draw (0, 0) -- (
\begin{python}
print(1)  # note that my default Python version is 3.2, so this works outside the tikzpicture environment. 
\end{python}
, 0);
\end{tikzpicture}
\caption{Blah.}
\end{figure}
\end{document}

The first error I get is:

Runaway argument? {pgf@tempcolor}{\def \@currenvir {python}\edef
\@currenvline {\on@line \ETC. ! Paragraph ended before \XC@definec@lor
was complete.
\par l.13 print(1)

I suspect you've forgotten a `}', causing me to apply this control
sequence to too much text. How can we recover? My plan is to forget
the whole thing and hope for the best.

Is it possible to get something like this work? Maybe with a different python package? Also, is there a way to make it so that the Python definitions persist between embedded environments?

Best Answer

You may be interested in my PythonTeX package. It only executes Python code when it is modified, saves all Python-generated results, and provides persistence between environments/commands.

I expect that part of the problem you were running into in your example relates to the internal workings of \draw. I couldn't get an equivalent example to work with my package either, and received similar errors. However, the following example does work. Note that the pycode environment currently cannot be indented, so the formatting is a little different than your example. Also, the \py and \pyc are for inline use, when you don't need a whole environment. \pyc executes code, and \py returns a string representation of whatever it is given.

\documentclass[oneside]{memoir}
\usepackage{pgfplots}
\usepackage{pythontex}

\begin{document}
\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{pycode}
a = 2
print(r'\draw (0, 0) -- ({0}, 0);'.format(a))
\end{pycode}
\pyc{b = 3}
\py{r'\draw (0, 0) -- ({0}, 1);'.format(b)}
\end{tikzpicture}
\caption{Blah.}
\end{figure}
\end{document}

Update August 2016

PythonTeX now has commands and environments for variable substitution/string interpolation. A version of the example rewritten to use one of these is included below.

Everything in the pysub environment is passed to Python verbatim. Substitution fields take the form !{<expression>}. If <expression> starts or ends with a literal curly brace, then a space should be added to separate the curly brace that is part of <expression> from the delimiting braces. If <expression> contains unpaired curly braces, then more delimiters may be used. For example, !{{{<expression>}}} would allow <expression> to contain any combination of unpaired {, {{, }, or }} (basically, any sequence of braces shorter than the delimiters). More details are available in the PythonTeX documentation.

\documentclass[oneside]{memoir}
\usepackage{pgfplots}
\usepackage{pythontex}

\begin{document}
\begin{figure}[h]
\centering
\begin{pycode}
a = 2
b = 3
\end{pycode}
\begin{pysub}
\begin{tikzpicture}
\draw (0, 0) -- (!{a}, 0);
\draw (0, 0) -- (!{b}, 1);
\end{tikzpicture}
\end{pysub}
\caption{Blah.}
\end{figure}
\end{document}