[clpython-devel] Calling Python functions from Lisp [Re Franz thread: spr35431]

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 -- Stuart C. Shapiro Professor, Department of Computer Science and Engineering University at Buffalo, The State University of New York 201 Bell Hall, Box 602000, Buffalo, NY 14260-2000, U.S.A. PHONE: 716-645-3180x125 FAX: 716-645-3464 shapiro@cse.buffalo.edu http://www.cse.buffalo.edu/~shapiro/

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
-- Stuart C. Shapiro Professor, Department of Computer Science and Engineering University at Buffalo, The State University of New York 201 Bell Hall, Box 602000, Buffalo, NY 14260-2000, U.S.A. PHONE: 716-645-3180x125 FAX: 716-645-3464 shapiro@cse.buffalo.edu http://www.cse.buffalo.edu/~shapiro/

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
-- Stuart C. Shapiro Professor, Department of Computer Science and Engineering University at Buffalo, The State University of New York 201 Bell Hall, Box 602000, Buffalo, NY 14260-2000, U.S.A. PHONE: 716-645-3180x125 FAX: 716-645-3464 shapiro@cse.buffalo.edu http://www.cse.buffalo.edu/~shapiro/
participants (2)
-
Stuart C. Shapiro
-
Willem Broekema