Skip to content

ajberkley/py4cl2

 
 

Repository files navigation

This is a fork of bendudson/py4cl.

Github Pages

Detailed documentation is available on github-pages (could be a bit outdated).

For MacOS Users

If you have bash 3.2 please upgrade it to a more recent version.

Releases

Check the Releases section. That said, if you are looking for stability, look at py4cl and not py4cl2, at least not in 2021. You may use py4cl2 on use-and-throw projects, or use it without using "edgy" features (not yet classified).

Contribution and PRs

Please test using py4cl2-tests.

Quick Demonstration

(ql:quickload :py4cl2 :silent t)

(py4cl2:defpymodule "numpy" nil :lisp-package "NP")
(py4cl2:defpymodule "scipy.integrate" nil :lisp-package "INTEGRATE")

;; Integrate some ODEs
(defparameter *data*
  (integrate:odeint 
   :func (lambda (y time) 
           (list (aref y 1)       ; dy[0]/dt = y[1]
                 (- (aref y 0)))) ; dy[1]/dt = -y[0]
   :y-0 #(1.0 0.0)   ; Initial state
   :t (np:linspace :start 0.0 :stop (* 2 pi) :num 20)))
                                        ; Vector of times

; (array-dimensions *data*) => (20 2)

;; Make a plot, save and show it in a window
(py4cl2:defpymodule "matplotlib.pyplot" nil :lisp-package "PLT")

(plt:plot *data*)
(plt:xlabel :xlabel "Time")
(plt:savefig "result.pdf")
(plt:show)

eval and exec

pyexec uses the Python exec function, which takes a Python statement. pyeval uses the Python eval function, which takes a Python expression.

When pyexec or pyeval'ing strings in your python image, they are all operating within a shared global namespace. So, for example, (pyexec "import math") will then make math.sqrt available for all future calls, so (pyeval "math.sqrt(9)") will return 3.

Running py4cl2 with a Python GUI

The example above with matplotlib was a static plot (no interactive zooming, no GUI). To enable interactivity, the main thread of the Python process needs to be running a GUI main loop. To do this, we can change the py4cl2 loop to not block and to be called regularly by the gui main loop. To do so, see the example src/PyQt6_example.py where we create a matplotlib plot on the Qt6 backend. To run it, you would do the following:

  ;; so python can find the example module
  (pyexec (format nil "import sys; sys.path.insert(0, '~a')"
                  (directory-namestring
                   (asdf:component-pathname
                    (asdf:find-component :py4cl2 "python-code")))))
  ;; start the gui loop and a simple plot.
  (raw-py-exec/no-return "import PyQt6_example; PyQt6_example.start_app(try_process_message);")
  (pyeval "1 + 1") ;; still works despite GUI refreshing as needed

Multiple Python processes

You can manage multiple running python processes. By default there is a dynamic variable *python* bound to the running process. If you want to create a new one, call (pystart) and (let ((*python* my-python)) around your calls.

Great thanks to Ben Dudson for starting this project, and documenting it enough to make it more-buildable!

About

Call python from Common Lisp

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Common Lisp 85.0%
  • Python 15.0%