Two problems here. (both requires understanding TeX to understand the fix.)
\py
does not expand its arguments.
(type 3 of my answer on nesting macro. See also how to pass section numbers to python in pythontex? - TeX - LaTeX Stack Exchange -- there's no completely automatic solution without learning TeX programming yet.)
One solution here is to use \expanded
(see the one inserted in the code below.) Alternative including edef, ExpandArgs, exp_args:Nx etc. (also see the linked questions from the answer linked above)
Warning: \expanded might not do what you want every time. Make sure you understand what the code does in case you want to modify it.
\py
is not expandable.
(type 2 of my answer above.)
This issue is documented in the pythontex manual.
(I include a screenshot here. If you want to read the text, read the manual.)

One workaround is to follow that, and define a Python function that prints out the whole outer thing.
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{pythontex}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{pycode}
def ggt(a,b):
r=a%b
i=0
erg=1
while r:
a=b
b=r
r=a%b
return b
def print_my_command(m, n):
print(
r'\ifnum' + str(ggt(m, n)) + r'''=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi'''
)
\end{pycode}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\expanded{\pyc{print_my_command(\m,\n)}}
}
\end{tikzpicture}
\end{document}
Although if you do this you might as well check in Python. Replace the print_my_command
with
def print_my_command(m, n):
if ggt(m, n)==1:
print(r""" \node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$}; """)
else:
print(r""" \node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$}; """)
you can also replace the \m
with the value of m
on the Python side.
Another workaround, this one requires more TeX knowledge, is to use temporary variable as explained in my answer linked above.
\documentclass{article}
\usepackage{tikz}
\usepackage[makeroom]{cancel}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{pythontex}
\usetikzlibrary{intersections,positioning,arrows.meta}
\begin{pycode}
def ggt(a,b):
r=a%b
i=0
erg=1
while r:
a=b
b=r
r=a%b
return b
def my_set_ggt(m, n):
print(r"\def\mytmpggt{" + str(ggt(m, n)) + "}")
\end{pycode}
\begin{document}
\begin{tikzpicture}
\draw[-Stealth] (0,-.5) -- (0,6) node [above] {$n\in \mathbb{N}$};
\draw[-Stealth] (-5.5,0) -- (5.5,0) node [right] {$m\in\mathbb{Z}$};
\foreach \m in {-4,...,4}
\foreach \n in {1,...,5}{
\def\mytmpggt{0}
\expanded{\pyc{my_set_ggt(\m,\n)}}
\ifnum\mytmpggt=1 {
\node (\m-\n) at (\m,\n) [circle, draw, inner sep=0, minimum size=0.6 cm, fill=white] {$\frac{\m}{\n}$};}
\else {
\node (\m-\n) at (\m,\n) [circle, inner sep=0, minimum size=0.6 cm, fill=white] {$\xcancel{\frac{\m}{\n}}$};
}\fi
}
\end{tikzpicture}
\end{document}
Side note, the braces in \ifnum
does not do what you think it does. Read the TeXbook (or TeX by Topic, TeX in a nutshell) if you want to learn.
\ifnum
clause, in such a way that it can work without Python in the first run. It is fine if the result is wrong at first, since this will be corrected in the third compilation run. Try to define a macro which you initially set to zero and which then is set toggt(\m,\n)
via Python. In the first run,\ifnum
sees zero which won't break the code.\foreach
loop, which can not succeed because of the way the three-step compilation works. At least not to my understanding.ggt(\m,\n)
won't work? Honestly, I wouldn't know how to do that too. Your answer however answered my question just perfectly, thank you so much!