I think that I have successfully installed CLPython. What I want to do is to call Python functions, defined in programs written by others, from Allegro Common Lisp. So here is a test Python program called test.py: ----------------------------- # A Python file to use to test clpython
def test(): print "I am a Python function." return "I am done."
print("The Python test file has been run.") -----------------------------
I loaded clpython, and did (note: this wasn't the first time I imported test, so test.fasl and test.pyc already existed.): ----------------------------- cl-user(3): (clpython:run "import test; test.test()") Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> ; Fast loading /net/projects/shapiro/clpython/test.fasl The Python test file has been run. Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> I am a Python function. "I am done." -----------------------------
First question: Why the Warning messages? How can I get rid of them?
Notice that I can make use of the values returned by the Python function: ----------------------------- cl-user(4): (setf x (clpython:run "import test; test.test()")) Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> ; Fast loading /net/projects/shapiro/clpython/test.fasl The Python test file has been run. Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> I am a Python function. "I am done."
cl-user(5): x "I am done." -----------------------------
What I'd really like to do now is to call test.test() as much as possible as though it were a Common Lisp function. One possible way is: ----------------------------- cl-user(6): (clpython:run "test.test()") Error: NameError: Variable `test' is unbound. [condition type: NameError]
Restart actions (select using :continue): 0: Enter a Lisp value to use for `test'. 1: Return to Top Level (an "abort" restart). 2: Abort entirely from this (lisp) process. ----------------------------- But, the name of the function does not seem to survive from one call of clpython:run to another.
Final question: How can I do this?
stu
Hello Stuart, welcome to the list.
On Thu, Jan 8, 2009 at 4:56 PM, Stuart C. Shapiro shapiro@cse.buffalo.edu wrote:
cl-user(3): (clpython:run "import test; test.test()") Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> ; Fast loading /net/projects/shapiro/clpython/test.fasl [...] First question: Why the Warning messages? How can I get rid of them?
Those were debug messages accidentally left in. They have been removed now. Sorry about that.
Notice that I can make use of the values returned by the Python function:
cl-user(4): (setf x (clpython:run "import test; test.test()")) Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> ; Fast loading /net/projects/shapiro/clpython/test.fasl The Python test file has been run. Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> I am a Python function. "I am done."
cl-user(5): x "I am done."
Yes, the last value of the Python expression is returned.
What I'd really like to do now is to call test.test() as much as possible as though it were a Common Lisp function. One possible way is:
cl-user(6): (clpython:run "test.test()") Error: NameError: Variable `test' is unbound. [condition type: NameError]
Restart actions (select using :continue): 0: Enter a Lisp value to use for `test'. 1: Return to Top Level (an "abort" restart). 2: Abort entirely from this (lisp) process.
But, the name of the function does not seem to survive from one call of clpython:run to another.
Final question: How can I do this?
There is not an elegent way for that yet (I'm working on it), but the following works:
cl-user(6): :pa clpython clpython(7): (setf *habitat* (make-habitat)) ;; required for py-import #<habitat @ #x10fd5472> clpython(8): (setq m (py-import '(foo))) #<module `foo' Src: /Users/willem/dev/lisp/tmp/git-clpython/foo.py Binary: /Users/willem/.fasl/allegro-8.1m-macosx-x86/Users/willem/dev/lisp/tmp/git-clpython/foo.fasl @ #x10a5a5a2> clpython(9): (attr m 'f) ;; attribute lookup #<python-function f @ #x10a5a872> clpython(10): (funcall *) 24 None
Where foo.y is: def f(): print 24
- Willem
Willem,
Thanks a lot. Your examples worked, and using them, I wrote a set of functions that seem to do what I want. I'll include them below, but first, here's a demo.
The python file, called /projects/shapiro/clpython/test.py ----------------------------- # A Python file to use to test clpython
def test(): print "I am a Python function." return "I am done."
def pyplus(x,y): return x+y
def pyminus(x,y): return x-y
print("The Python test file has been run.") -----------------------------
My use of it, after loading CLPython and my new utility: ----------------------------- cl-user(3): :pwd Lisp's current working directory is "/home/csefaculty/shapiro/" *default-pathname-defaults* is #P"/home/csefaculty/shapiro/"
cl-user(4): (clpython:pypaths "/projects/shapiro/clpython/") ("/projects/shapiro/clpython/")
cl-user(5): (clpython:pyimport 'test) ; Fast loading /projects/shapiro/clpython/test.fasl The Python test file has been run. #<module `test' Src: /net/projects/shapiro/clpython/test.py Binary: /net/projects/shapiro/clpython/test.fasl @ #x723d675a>
cl-user(6): (* (clpython:pycall 'test 'pyplus 3 5) (clpython:pycall 'test 'pyminus 7 4)) 24 -----------------------------
My utility. It could probably be made more sophisticated. ----------------------------- ;;; Utility for calling Python Functions from Common Lisp ;;; Stuart C. Shapiro ;;; Uses CLPython ;;; and additional suggestions from Willem Broekema ;;; January 9, 2009
(in-package :clpython)
(export '(pypaths pyimport pycall))
(setf *habitat* (make-habitat))
(defvar *pymodules* (make-hash-table) "A map from module names to module structures.")
(defun pypaths (&rest paths) "Adds the paths to the list of paths that are tried when locating a module in order to import it." (setf cl-user::*clpython-module-search-paths* (append cl-user::*clpython-module-search-paths* paths)))
(defun pyimport (module) ;; Imports the given Python module, and creates an entry for it in *pymodules*" (setf (gethash module *pymodules*) (py-import (list module))))
(defun pycall (module fn &rest args) "Calls the function named fn of the module named module on the given arguments, and returns what it returns." (unless (gethash module *pymodules*) (error "There is no loaded module named ~S." module)) (apply (attr (gethash module *pymodules*) fn) args)) -----------------------------
Thanks, again.
stu
Willem Broekema wrote:
Hello Stuart, welcome to the list.
On Thu, Jan 8, 2009 at 4:56 PM, Stuart C. Shapiro shapiro@cse.buffalo.edu wrote:
cl-user(3): (clpython:run "import test; test.test()") Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> ; Fast loading /net/projects/shapiro/clpython/test.fasl [...] First question: Why the Warning messages? How can I get rid of them?
Those were debug messages accidentally left in. They have been removed now. Sorry about that.
Notice that I can make use of the values returned by the Python function:
cl-user(4): (setf x (clpython:run "import test; test.test()")) Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> ; Fast loading /net/projects/shapiro/clpython/test.fasl The Python test file has been run. Warning: *import-recompiled-files* = #<equal hash-table with 0 entries> Warning: /net/projects/shapiro/clpython/test.fasl not in #<equal hash-table with 0 entries> I am a Python function. "I am done."
cl-user(5): x "I am done."
Yes, the last value of the Python expression is returned.
What I'd really like to do now is to call test.test() as much as possible as though it were a Common Lisp function. One possible way is:
cl-user(6): (clpython:run "test.test()") Error: NameError: Variable `test' is unbound. [condition type: NameError]
Restart actions (select using :continue): 0: Enter a Lisp value to use for `test'. 1: Return to Top Level (an "abort" restart). 2: Abort entirely from this (lisp) process.
But, the name of the function does not seem to survive from one call of clpython:run to another.
Final question: How can I do this?
There is not an elegent way for that yet (I'm working on it), but the following works:
cl-user(6): :pa clpython clpython(7): (setf *habitat* (make-habitat)) ;; required for py-import #<habitat @ #x10fd5472> clpython(8): (setq m (py-import '(foo))) #<module `foo' Src: /Users/willem/dev/lisp/tmp/git-clpython/foo.py Binary: /Users/willem/.fasl/allegro-8.1m-macosx-x86/Users/willem/dev/lisp/tmp/git-clpython/foo.fasl @ #x10a5a5a2> clpython(9): (attr m 'f) ;; attribute lookup #<python-function f @ #x10a5a872> clpython(10): (funcall *) 24 None
Where foo.y is: def f(): print 24
- Willem
On Fri, Jan 9, 2009 at 9:48 PM, Stuart C. Shapiro shapiro@cse.buffalo.edu wrote:
Thanks a lot. Your examples worked, and using them, I wrote a set of functions that seem to do what I want. I'll include them below, but first, here's a demo.
Thanks for showing how you use this. Eventually I want to provide an integration between Python and Lisp where Python functions can be invoked just like Lisp functions without using attr and funcall, but that's still in development.
Let me know if there is anything more you need help with.
Cheers, - Willem
Willem,
That would be even better. Please let me know when it's done. In the meantime, what I have will do.
stu
Willem Broekema wrote:
On Fri, Jan 9, 2009 at 9:48 PM, Stuart C. Shapiro shapiro@cse.buffalo.edu wrote:
Thanks a lot. Your examples worked, and using them, I wrote a set of functions that seem to do what I want. I'll include them below, but first, here's a demo.
Thanks for showing how you use this. Eventually I want to provide an integration between Python and Lisp where Python functions can be invoked just like Lisp functions without using attr and funcall, but that's still in development.
Let me know if there is anything more you need help with.
Cheers,
- Willem
clpython-devel@common-lisp.net