6

I'm trying to pass a LaTeX-Length (\textwidth) to a python function specified in an pyblock-environment provided by the pythontex-package. Running pythontex gives me an error message, that does not provide any help to me:

This is PythonTeX v0.12

----  Messages for py:default:default  ----
* PythonTeX stderr - error on line 10:
    File "<outputdir>/py_default_default.py", line 65
      print(pytex.formatter(printtexlength(\textwidth )))
                                                        ^
  SyntaxError: unexpected character after line continuation character

--------------------------------------------------
PythonTeX:  minimal - 1 error(s), 0 warning(s)

Has anybody an idea what is going wrong here, or how can I pass a LaTeX-Length to a python-function?

Here is a minimal-example:

\documentclass{scrreprt}

\usepackage{pythontex}

\begin{document}

\begin{pycode}
def printtexlength(length):
    print('Length ist %f' % length)
\end{pycode}
\newcommand{\printlength}[1]{\py{printtexlength(#1)}}
%\py{printtexlength(\textwidth)} % This although fails with same error message
\printlength{\textwidth}

\end{document}
  • The problem is that the pythontex commands don't expand their arguments, so Python receives the literal string \textwidth and doesn't know what to do with it. egreg's solution expands \textwidth to avoid this. The next version of pythontex (beta on GitHub in a few days) has built-in utilities for passing contextual information like page dimensions to the Python side, as well as conversion functions for going from pt to in, cm, and mm. This can be used to make figures automatically adjust to page dimensions, etc. – G. Poore Jan 27 '14 at 14:14
5

\py doesn't accept this, but only an explicit number. Here's a possibly working version, where the dimension is expanded to a number before passing it to \py:

\documentclass{scrreprt}

\usepackage{pythontex}

\makeatletter
\newcommand{\printlength}[1]{%
  \begingroup\edef\x{\endgroup
    \noexpand\py{printtexlength(\strip@pt\dimexpr#1\relax)}}\x}
\makeatother

\begin{document}

\begin{pycode}
def printtexlength(length):
    print('Length is %f' % length)
\end{pycode}
\printlength{\textwidth}

\printlength{1in}

\end{document}

enter image description here

I don't know enough Python to understand why None appears.

Thanks to G. Poore, here's the correct version of the function:

\begin{pycode}
def printtexlength(length):
    return 'Length is %f' % length
\end{pycode}

enter image description here

| improve this answer | |
  • The \py macro automatically prints a string version of whatever it is given (it can be given numbers, the names of existing Python variables, quoted strings, or any other valid Python code...it just doesn't expand its argument). The print() in printtexlength() is not needed. What is happening is that printtexlength() prints the desired value, and then \py prints the return value of the function, which is None. Instead, printtexlength() should be return 'Length is %f' % length. Then only the desired text will be printed. – G. Poore Jan 27 '14 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.