PythonTex by Examples
PythonTex by Examples
1
1 Relevant resources used
[3] B. Nettles and G. Poore. Using Python and pdflatex to Generate Cus-
tomized Physics Problems. 18 slides, 2016. URL: https://www.aapt.o
rg/docdirectory/meetingpresentations/WM16/AAPTpaper CI07 Net
tles.pdf [cited 2022-02-12].
[4] Günter Partosch. Wie kann ich die Möglichkeiten von Python für LaTeX
nutzen? 148 slides, 2019. URL: https://github.com/GuenterPartos
ch/Vortraege-Kurse/blob/master/TeX+LaTeX/python+latex-alles.
pdf [cited 2022-03-08].
[6] G. Poore. The PythonTeX package. Last version from 2021-06-06. URL:
https://ctan.org/pkg/pythontex [cited 2022-02-11].
[7] G. Poore. PythonTeX: Fast Access to Python from within LaTeX. 20:45
min presentation from SciPy2012, 2012. URL: https://www.youtube.
com/watch?v=yIO4l0zHGjw [cited 2022-02-12].
2
2 Command overview and some preliminary
remarks
• Comments in LaTeX start with %, but in Python with #.
To interchange these characters is a typical beginner’s pitfall, especially
if the tex file contains both sorts of code.
3
– pygments General code typesetting
– pyconsole Simulates an interactive Python console, i.e.
executes the commands (like pycode) after >>>
– pythontexcustomcode Code executed like pycode, but also prints
are not shown.
• Generally, PythonTeX offers 7 inline commands to be used within nor-
mal LaTeX running text:
– \py Evaluates a Python expression and prints its value. Here
also functions defined via pycode can be used.
– \pyc Executes code, output goes to stdout, does not typeset it
– \pyb Executes code, but outputs only the code prettyprinted.
To show anything printed, use \printpythontex or \stdoutpythontex.
– \pys Supports variable and expression substitution
– \pyv Prettyprints code (nothing is executed).
- Same as \pygment{python}
- Other than the pyverbatim env no new paragraph is created.
– \pygment General code typesetting
– \pycon Accesses a variable from a previous pyconsole block
• PythonTeX provides many additional features, e.g. with the mathescape
option and the fvextra package. See documentation.
• The depythontex utility creates a copy of a document in which all
PythonTeX commands and environments have been replaced by their
output. The resulting document is more suitable for journal submis-
sion and conversion to other document formats. This is necessary as
many publishers will not accept LaTeX documents that require special
packages or need special macros.
4
3 Execute Python code with pycode and eval-
uate Python expressions with py and pyc
The \py command sends code to Python, and Python returns a string rep-
resentation of the code. Opening and closing delimiters must be either a
pair of identical, non-space characters, or a pair of curly braces. If curly
braces are used as delimiters, then curly braces may only be used within the
code if they are paired. Thus, \py{1+1} sends the code “1+1” to Python,
Python evaluates the string representation of this code, and the result “2” is
returned to LaTeX. The commands \py#1+1# and \py@1+1@ would have
the same effect. The command can also be used to access variable values.
For example, if the code “a = 1” had been executed previously, then \py{a}
simply brings the string representation of a back into the document as “1”.
Assignment is not allowed using \py. For example, \py{a = 1} is not valid.
This is because assignment cannot be converted to a string. The text returned
by Python must be valid LaTeX code. Verbatim and other special content
is allowed. The primary reason for using \py rather than print is that \py
is more compact.
5
10 \ begin { pyblock }[][ numbers = left ]
11 a , b = 2 ,3
12 print (a , b , ' Sum : ' , a + b )
13 \ end { pyblock }
14 \ stdoutpythontex % \ printpythontex
15
16 \ begin { pyblock }[][ numbers = left ]
17 a = 5
18 print ( ' Changed in second block : a = ' , a )
19 \ end { pyblock }
20 \ printpythontex % \ stderrpythontex
21
22 \ vspace {1 cm }\ noindent The variable is $a =\ py { a } $ .
23
24 \ end { document }
And here is the output of the code in the above listing. The code within
the blocks is printed (with highlighting). The results (outputs of print) are
shown by calling stdoutpythontex and printpythontex after the blocks.
1 a,b = 2,3
2 print(a, b, 'Sum: ', a+b)
2 3 Sum: 5
1 a = 5
2 print('Changed in second block: a = ', a)
The variable is a = 5.
6
3.2 Execute Python code with pycode and numpy
1 \ begin { pycode }
2 print ( r '\ begin { center } ')
3 print ( r '\ textit { A message from Python !} ')
4 print ( r '\ end { center } ')
5
6 print ( " [ pycode ] Hello \ LaTeX " )
7 import numpy as np
8 \ end { pycode }
9
10 [ After the pycode block ] Random value via Python and np : \
py { np . random . randint (10) }
[After the pycode block] Random value via Python and np: 1
Remarks:
a) After beginpycode there is no comment allowed.
b) The code inside the block must begin in the 1st column.
We get “None” at the end because \py additionally evaluates the expres-
sion. For print it’s better to use \pyc instead of \py which works like
begin{pycode} and avoids “None”.
7
1 \ pyc { print ( " [ pyc ] Hello \ LaTeX 3 " ) }
2
3 [ py ˜] \ py {2+5}
[py ] 7
For calculating 2+5 we need the evaluation, so \py was correct [using \pyc
here causes an pdflatex error].
8
1 Via \ pygment { latex }{\ py }: $ 2ˆ{100}=\ py {2**100} $
2
3 Via \ pygment { latex }{\ py }: $ 2ˆ{100}=\ py { print ( " {: ,} " . format
(2**100) ) } $
4
5 Via \ pygment { latex }{\ pyc }: $ 2ˆ{100}=\ pyc { print ( " {: ,} " .
format (2**100) ) } $
6
7 Via \ pygment { latex }{\ pyc } and using a function for German
number separation :
8 \[
9 2ˆ{100}=\ pyc { print ( A d d P o i n t A s T h o u s a n d s S e p a r a t o r (2**100) ) }
10 \]
11
12 \ begin { p y t ho n t ex c u st o m co d e }{ py }
13 def A d d P o i n t A s T h o u s a n d s S e p a r a t o r ( x ) :
14 if x < 0:
15 return ' - ' + A d d P o i n t A s T h o u s a n d s S e p a r a t o r ( - x )
16 result = ' '
17 while x >= 1000:
18 x , r = divmod (x , 1000)
19 result = " .%03 d % s " % (r , result )
20 return " % d % s " % (x , result )
21 \ end { p y t ho n t ex c u st o m co d e }
Via \py: 2100 = 1, 267, 650, 600, 228, 229, 401, 496, 703, 205, 376N one
Via \pyc: 2100 = 1, 267, 650, 600, 228, 229, 401, 496, 703, 205, 376
2100 = 1.267.650.600.228.229.401.496.703.205.376
Remark 1: In the second line we get “None” at the end because \py addi-
tionally evaluates the expression. For print it’s better to use \pyc like in
the third line (instead of \py), which avoids “None”.
9
3.6 Use variable and function inside the pycode block
1 \ begin { pycode }
2 x = 3
3 f = x **2; g = 1 / f
4 print ( 'f : ' , f , ' ˜˜˜//˜˜˜ g : ' , g , ' ˜˜˜//˜˜˜ ')
5
6 def h ( x ) :
7 return ( x **3)
8
9 print ( 'h (3) : ' , h (3) )
10 \ end { pycode }
11
12 % [ latex and py ]
13 [ After the pycode block ] The variable $x$ and the function
$h$ are also known outside the pycode block : ˜ $x$ = \ py { x
} , ˜˜ $h (4) $ = \ py { h (4) }.
f: 9 // g: 0.1111111111111111 // h(3): 27
[After the pycode block] The variable x and the function h are also known
outside the pycode block: x = 3, h(4) = 64.
10
3.8 Invert a string / exchange first and last letter /
pow (LaTeX commands defined with \py)
Power: 256
11
4 pyb: Just show the Python code with \pyb
\pyc and \pyb both execute the Python code. Then \pyc writes the output
to stdout, but does not typeset the code. \pyb does it the other way around
and outputs only the code prettyprinted.
1 {[} pyb :{]} \ pyb { '1 Python says hi !\ n '}
2 {[} pyb :{]} \ pyb { print ( '2 Python says hi !\ n ') }
3 {[} pyc :{]} \ pyc { print ( '3 Python says hi !\ n ') }
>>> x = 87.27
>>> x = x**2
>>> x
7616.0529
Remark: By default, the results from the console is printed in grey. For the
pyconsole block this can be turned to black by adding in the preamble:
\setpygmentspygopt[pyconsole]{style=bw}
However this didn’t effect how \pycon colored the output.
12
6 Samples with Sympy
The following sample from PythonTeX Gallery shows how PythonTEX can
do some amazing document automation, such as this derivative and integral
table. With latex() used in sympyblock the mathematical terms are nicely
formatted. Without sympy and only using Python, functions like sin are not
accessible.
13
Here only the source code follows which is WITHIN the sympy block. This
is just to show, that sympyblock prints the source code (independent of
our listing). The alternative sympycode would not print the source code
by itself.
1 var('x')
2
9 print(r'\begin{align*}')
10
11 for func in funcs:
12 # Put in some vertical space when switching to arc
13 # and hyperbolic funcs
14 if func == 'asin(x)' or func == 'sinh(x)':
15 print(r'&\\')
16 myderiv = 'Derivative(' + func + ', x)'
17 myint = 'Integral(' + func + ', x)'
18 print(latex(eval(myderiv)) + '&=' +
19 latex(eval(myderiv + '.doit()')) + r'\quad & \quad')
20 print(latex(eval(myint)) + '&=' +
21 latex(eval(myint+'.doit()')) + r'\\')
22
23 print(r'\end{align*}')
This text here is just to emphasize that the output is printed only when
calling \printpythontex in the document.
14
d Z
sin (x) = cos (x) sin (x) dx = − cos (x)
dx
d Z
cos (x) = − sin (x) cos (x) dx = sin (x)
dx
d Z
tan (x) = tan2 (x) + 1 tan (x) dx = − log (cos (x))
dx
d 1 Z √
asin (x) = √ asin (x) dx = x asin (x) + 1 − x2
dx 1 − x2
d 1 Z √
acos (x) = − √ acos (x) dx = x acos (x) − 1 − x2
dx 1 − x2
d 1 Z
log (x2 + 1)
atan (x) = 2 atan (x) dx = x atan (x) −
dx x +1 2
Remark:
It is possible to show the value of a variable from the previous sympy block
in the LaTeX environment like it was done with variables from the pycode
block (see Sections 3.6 and 12.1). However, not via \py and only in math
mode – thanks to Geoff Poore.
Explanation: sympy wraps its arguments with the latex() function to handle
math, so it often needs math mode depending on the situation. Using py
doesn’t work because all commands with “py” vs “sympy” in the names
execute code in separate sessions or interpreters. So there isn’t shared data
between code executed with the different sets of commands.
15
6.2 Integration of a term. Source is executed via pycode
importing sympy functions
The integration using the sympy function \int worked well, but the output
of the function and the presentation of the results differed:
- fraction versus decimal number (1a versus 1b)
- root sign version exponent as fraction (1a versus 1b)
- root sign versus others (1a versus 1b and 2b)
In addition, in the second sub section I tried to not write the function term
twice.
1 \ begin { pycode }
2 from sympy import *
3 x = symbols ( 'x ')
4 result1a = latex ( integrate ( " (1+ x ) **(1/2) " ,x ) )
5 result2a = latex ( integrate ((1+ x ) **(1/2) ,x ) )
6 # %??? result3a = latex ( integrate ( str ((1+ x ) **(1/2) ) ,x ) )
7 \ end { pycode }
8
9 1 a Result of integrating $ \ int \ sqrt {1+ x } \ , dx$ is : $ \ py {
result1a } $ \\
10 2 a Result of integrating $ \ int \ sqrt {1+ x } \ , dx$ is : $ \ py {
result2a } $ \\
11 % 3 a Result of integrating $ \ int \ sqrt {1+ x } \ , dx$ is : $ \ py
{ result3a } $ \\
R√ 3
1a Result of integrating 1 + x dx is: 2(x+1)
2
R√ 3
2a Result of integrating 1 + x dx is: 0.666666666666667 (x + 1)1.5
16
6.2.2 Write down the math function f only once
The following sample tries to define the code for a function f only once. The
aim was to have here the same output as in Section 6.2.1 in the first line
(1a).
3
1b Result of integrating (1+x)**(1/2) dx is: 2(x+1)
R 2
3
2b Result of integrating (x + 1)0.5 dx is: 0.666666666666667 (x + 1)1.5
R
To avoid flaws we tried to write down the code defining f only once. In
this attempt the terms are still not displayed in a consistent way (we wanted
fractions of integers, no decimal numbers).
17
[Remark: Showing it with fractions would be the default with the SageTeX
package (https://doc.sagemath.org/html/en/tutorial/sagetex.html).
Also see the SageMath appendix of the CrypTool Book at https://www.cr
yptool.org/en/documentation/ctbook/.]
Z
1c Result of integrating (x + 1)0.5 dx = 0.666666666666667 (x + 1)1.5
3
Z √ 2 (x + 1) 2
2c Result of integrating x + 1 dx =
3
The following code snippet bundles the code in the pycode block from Sec-
tion 6.2.1 into a function [the code of this subsection is from the website
18
https://www.12000.org/my notes/python in latex/index.htm, Sec-
tion 3 “Calling Python passing an argument to process it and getting the
LaTeX back”, which reuses many samples from the references listed at Sec-
tion 1 and offers for each sample a ready-to-run LaTeX document]. This
could be further improved by defining it like in the above paragraph b) Sym-
bolic definition of the integral.
1 \ begin { pycode }
2 from sympy import *
3 def inte ( theIntegrand , var ) :
4 var = symbols ( var )
5 anti = integrate ( theIntegrand , var )
6 return latex ( anti )
7 \ end { pycode }
8
√
The result of integrating √1 dx is given by 2 x + 1
R
1+x
19
Here is a list of six integrations:
Z
1 √
√ dx = 2 x + 1
1+x
Z
sin x dx = − cos (x)
Z
x sin x dx = −x cos (x) + sin (x)
Z
x2 sin x dx = −x2 cos (x) + 2x sin (x) + 2 cos (x)
Z
(2x − 1) e2x
xe2x dx =
4
Z
1
du = log (u + 1)
1+u
20
7 Create and expand binoms with Sympy
This sample is from [1], Section 3.2.1 “Mathematik und Formelsatz”, written
by Karsten Brodmann. Very similar code is in [4], 2018, slide 36 by G.
Partosch, and in [2], 2013, slide 28 by Mertz/Slough.
1 \ begin { pycode }
2 from sympy import *
3 x , y = symbols ( " x y " )
4 binome = []
5 for exponent in range (3 , 10) :
6 binome . append (( x + y ) ** exponent )
7 print ( r " \ begin { align *} " )
8 for expr in binome :
9 print ( r " % s &= % s \\ " % ( latex ( expr ) , latex ( expand ( expr ) ) ) )
10 print ( r " \ end { align *} " )
11 \ end { pycode }
The latex command from sympy does the setting of the formulas. The print
command from pycode outputs the LaTeX code for this document.
21
8 Create and include a function plot with
matplotlib
The paper [1] referred before in Section 7 has two more interesting samples:
• Section 3.2.4 for creating a function plot with pylab instead of math-
plotlib)
Below is the one for creating a function plot (very similar code is in [4], slide
78-82 (file pytex38.text) and in [2], slide 33) which seems to be the origin).
As pylab which was used in the cited literature, is depricated it was substi-
tuted here by the two imports (matplotlib and numpy) which pylab called
internally.
1 \ begin { pycode }
2 from matplotlib . pyplot import *
3 from numpy import *
4
5 def f ( t ) :
6 return cos (2 * pi * t ) * exp ( - t )
7
8 t = linspace (0 , 10 , 500)
9 y = f(t)
10 clf ()
11 figure ( figsize = (5 , 3) )
12 rc ( " text " , usetex = True )
13 plot (t , y )
14 title ( r ' Ged \" ampfter exponentieller Zerfall ') # Achtung :
Umlaut !
15 text (6 , 0.15 , r " $y = \ cos (2 \ pi t ) e ˆ{ - t } $ " )
16 xlabel ( " Zeit ( t ) " )
17 ylabel ( " Spannung ( mV ) " )
18 savefig ( " zerfall . pdf " , bbox_inches = " tight " )
19 print ( r " \ begin { center } " )
20 print ( r " \ includegraphics [ width =0.9\ textwidth ]{ zerfall . pdf } " )
21 print ( r " \ end { center } " )
22 \ end { pycode }
22
The pycode sample above generates the following plot (with German labels)
and stores it in the file “zerfall.pdf”.
0.75
Spannung (mV)
0.50
0.25
y = cos(2πt)e−t
0.00
−0.25
−0.50
0 2 4 6 8 10
Zeit (t)
And here the according version with English labels from [2]:
0.75
0.50
voltage (mV)
0.25
y = cos(2πt)e−t
0.00
−0.25
−0.50
0 1 2 3 4 5
time (s)
23
9 Sample: Python code with internet calls;
result written in table
Via \pyc and \py the stock price at March 8, 2022 at 15:15:
24
10 Create a list with Python and show it with
LaTeX
Creating lists in Python is much easier than creating them purely with LaTeX
syntax. Here, two lists are defined in Python and then shown in LaTeX.
1 \ begin { pycode }
2 my_list1 = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9]
3 print ( " my \ _list1 : " , my_list1 , " \ n " )
4 result = filter ( lambda x : x % 2 == 0 , my_list1 )
5 resultL = list ( result ) # Assign to a variable to have access
more than once .
6
7 print ( " resultL : " , resultL , " ˜˜˜˜˜( elements of my \ _list1
which can be divided by 2) \ n " )
8
9 print ( " Second value in my \ _list1 : " , my_list1 [1] , " \ n " ) #
escape necessary
10 print ( " Second value in resultL : " , resultL [1] , " \ n " )
11 \ end { pycode }
12
my list1: [1, 2, 3, 4, 5, 6, 7, 8, 9]
After the pycode block a variable defined in the block can be accessed
in the LaTeX text via \py:
Second value in my list1: 2
Second value in resultL: 4
25
Here is another pycode block, now with strings instead of numbers in the
list:
1 \ begin { pycode }
2 my_list2 = [ " alpha " , " beta " , " gamma " ]
3 print ( " my \ _list2 : " , my_list2 , " \ n " )
4 \ end { pycode }
26
11 Dynamic creation of a tabular environ-
ment using a Python loop
LaTeX tables can be created dynamically using pyblock. The loop variable
can be passed over and used as index for arrays defined in another pyblock.
The Python code generates the LaTeX commands to build the table. The
LaTeX code is shown via printpythontex. And these LaTeX commands are
then processed with the TeX engine to show the resulting table.
Remark: Instead of pyblock and printpythontex, we could have also used
lstlisting and pycode (like we did before).
anfang, ende = 1, 5
print(r"\begin{tabular}{r|r}") # raw string r"..." saves burdon
print(r"$m$ & $2ˆm$ \\ \hline") # of escaping backslash.
for m in range(anfang, ende + 1):
print(m, "&", 2**m, r"\\")
print(r"\end{tabular}")
m 2m
1 2
2 4
3 8
4 16
5 32
27
Explanation: What and how many statements can be put between the end
of the pyblock and the call of \printpythontex?
Here again, the PythonTeX code generates the LaTeX commands to build
the table.
Again pyblock and printpythontex are used like in Section 11.1: pyblock
generates the LaTeX code and prints the code within the block; printpythontex
is needed to print the results.
The table created has 2 columns: The first col is the running index of the
loop; the second column contains the array elements of my list2, defined in
Section 10.
print(r"\begin{tabular}{l|r} \toprule")
print(r"Number & String \\ \midrule")
for i in range(0, len(my_list2)):
print(i+1, "&", my_list2[i], r"\\")
print(r"\end{tabular}")
Number String
1 alpha
2 beta
3 gamma
28
12 Passing variables – Subsections here show
what works well
Current STATUS: Using variables from LaTeX and pycode being passed to
a PythonTeX command like \py works well.
29
Remark 1: What doesn’t work is passing \py{mypyvar} or \pyc{mypyvar}
as function argument instead of mypyvar:
1 \ begin { pyverbatim }
2 \ pyc { Primzahlen1 (\ py { mypyvar }) }. % PythonTeX error
3 \ pyc { Primzahlen1 (\ pyc { mypyvar }) }. % PythonTeX error
4 \ end { pyverbatim }
aa 6
bb 6
cc 2 3 5 7 11 and 13
Remark: Indentation and vertical parskip are tricky, if the print calls are
within \pycode. It’s better to do the prints not in the pycode block but
afterwards in LaTeX and with inline calls to \py.
AFTER finishing pycode an inline call in LaTeX text is made with \py{sols}
and \py{sols[1]}:
30
1 ˜˜˜ sols : \ py { sols }\\
2 ˜˜˜ Second value in sols : \ py { sols [1]}
31
12.2 Passing LaTeX variables as a parameter to a Python-
TeX command
In the next subsections, there are working samples, how to pass expanded
LaTeX parameters to a PythonTeX command [but still no passing of a param
to a self-defined pycode function which is called within a pycode block or
within a \py command. However, passing to the default print() function
works!].
The following samples show the syntax how to self-define LaTeX variables
like \def\a{1} or \def\a{\b}.
1 \ def \ a {1}
2 \ def \ b {3}
3 a1 : \ a \\
4 b1 : \ b \\
5 \ def \ a {7}
6 a2 : \ a \\
7 \ def \ a {\ b }
8 a3 : \ a \\
9 \ def \ a {3*\ b }
10 a4 : \ a \\
11 \ def \ az {\ b }
12 az1 : \ az \\
13 \ def \ az {\ b +\ a }
14 az2 : \ az
32
12.2.2 Case 2: Passing a PythonTeX context variable to pyc
xxx: 4
yyy: 3
xxx: 4 x=7
x = 3*3
33
12.2.3 Expand thesection before using it with py
a) Here, pure LaTeX methods are used to get the current section number.
1 \ newcommand {\ getcurrentref }[1]{%
2 \ ifnum \ value { # 1}=0 ??\ else \ csname the #1\ endcsname \ fi
3 }
4
5 \ indentation a Section : \ getcurrentref { section }\\
6 \ indentation a Subsection : \ getcurrentref { subsection }\\
7 \ indentation a Subsubsection : \ getcurrentref { subsubsection }
a Section: 12
a Subsection: 12.2
a Subsubsection: 12.2.3
34
b1 Section: 12
b1 Subsection: 12.2
b1 Subsubsection: 12.2.3
b2 Section: 12
b2 Subsection: 12.2
b2 Subsubsection: 12.2.3
While Sections 3.6 and 12.1 used a PythonTeX variable outside of the pycode
block, here again it is the other way around: A variable defined in the LaTeX
environment is passed to a PythonTeX command.
35
Here we use a macro defined at https://tex.stackexchange.com/questi
ons/48403.
PythonTeX cannot only handle \lipsum, but also macros like this one (loremlines)
around \lipsum, which allows to determine the number of lines (here 2):
1 \ newbox \ one
2 \ newbox \ two
3 \ long \ def \ loremlines # 1{%
4 \ setbox \ one =\ vbox {%
5 \ lipsum
6 }
7 \ setbox \ two =\ vsplit \ one to # 1\ baselineskip
8 \ unvbox \ two }
9
10 \ pyc { mytext = """ \ loremlines {2} """ } % This macro shortens
lipsum # 16 to 2 lines
11 \ py { mytext }
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida
Remark: LaTeX problem: mdframed only builds the frame for one line, even
if loremlines prints more. parbox around the \py commands created an
error. So here I gave up painting the frame.
36
13 Own function with parameters defined in
a pycode block
For the definition of these own functions sympy is used. The functions are
defined either in a pycode block or in a pythontexcustomcode block.
These functions will later be used for the experiments / tries in Section 15.
11 \ begin { pycode }
12 from sympy import prime # symbolic maths , here prime
numbers
13 def Primzahlen2 ( n ) : # definition of a Python
function
14 for i in range (1 , n ) :
15 print ( prime ( i ) , " " ) # next prime number
16 print ( " and " , prime ( n ) ) # last prime
17 \ end { pycode }
37
18
38
13.2 Pass a variable as input to a self-defined pycode
function in a loop
While in Sections 13.1 and 13.1 each of the parameters “9” and “7” had to
be written twice (in the LaTeX text after “first” and as parameter for the
function Primzahlen<1,2>),
1 [ p y t ho n t ex c u st o m co d e ] The first 7 primes are \ py {
GenPrimeList (7) }.
we like to pass the value of the parameters only once, and we want to use a
variable for this (makes it easier to keep documents consistent and flexible).
1) Within a loop: We’d like to pass the loop index (variable) as input pa-
rameter. This works. See Section 14.
2) Passing the PythonTeX variable mylavar to \py also works well. When
passing the variable to the self-defined function Primzahlen1() within \pyc,
mind the difference that it doesn’t work, when being passed via another \py
statement, but it works when just passed directly via mylarvar:
1 \ pyc { mylavar = 11} % defining a LaTeX variable
2 The first \ py { mylavar }˜ primes % ok .
3 are \ pyc { Primzahlen1 ( mylavar ) }. % ok .
39
1 \ begin { p y t ho n t ex c u st o m co d e }{ py }
2 def Pr in tW ho le Se nte nc e ( n ) :
3 print ( " The first % d primes are " % ( n ) )
4 Primzahlen1 ( n )
5 print ( " . " )
6 \ end { p y t ho n t ex c u st o m co d e }
7
However, passing a variable instead of the fixed number “14” first didn’t
work in the step where it is passed to the self-defined PythonTeX func-
tion Primzahlen1 within the LaTeX macro (we tried with mylavar, with a
PythonTeX context variable and with a LaTeX variable \y).
What’s needed is to define LaTeX variables first and then insert their expan-
sion into PythonTeX commands. The solution can be found in Section 15.8.
So here is the first try of a LaTeX macro which only works, if no variables
are passed.
1 \ newcommand \ L a T e X C m d W h o l e S e n t e n c e P l u s F c t C a l l [1]{%
2 The first # 1 primes are \ pyc { Primzahlen1 (#1) }.
3 }
4
5 \ L a T e X C m d W h o l e S e n t e n c e P l u s F c t C a l l {14}
40
14 Using the loop counter as parameter for
a self-defined PythonTeX function
15 / 2 3 5 7 11 13 17 19 23 29 31 37 41 43 and 47
16 / 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 and 53
17 / 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 and 59
41
Count Primes list
1 [2]
2 [2, 3]
3 [2, 3, 5]
4 [2, 3, 5, 7]
5 [2, 3, 5, 7, 11]
6 [2, 3, 5, 7, 11, 13]
TEST2
42
4) Compare the output via \py{GenPrimeList(7)} to the one via \py{Primzahlen1(7)}.
Both print a sentence (no table, no loop here):
1 The first 7 primes are \ pyc { Primzahlen1 (7) }.
2
3 The first 7 primes are \ py { GenPrimeList (7) }.
4
5 Get rid of the brackets of the list :\\
6 The first 7 primes are \ pyc { print (* GenPrimeList (7) , sep = " ,
" ) }.
7
8 Get rid of the brackets of the list and of the commas :\\
9 The first 7 primes are \ pyc { print (* GenPrimeList (7) ) }.
43
15 Passing variables – a major issue? No.
Here are some experiments when several students tried to pass LaTeX (or
PythonTeX) variables as parameters to a self-defined pycode function which
is called within a pycode block or within a \py command. These tries were
done to make the goal described in Section 13.2 work. Despite they failed
in the first run, these tries are listed for didactical purposes.
[myLvar] 6
What worked in Section 12.2.2 was passing a LaTeX variable to \pyc via the
Python context.
44
What doesn’t work is passing a variable defined with \newcommand or \newcounter
to \py:
1 \ newcommand {\ varname }{88}
2 \ varname
3 % ˜˜˜\ py {88+3} % ok .
4 % ˜˜˜\ py {\ varname } % PythonTeX error
5
6 \ newcounter { mycounter }{ " my \ _string " }
7 % ˜˜˜\ py {88+5} % ok .
8 % \ py {\ mycounter } % PythonTeX error
9 % \ py {\ themycounter } % PythonTeX error
10
11 \ newcommand {\ pyvarname }[1]{\ py { # 1}}
12 \ pyvarname {88+7} % ok .
13 % ˜˜˜\ pyvarname {\ varname } % PythonTeX error
88
95
mylavar: 6
45
1 \ verb ! pytex . context . xxx !: \ pyc { print ( ' xxx : ' , pytex .
context . xxx ) } OK
2
3 % \ pyc { Primzahlen1 (\ pyc { pytex . context . xxx }) } % PythonTeX
error
4 % \ pyc { Primzahlen1 (\ py { pytex . context . xxx }) } % PythonTeX
error
5 % \ pyc { Primzahlen1 ( pytex . context . xxx ) } % PythonTeX error
pytex.context.xxx: xxx: 4 OK
x: 12
avar: 13
46
15.4 Try 4: Passing a LaTeX variable via pysub
Sadly, this approach didn’t work in our experiment when using variables.
9 \ begin { pysub }
10 \ begin { Verbatim }
11 [ From in pysub ]: x = !{2**16} % Note , this does not assign
to a variable x !
12 [ From in pysub ]: $y = !{2**8} $
13 [ From in pysub ]: xpp = !{ xpp }
14 # [ From pysub ]: \ xpp * 5 % This doesn 't do any calculation
15 # [ From pysub ]: !{\ xpp * 5} % PythonTeX error
16 \ end { Verbatim }
17 \ end { pysub }
18
19 [ From latex : \ textbackslash {} xpp *5]: $ \ xpp * 5 $ \\
20 [ From pys : value ]: \ pys {\ verb | calculated value = !{2**7}|}\\
21 [ From pys : xpp ]: \ pys {\ verb | value = !{ xpp }|}
22 [ From pys : 5* xpp ]: \ pys {\ verb | calculated value = !{5* xpp }|}
47
[From latex: xpp]: 30
48
⇒ It works like it should: The expression !{1+2} is correctly evaluated. The
function itself is not called. The LaTeX variable was expanded successfully
and worked as function parameter too.
Summary:
The following sample uses pys instead of pysub (and no variable is involved):
1 1: \ pys {\ verb | calculated value = !{2**7}|}\\ % Ok
2 2: \ pys {\ verb | calculated value = !{(1+2) }|}\\ % Ok
3 % x : \ pys {\ verb |!{ Primzahlen1 (1+3) }|} % Nok : LaTeX error
: \ verb ended by end of line .
4 3: \ pys {\ verb | Primzahlen1 (!{1+2}) |}\\ % Ok : just prints
" Primzahlen1 (3) "
5 4: Primzahlen1 (\ pys {\ verb |!{1+2}|}) \\ % Ok : just prints
" Primzahlen1 (3) "
a) Within pgfmath LaTeX variables (here avarx) can be handled like this.
1 \ newcommand {\ avarx }{10}
2 [ latex - pgf ]: 87 divided by \ avarx ˜ is approximately \
pgfmathparse { int ( round (87/\ avarx ) ) }\ pgfmathresult .
49
[latex-pgf]: 87 divided by 10 is approximately 9.
b) This approach (with counters) can also only work when the LaTeX vari-
able has been expanded before.
1 \ newcounter { mycounter } % Initializing the value to 0
2 \ setcounter { mycounter }{12} % Changing this value to 12
3 \ pyc { Primzahlen1 (\ value { mycounter }) } % PythonTeX error
4 \ pyc { Primzahlen1 (\ themycounter ) } % PythonTeX error
50
15.6 Try 6: Calling a LaTeX macro within pycode does
not work
Just a note, what was tried too: It is clear that the following code doesn’t
work as LaTeX macros like LaTeXCmdWholeSentencePlusFctCall() (de-
fined in Section 13.2) are not known within the pycode block.
1 \ begin { pycode }
2 print (3 , r " \\ " )
3 print (\ L a T e X C m d W h o l e S e n t e n c e P l u s F c t C a l l {15} , r " \\ " ) #
PythonTeX error
4 \ end { pycode }
What worked was passing a LaTeX variable to \py via the Python context
(see Section 12.2.2).
51
-x-
-x-
-x-
52
Loop # 19 / 19:
87 42 – 19 19 361 361
Loop # 20 / 20:
87 42 – 20 20 400 400
53
15.8 Conclusion / Solution for passing LaTeX vari-
ables
If you want to pass LaTeX commands to Python, you need to define a custom
command to work around LaTeX tokenization. Everything inside Python-
TeX commands/environments is interpreted as pure Python (no LaTeX in-
terspersed), so you need to create new commands that will expand macros
and then insert the expansion into PythonTeX commands.1 Exactly what
you need depends on the macros you want to pass to Python. For simple
macros that only require one level of expansion, you could do something like
this:
1 \ def \ varint {123}
2 \ def \ varstring { string }
3
4 \ newcommand {\ inttopy }[2]{\ expandafter \ inttopytwo \
expandafter { # 2}{#1}}
5 \ newcommand {\ inttopytwo }[2]{\ pyc { # 2=#1}}
6 \ newcommand {\ strtopy }[2]{\ expandafter \ strtopytwo \
expandafter { # 2}{#1}}
7 \ newcommand {\ strtopytwo }[2]{\ pyc { # 2="#1"}}
8
9 \ inttopy { varint }{\ varint }
10 \ strtopy { varstring }{\ varstring }
11 \ verb |\ varint | is \ py { varint } and \ verb |\ varstring | is \ py {
varstring }.
Passing #1 to the PythonTeX function worked fine, but the first usage of #1
just showed the variable name and not its value. So the definition had to be
1
Thanks to Geoff Poore for his great support.
54
slightly reworked to always make PythonTeX handle the parameter #1. This
was the change: The first #1 primes ==> The first \py{#1} primes
1 \ newcommand \ w L a T e X C m d W h o l e S e n t e n c e P l u s F c t C a l l [1]{%
2 The first \ py { # 1} primes are \ pyc { Primzahlen1 (#1) }.
3 }
55
Contents
3.8 Invert a string / exchange first and last letter / pow (LaTeX
commands defined with \py) . . . . . . . . . . . . . . . . . . . 11
56
6.2 Integration of a term. Source is executed via pycode importing
sympy functions . . . . . . . . . . . . . . . . . . . . . . . . . . 16
11.1 Print the code of a pyblock environment and print the code’s
result via printpythontex . . . . . . . . . . . . . . . . . . . . 27
57
12.2.2 Case 2: Passing a PythonTeX context variable to pyc . 33
15.6 Try 6: Calling a LaTeX macro within pycode does not work . 51
58