45

The question is inspired by Martin Schröder's answer to I am new to TeX. Should I use LaTeX, XeLaTeX, …? as well as my two previous questions on this forum:

  1. Automatic document update
  2. Generate LaTeX Truth Table with Python Cheetah

In retrospect, I am truly surprised that no LuaTeX user offered any answers to my questions as it seems to me that that could be easily done in LuaTeX by embedding Lua scripts into the LaTeX code. Can it be really done (question for LuaTeX users only) and is it easy?

My second question is motivated by the fact that I hate very thought of having to learn another scripting/general programming language (Lua) if I already know Python (you can substitute Perl if you like) just to use it with TeX. Is anybody cooking a Python interface for TeX call it PythonTeX for short (PerlTeX actually does exist)? As far as I know PythonTeX doesn't exist. There is something called PyTeX but that just look like a tool for people who want to type TeX documents using Python syntax.

Is there an advantage of using Lua over Python as an embedded scripting language for TeX (apart of the fact that people who started LuaTeX probably were more familiar with Lua)?

  • 2
    With regard to your question on truth tables, see the example at the ConTeXt wiki. It is relatively straightforward to modify that to generate truth tables. I'll post a separate answer to your question on automatic document update. – Aditya Jan 29 '12 at 19:38
  • 3
    Just a minor comment on the Lua bit. I had never even seen a bit of Lua code before about three months ago. Now I can code stuff like this: http://youtu.be/m_9Q2X-PJwE It really is easy to learn, even for a non-programmer like myself. – Andrew Stacey Jan 29 '12 at 21:22
  • 1
    @Andrew Stacey I will re-paraphrase one of my favorite comments on this forum which happened to be written by you. Some n00b was asking about perfect tools for TeX-ing to which you responded:"Do not forget to do your research while searching for the perfect tool". What I am trying to say? The human life span is very short and we have to budget carefully. I would much rather waist the rest of what I have left trying to do research than trying to learn new tools. Having said that I already broke that rule by learning Python while being fairly familiar with Shell, AWK, MATLAB and C. – Predrag Punosevac Jan 29 '12 at 21:32
  • Touché. But I can turn that around. Learning Lua will take very little time at all. Writing PythonTeX will take an extremely long time. If going beyond TeX will help you do your day job, then learning Lua will leave much more time for the research than writing PythonTeX would. – Andrew Stacey Jan 29 '12 at 21:57
  • @PredragPunosevac True. But there is something to be said for evaluating the time trade-off between learning a new tool and trying to bend an existing tool such that it suits the task at hand. You can beat a hole in a steel plate with a hammer---but it is much more efficient to learn how a plasma cutter works. – Sharpie Jan 29 '12 at 22:40
  • 1
    @Sharpie: plasmas cutters are expensive ;-) – Bruno Le Floch Jan 30 '12 at 07:05
  • Unless you try something which introduces completely different concepts, you only have to learn the syntax. I haven't used Lua or LuaTeX yet, but I'm expecting you should learn what is necessary to get your problem solved quite quickly. – Psirus Jan 30 '12 at 10:13
  • @BrunoLeFloch Time is money as well. – Sharpie Jan 30 '12 at 17:00
  • Have anyone mentioned pyluatex? (by the way refer to https://tex.stackexchange.com/questions/238016/embedding-python-in-latex and https://tex.stackexchange.com/questions/33129/using-python-within-latex-and-accessing-its-variables for options to embed Python in TeX) – user202729 Jul 13 '22 at 05:36
  • Side note, the plasma cutter comparison above is kind of inaccurate, talking as if Python is the hammer and Lua is the plasma cutter. For certain tasks it's the opposite, with all of the Python libraries (numpy, sympy, pandas, tensorflow etc.) -- the advantage of Lua here is that it has a built-in embedding inside TeX; nevertheless learning Lua then figure out replacements for numpy etc. isn't quite a good way, better way might be to learn just-enough Lua to write a Python binding then use Python afterwards (although nowadays with pyluatex it isn't really necessary) – user202729 Jul 13 '22 at 06:03

7 Answers7

27

I have been coding "PythonTeX" since last May, and am planning the first public release sometime between next weekend and the beginning of March. I'm actually planning to call it PythonTeX, by analogy to PerlTeX and SageTeX.

I've created a LaTeX package, and accompanying Python scripts, that provide most functionality of python.sty, SageTeX, and SympyTeX, but with emphasis on speed and usability. Here's a brief summary of what PythonTeX will bring.

  • Persistence between commands and environments. For example, each environment \begin{pythoncode} ... \end{pythoncode} picks up where the last left off, so all variables, functions, etc. persist. You can optionally name commands and environments, and then there is only persistence between commands and environments with the same name. For example, \begin{pythoncode}[name] ... \end{pythoncode} only shares persistence with other commands and environments called name.

  • Automatic inclusion of printed content. For example,

    \begin{pythoncode}
    print(1+1)
    \end{pythoncode}
    

    is automatically replaced by 2 in the compiled document.

  • Speed. Each set of named commands and environments is executed in its own process, using Python's multiprocessing package. Also, each set is hashed, so code is only executed when changed. The results of running the code are saved, and reused when no changes are detected.

  • Code typesetting. All code that is executed can also be typeset, using fancyvrb and its internals. Optionally, code can be typeset using Pygments, which is a Python package that does syntax highlighting (Pygments is used by the minted package). When Pygments is used, all code is hashed and the typeset results are saved, so that only changed code must be processed by Pygments in subsequent runs. This helps prevent Pygments from slowing things down.

  • Meaningful error messages. All error messages are parsed by code that determines the line of your document where the error occurred (as opposed to the line of the *.py file that is actually executed). So you know exactly where things went wrong in your document.

  • Minimal files. The code cleans up after itself, so the number of permanent files created by Python is kept to a minimum and all temporary files are deleted after each run.

I can post a link as soon as PythonTeX is released. I will also be submitting it to CTAN shortly after the first public release.

G. Poore
  • 12,417
  • Your PythonTeX is for LaTeX only or for plain TeX too? – Sam Qasbah Feb 01 '12 at 09:36
  • 7
    You can't compare solutions like these (also perlTeX etc.) with the current state of LuaTeX, because the external processes will not allow to manipulate TeX's internal state and data structures. – topskip Feb 01 '12 at 09:39
  • @SamQasbah Unfortunately, my package is for LaTeX, not plain TeX. It requires several other LaTeX packages like fancyvrb, so a plain TeX version could involve a lot of work. – G. Poore Feb 01 '12 at 16:18
  • 6
    @PatrickGundlach I agree--PerlTeX, SageTeX, my "PythonTeX", and similar packages lack LuaTeX's power and integration on the TeX side. If someone needs that, then LuaTeX is the way to go (and I think Lua was a good language choice, given LuaTeX's objectives). But if someone just needs to run code and get its output back in a document, then these other packages can be compared with LuaTeX on that level. Personally, I don't need to manipulate TeX internals. I just want to run Python code that creates pdf figures or returns its output in LaTeX format, without having to leave my text editor. – G. Poore Feb 01 '12 at 17:05
  • 7
    After some delays and feature creep, a beta version of my PythonTeX code is now available at GitHub. – G. Poore Apr 27 '12 at 19:12
26

The LuaTeX developers have commented on their choice of Lua over other languages, including Python, on their home page.

Embedding the interpreter is one thing, and apparently no fun with Python. Another is to actually make the innards of TeX visible to the embedded interpreter. While much of the communication code could likely be adapted in some way from LuaTeX to PythonTeX, it will still be a lot of work.

A better approach may be to cheat a bit, and simply piggyback on the LuaTeX interpreter. There is a bridge that 'embeds' Python inside Lua called Lunatic Python, and maybe it can be made to work with LuaTeX also. However, it may be easier to just use XML-RPC: Let LuaTeX spawn a Python process, which acts as the XML-RPC server. LuaTeX commands can then make calls to the Python process. Bonus feature: Once this is implemented on the LuaTeX side, it can be used with any other scripting language, not just Python.

  • 3
    In EuroTeX 2009 Luigi Scarso demostrated a working version of Lunatic Python. More details on installation instruction along with different examples are on the ConTeXt wiki – Aditya Jan 29 '12 at 20:18
  • Thanks, Aditya. I looked at it, and while there seems to be a bit of source code hacking involved, it doesn't seem too bad. Worth a try for anyone interested in exploring the possibilities. – Michael Palmer Jan 30 '12 at 02:36
  • 1
    This was a reasonable answer in 2012, but at this point it is clearly a mistake. Back in 2010 when git and mercurial were equally popular, I chose mercurial. Git won; I swallowed my pride and switched all my repos to git. The same thing has happened here. Lua and Python were reasonable choices in 2010. Python won the popularity contest. Now, Python is a richer language with far more support, more libraries, and more users. As much as it hurts, it is worth prioritizing a Python frontend to a TeX backend. – Neil G Mar 14 '20 at 22:01
  • Nowadays unfortunately Lunatic Python is not very well maintained, but the fork https://github.com/bastibe/lunatic-python/issues/65#issuecomment-951888478 works fine. I find it somewhat hard to install (and underdocumented regarding that) so I wrote install instruction there. (also search the old issues of the repository) Also note that it's a C Lua library which requires some special instruction to install: https://tex.stackexchange.com/a/372134/250119 // There's also Lupa: https://pypi.org/project/lupa/ but this one is Python → Lua only. – user202729 Nov 01 '21 at 15:43
12

Here is a way to call into a persistent Python process from LuaTeX via JSON-RPC. 1)

Required setup:

  1. Download and install jsonrpclib. This provides the Python server.

  2. Download a Lua json-rpc client. I adapted some Lua modules I found on the web and zipped them up and put them on my server. Unzip into one of the directories specified in this answer: "Lua tree" (analogue of texmf tree)

Now, we can write a Python server that exposes some functions:

import sys
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer

server = SimpleJSONRPCServer(('localhost', 8080))

server.register_function(lambda: "Hello from Python!", 'ping')
server.register_function(lambda *args: sum(args), 'add')

# the counter generator shows that the server can be used
# to preserve state between requests, and even across multiple
# LaTeX compiler runs (which we may not want)
counter = iter(xrange(sys.maxint))
server.register_function(lambda: counter.next(), 'count')

server.serve_forever()

Save this as testserver.py and run.

Here is test document that shows how to call the server:

\documentclass{article}

\directlua{ % make the running python server available as a proxy
    require "jsonrpc"
    pythonserver = jsonrpc.proxy("http://localhost:8080")
}

\newcommand{\python}[2][]{\directlua{%
    result = pythonserver.#2(#1)
    tex.print(result)
}}

\begin{document}

\python{ping}

The sum of 1,2,3,4,5,6,2,4,5,6 is \python[1,2,3,4,5,6,2,4,5,6]{add}

\directlua{%
    for x=0,100,1 do
        result = pythonserver.count()
        tex.print(result)
    end
}

\end{document}

Addressing the original question about how to implement pythontex, all that would be required now is a shell script that first starts the server, then calls LuaTeX, and then shuts down the server again. This is left as an exercise to the reader ;)

1) The reason why I used JSON-RPC instead of XML-RPC is that I couldn't find a Lua-only XML-RPC client; the one client that I did find used a C extension library, and I and couldn't figure out how to load that into LuaTeX (blush). The JSON-RPC modules were simpler, and after some kicking and screaming (on my part) could be persuaded to cooperate. Maybe someday I can figure out how to make XML-RPC work also.

11

My take is: Lua as a language was created as an embedded language and is well suited for the job. Now that with LuaTeX a scriptable TeX implementation exists, there is little principled reason to create another one. Of course, you can go ahead and create PythonTeX. But it seems that the community feels that this would not add enough value over LuaTeX to justify the cost.

9

Actually, a good way to use Python code into (plain) TeX code is:

  1. for the typesetting work (boxes, glue and penalties) use only TeX;
  2. for calculation, databases interface and so on you can build Python modules that you can call from the TeX program via \write18. The Python modules have to leave the output into files that have to be read via the usual \newread and then used into the TeX code. This solution work best on Linux, as far as on Linux Python is natively installed.

As an example try this: prepare the module `adder.py' this way:

#!/usr/bin/env python
# file 'adder.py'

import sys

def save(data):
    tempFile = open("temp.dat","w")
    tempFile.write(str(data))
    tempFile.close()

def double(x):
    result = x * 2
    save(result)


if __name__ == "__main__":
    n = int(sys.argv[1])
    double(n)
    sys.exit

now, in the same directory, you can type a TeX file like this:

% file `doubler.tex'
\newread\tempfile
%
\def\double#1{%
    \immediate\write18{python adder.py #1}\relax
    \immediate\openin\tempfile=temp.dat
    \read\tempfile to \var
    \var}%
%
Double 2 is \double2\par
Double 3 is \double3\par
Double 4 is \double4\par
Double 5 is \double5\par
Double 6 is \double6\par
\bye

This TeX file has to be compiled with shell-escape, e.g.:

tex -shell-escape doubler

pdftex -shell-escape doubler

xetex -shell-escape doubler
Arun Debray
  • 7,126
  • 2
  • 30
  • 54
  • I really appreciate your answer. I will have to investigate that a bit further. – Predrag Punosevac Jan 29 '12 at 21:41
  • 2
    @PedragPunosevac I've added a working example into my post, so you can use that technique a bit easylier. – Sam Qasbah Jan 29 '12 at 22:55
  • 1
    Why not simply \input the generated file? – Aditya Jan 29 '12 at 23:34
  • 3
    This is nice, as far as toy examples are concerned. However, realize that this method creates and destroys a Python process for every call. On my machine, that is an overhead of 20 ms just for the Python interpreter itself. Load some big libraries such as scipy or matplotlib and it takes 120 ms, even with OS caching. So, for any serious usage, we need to talk to a persistent Python process, and the easiest way for this is XML-RPC. I just confirmed that with an asyncore-based XML-RPC server, a single call takes less than 2 ms. – Michael Palmer Jan 30 '12 at 02:29
  • @MichaelPalmer could you post an example? Perhaps on this question, or I could ask another question "How do I interface between TeX and a persistent Python process?" (although... it is borderline off-topic for this site). – Bruno Le Floch Jan 30 '12 at 07:08
  • @Aditya In the above example the generated file contains just a number, so it have no sense to \input it. But for advanced applications it is possible to build via python and \write18 a file that contains TeX code (more or less like in TeX's cross-referencing applications) and then \input that file in the current document. – Sam Qasbah Jan 30 '12 at 11:23
  • @Bruno I should have been clearer about this - I did not call from within Luatex but from a simple Python client - I haven't implemented the Lua client. The time measurement should be valid though. Maybe go ahead and ask the question - someone familiar with Lua might volunteer to implement it. – Michael Palmer Jan 30 '12 at 14:34
  • @Bruno I added an example below in a new answer. – Michael Palmer Feb 01 '12 at 01:55
8

I think that the pdfTeX community analyzed the situation correctly when they chose Lua. Lua is intended to be embedded into other applications, and it provides a robust, easy to use C API. The Lua API is straightforward and its design eliminates the need for manual reference management in C code, unlike Python's API.

Python is an opinionated language controlled by essentially one person and many people, myself included do not favour the significance of whitespace.

Yes, for you it maybe easier to use Python as it would have been easier for me if everyone stayed with the original Pascal code. Pascal would have provided everything one needed, it is a beautiful language and everyone is almost using it daily via pseudo-code and it would have provided a good way to migrate TeX to a new generation.

If there is any merit to suggest another language, I would recommend JavaScript. It is gaining in popularity via the web and easy to learn. The maths part of it has already been written, at least for browsers. It also provides full unicode support.

yannisl
  • 117,160
  • @Yiannis Actually, Pascal was my first programming language, even though I do not list it on my CV, and I completely agree with your assessment. I am too young to remember ALGOL (Pascal's inspiration) but just like in Shell Script (inspired by ALGOL) its influence is popping up up all over. – Predrag Punosevac Jan 29 '12 at 19:56
  • To be fair: is Lua any less controlled by Roberto Ierusalimschy than Python is by Guido van Rossum? – Christian Lindig Jan 29 '12 at 19:59
  • 1
    @ChristianLindig Roberto and his team come out more like the LaTeX Team with Roberto Ierusalimschy more like a guiding figure as well as an active developer. – yannisl Jan 29 '12 at 20:10
  • @MichaelPalmer We try and avoid flame wars here. They are unecessary to one's life. Personally, I would have liked TeX to have evolved organically and not have the need to jump to another language to achieve new goals. I suggested JavaScript as an alternate, as I have done a lot of interfacing at work, between documents and a web browser interface (mostly simple forms and text pre-processing). By the why do you say that Pascal was constraining? – yannisl Jan 29 '12 at 20:21
  • The problem with using Pascal as an extension language is that one would have needed to embed and integrate a full compiler. An interpreted language seems like the right choice to me. – Sharpie Jan 29 '12 at 20:23
  • @Sharpie Thanks, I realize that is not easily do-able anymore, in any case TeX is now written in "C". Personally I don't like mixing languages. (La)TeX has most of the tools and facilities to let you program anything you wish, maybe not that easily, but it can be done. My only wish is an easier output routine than LaTeX's and better management of fonts. – yannisl Jan 29 '12 at 20:34
  • ``I think that the LaTeX community analyzed the situation correctly when they chose Lua.'' When the LaTeX community analized the situation? And when Lua was choosen by the community? – Sam Qasbah Jan 29 '12 at 20:56
  • 1
    ``Lua is intended to be embedded into other applications''-- Do you really think that there is a field in which python is worse than Lua, or viceversa? – Sam Qasbah Jan 29 '12 at 20:59
  • 2
    @SamQasbah: Edited: It were the pdfTeX developers. – Martin Schröder Jan 29 '12 at 21:20
  • 2
    I suggested JavaScript at the time, but any JS interpreter is a behemoth compared to the Lua interpreter. Lua is the better choice. – Martin Schröder Jan 29 '12 at 21:21
  • 2
    @SamQasbah For answers I will let the current developers talk please see http://www.luatex.org/languages.html and yes I think there are fields where Lua is a better choice than python and vice versa. If you feel so strongly that this is the wrong language why don't you give it a try, find a group and produce pythonTeX? – yannisl Jan 29 '12 at 21:25
  • 1
    @predrag -- the immediate precursor to pascal was the algol 68 committee; wirth thought it was going mad, and stormed out and designed pascal instead. algol 68 turned out rather a good language, but not many people used it (i did -- i wrote cad code in it). wirth is now (afaict) effectively retired, but he came here a few years back and gave us a talk about writing code to guide model aeroplanes... – wasteofspace Feb 01 '12 at 15:28
  • This assumes that the future development of tex is to continue using the basic tex architecture and insert a small scripting component. Another view is that it's tex that's embedded inside some other language as the system is moved away from tex primitives. I'd love it if in 15 years there was no expandafter and we had the power of latex but implemented like a modern templating system. For that goal lua seems more limiting. I mean personally I'd love ruby or lisp but any language that's not intending to principly be embeddable scripting seems desirable. Ideally, both could be pursued. – Peter Gerdes Feb 11 '21 at 12:01
  • I think the ideal situation would be an implementation of tex in some common bytecode system (even javascript is going this way: web-asm) such as microsoft's CLS (i.e. mono) but I understand why this wasn't done and don't mean to criticize since the luatex team got something working and that's more important than anything else (NTS was abandoned/folded in). I just wanted to point out that embedding in tex is not the only perspective from which to analyze the issue. I wonder if you could move tex to one of these runtimes using the lua implementation on those systems…hmm worth looking into. – Peter Gerdes Feb 11 '21 at 12:13
6

Pweave

Much like the original poster, I also do regret the absence of a LaTeX interpreter capable of directly interpreting Python code.

Since PythonTeX got mentioned here in one of the other answers, I also would like to call your attention to Pweave. It is easier to use than PythonTex and also offers a couple more environment options.

Compiling a document that uses PythonTeX involves three steps: run latex, run pythontex.py, and finally run latex again. Pweave only needs two steps: run Pweave, then run pdflatex.

I got started with Pweave by reading a concise but excellent introductory article. You will also find my minimal working example over here on tex.StackExchange.

I have also posted an easier example involving currency notations and demonstrating the power of locales, Python and Pweave over here.

EDIT:

$ Pweave -l

Pweave supported output formats:

  • sphinx: reStructuredText for Sphinx
  • pandoc: Pandoc markdown
  • tex: Latex with verbatim for code and results
  • html: HTML with pygments highlighting
  • rst: reStructuredText
  • texpweave: Latex output with user defined formatting using named environments (in latex header)
  • texminted: Latex with predefined minted environment for codeblocks

More info: http://mpastell.com/pweave/formats.html

  • I actually started using PythonTeX and it is damn good! Thanks for bringing to my attention Pwave! I will have a look. – Predrag Punosevac May 26 '13 at 21:19
  • Thanks for adding another option to the mix! Potential Pweave users might benefit from a little more information. For example, Pweave supports multiple input and output formats, so it's not just a tool for TeX. Also, just to clarify: PythonTeX has a 3-step compile process, but the last 2 steps are only needed when Python code is modified and needs to be executed; otherwise, only a 1-step compile with pdflatex is needed. – G. Poore May 27 '13 at 17:41