Search code examples
pythonlispcommon-lispexecutableccl

How to get output of a Lisp program into Python?


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?


Solution

  • 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!"