3
votes

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
Specify the full path to the ccl64 binary. - uselpa
To extend a bit what @LePetitPrince says: When you're typing on a terminal, typing just ccl64 works because the executable is in your PATH environment variable but (by default), subprocess doesn't know that PATH. Find where the ccl64 executable lives and pass the whole path to your Popen call. - BorrajaX

1 Answers

4
votes

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