How to get output of a Lisp program into Python?

1.3k views Asked by At

I've got a very large Lisp project whose output I'd like to programmatically pipe to a Python program, i.e. use Python to call the Lisp program on some input and get the output back into Python.

The project only compiles in Clozure Common Lisp (ccl64) and I did try to find a way to turn it into an executable (I'm using Mac OS X), but that ran into a lot of dead ends (I am not a Lisp programmer).

This documentation for Clozure Common Lisp should provide the solution to the above, but I was not able to understand it. The examples I made created a file, but Terminal would not run them as executables.

How to create executable for ccl64

I tried to follow this question's answer Compiling Common Lisp to an executable except using ccl64's save application function.

$ ccl64
Welcome to Clozure Common Lisp Version 1.9-dev-r15612M-trunk  (DarwinX8664)!
? (in-package :ccl)  
#<Package "CCL">
? (defun main () (print "hello"))
MAIN
? (save-application "hello" :toplevel-function #'main)

I am trying to use Python's subprocess to invoke ccl64, run the Lisp program, and get the output. However, subprocess for some reason refuses to run the ccl64 command. Here is what I wrote so far:

import subprocess

process = subprocess.Popen(['ccl64', '-h'], stdout=subprocess.PIPE)
out, err = process.communicate()

The variable out should contain the output of getting the usage/help from ccl64. Instead I get an error:

Traceback (most recent call last):
  File "sub.py", line 3, in <module>
    process = subprocess.Popen(['ccl64', '-h'], stdout=subprocess.PIPE)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1249, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

How can I get Python to invoke ccl64 and get output from the Lisp project?

1

There are 1 answers

4
Rainer Joswig On BEST ANSWER

The error in your Python code is clear: No such file or directory.

You need to tell in your Python code which application you want to run in a way that it actually finds it.

It's also not clear why you save a Lisp executable somewhere named hello, but you are not trying to call it. With the necessary path. Your code tries to call Clozure CL - without the necessary path - but why? You just saved an executable. Why would you call Clozure CL to run it? I would also save the executable with prepending the kernel - that makes it self-contained.

Example:

Calling Clozure CL:

rjmba:~ joswig$ ccl
Welcome to Clozure Common Lisp Version 1.9-dev-r15612M-trunk  (DarwinX8664)!

Defining the main function:

? (defun main () (print "hello"))
MAIN

Saving an executable:

? (save-application "hello" :toplevel-function #'main :prepend-kernel t)

Running the new executable from the same directory:

rjmba:~ joswig$ ./hello

"hello" 

Calling a Clozure CL application with an argument:

bash-3.2$ ccl
Welcome to Clozure Common Lisp Version 1.9-dev-r15612M-trunk  (DarwinX8664)!

The function ccl::command-line-arguments returns the arguments as a list. The first item is the called application itself.

? (defun main ()                                                                
    (print (second (ccl::command-line-arguments))))
MAIN

? (save-application "hello"                                                     
                    :toplevel-function #'main                                   
                    :prepend-kernel t)

Calling it:

bash-3.2$ ./hello hello!

"hello!"