### Install Project After Building Source: https://github.com/clj-python/libpython-clj/blob/master/README.md Installs the project to the local .m2 repository after the pom.xml file has been processed. This command should be run after building the project. ```bash $ clj -X:install ``` -------------------------------- ### Initialize JVM and Start REPL in Python Source: https://github.com/clj-python/libpython-clj/blob/master/docs/embedded.html This snippet demonstrates how to initialize the Java Virtual Machine (JVM) and start a Clojure REPL from a Python environment using the cljbridge library. Ensure JAVA_HOME is set and cljbridge is installed. ```python from clojurebridge import cljbridge test_var=10 cljbridge.init_jvm(start_repl=True) ``` -------------------------------- ### Python EDN Configuration Example Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Example configuration for `python.edn` to specify Python executable, library path, and home directory. ```clojure ;; python.edn {:python-executable "/usr/bin/python3.7" :python-library-path "/usr/lib/libpython3.7m.so" :python-home "/usr/lib/python3.7" :python-verbose true} ``` -------------------------------- ### Python EDN Configuration with Custom Hooks Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Example `python.edn` configuration demonstrating custom pre- and post-initialization functions. ```clojure ;:pre-initialize-fn my-ns/my-venv-setup-fn! ;;:post-initialize-fn my-ns/my-venv-validate-fn! ``` -------------------------------- ### Ubuntu Installation Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Provides the commands to install Python 3.6 and necessary libraries (numpy, pandas) on Ubuntu systems. Numpy is required for zero-copy support. ```bash sudo apt install libpython3.6 # numpy and pandas are required for unit tests. Numpy is required for # zero copy support. python3.6 -m pip install numpy pandas --user ``` -------------------------------- ### Python EDN Configuration with Virtual Environment Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Example `python.edn` configuration for using a local virtual environment. ```clojure ;; python.edn {:python-executable "env/bin/python"} ``` -------------------------------- ### Install Jar to Local .m2 Source: https://github.com/clj-python/libpython-clj/blob/master/README.md Installs the built jar file to your local Maven repository (.m2). This command requires the depstar alias to be available. ```bash $ clj -X:depstar ``` -------------------------------- ### Make Callable Options Example Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Demonstrates options for `make-callable`, including custom argument and result converters, and method naming. ```clojure ; Options: ;; * :arg-converter - Function called for each function argument before your ifn gets access to it. Defaults to `->jvm`. ;; * :result-converter - Function called on return value before it gets returned to python. Must return a python object. Defaults to `->python`; the result will get an extra incref before being returned to Python to account for the implied tracking of `as-python` or `->python`. ;; * :name - Name of the python method. This will appear in stack traces. ;; * :doc - documentation for method. ``` -------------------------------- ### Initialize JVM with Aliases and Start REPL Source: https://github.com/clj-python/libpython-clj/blob/master/docs/embedded.html Use this function to initialize the Clojure JVM from Python, specifying aliases from deps.edn and optionally starting a REPL. Ensure your deps.edn file is configured with the necessary JVM options. ```python import cljbridge cljbridge.init_jvm(aliases=["jdk-17","fastcall"],start_repl=True) ``` -------------------------------- ### Pandas DataFrame Access Example Source: https://github.com/clj-python/libpython-clj/blob/master/topics/Usage.md Provides a full example of creating a Pandas DataFrame and accessing its rows using `.loc` in both Python and Clojure. ```python # Python import numpy as np import pandas as pan dates = pan.date_range("1/1/2000", periods=8) table = pan.DataFrame(np.random.randn(8, 4), index=dates, columns=["A", "B", "C", "D"]) row_date = pan.date_range(start="2000-01-01", end="2000-01-01") table.loc[row_date] ``` ```clojure ; Clojure (require '[libpython-clj2.require :refer [require-python]]) (require-python '[numpy :as np]) (require-python '[pandas :as pan]) (def dates (pan/date_range "1/1/2000" :periods 8)) (def table (pan/DataFrame (call-attr np/random :randn 8 4) :index dates :columns ["A" "B" "C" "D"])) (def row-date (pan/date_range :start "2000-01-01" :end "2000-01-01")) (get-item (get-attr table :loc) row-date) ``` -------------------------------- ### Install cljbridge and javabridge Source: https://github.com/clj-python/libpython-clj/blob/master/topics/embedded.md Install the cljbridge Python library, which also compiles the javabridge module. Ensure your JAVA_HOME environment variable is set correctly to point to a JDK. ```bash export JAVA_HOME=<--YOUR JAVA HOME--> python3 -m pip install cljbridge ``` -------------------------------- ### Initialize Python and Import NumPy Module Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html This snippet shows the basic setup for using libpython-clj2. It requires the library, initializes the Python interpreter, and imports the 'numpy' module. ```clojure (require '[libpython-clj2.python :as py]) nil (py/initialize!) ;; ... (logging) :ok (def np (py/import-module "numpy")) #'user/np ``` -------------------------------- ### Call Referred Functions Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.require.html Demonstrates calling 'get' function from the 'requests' module, both with and without the module prefix. ```clojure (requests/get "https//www.google.com") ``` ```clojure (get "https//www.google.com") ``` -------------------------------- ### Install libpython-clj Dependencies on Ubuntu Source: https://github.com/clj-python/libpython-clj/blob/master/topics/Usage.md Installs the necessary Python shared library and packages (numpy, pandas) on Ubuntu systems. ```console sudo apt install libpython3.6 python3.6 -m pip install numpy pandas --user ``` -------------------------------- ### Start Clojure REPL for Python Integration Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.embedded.html Use `start-repl!` to launch a Clojure REPL and release the Python GIL, allowing Python interaction. This function blocks until `stop-repl!` is called. Options are passed to nrepl.cmdline. ```clojure (start-repl! options) (start-repl!) ``` -------------------------------- ### Importing and using NumPy linspace Source: https://github.com/clj-python/libpython-clj/blob/master/topics/Usage.md Demonstrates using `py/from-import` to import specific functions from Python modules and then calling them. Requires NumPy to be installed. ```clojure user> (py/from-import numpy linspace) #'user/linspace user> (linspace 2 3 :num 10) [2. 2.11111111 2.22222222 2.33333333 2.44444444 2.55555556 2.66666667 2.77777778 2.88888889 3. ] user> (doc linspace) ------------------------- user/linspace Return evenly spaced numbers over a specified interval. Returns `num` evenly spaced samples, calculated over the interval [`start`, `stop`]. ``` -------------------------------- ### start-repl! Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.embedded.html Starts a Clojure REPL and blocks the current thread until `stop-repl!` is called. This design ensures the Python GIL is released, allowing Python interaction while connected to the REPL. Returns the port of the new or existing REPL server. Options are the same as nrepl.cmdline. ```APIDOC ## start-repl! ### Description Starts a Clojure REPL and blocks the thread. This function does not return control to the calling thread until another thread calls `stop-repl!`; this design is explicit to ensure the python GIL is released and thus when connected to the REPL you can use Python. If an existing repl server has been started this returns the port of the previous server else it returns the port of the new server. To return control to the calling thread call `stop-repl!`. Options are the same as the command line options found in nrepl.cmdline. ### Signature `(start-repl! options)` `(start-repl!)` ``` -------------------------------- ### Create and Access Pandas DataFrame Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Provides an example of creating a Pandas DataFrame in Python and accessing its rows using `.loc` from Clojure. ```python # Python import numpy as np import pandas as pan dates = pan.date_range("1/1/2000", periods=8) table = pan.DataFrame(np.random.randn(8, 4), index=dates, columns=["A", "B", "C", "D"]) row_date = pan.date_range(start="2000-01-01", end="2000-01-01") table.loc[row_date] ``` -------------------------------- ### Require Module with Specific Referrals Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.require.html Loads the 'requests' module and specifically refers to 'get' and 'post' functions. ```clojure (require-python '[ equests :refer [get post]]) ``` -------------------------------- ### Create and Access Pandas DataFrame in Clojure Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Shows how to create a Pandas DataFrame and access rows using `.loc` from Clojure, mirroring the Python example. ```clojure ; Clojure (require '[libpython-clj2.require :refer [require-python]]) (require-python '[numpy :as np]) (require-python '[pandas :as pan]) (def dates (pan/date_range "1/1/2000" :periods 8)) (def table (pan/DataFrame (call-attr np/random :randn 8 4) :index dates :columns ["A" "B" "C" "D"])) (def row-date (pan/date_range :start "2000-01-01" :end "2000-01-01")) (get-item (get-attr table :loc) row-date) ``` -------------------------------- ### Managing Python Global Variables Source: https://github.com/clj-python/libpython-clj/blob/master/topics/Usage.md Shows how to get and set global variables in the Python environment. These variables persist across subsequent Python string executions. ```clojure (def main-globals (-> (add-module "__main__") (module-dict))) #'user/main-globals user> main-globals {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': } user> (keys main-globals) ("__name__" "__doc__" "__package__" "__loader__" "__spec__" "__annotations__" "__builtins__") user> (get main-globals "__name__") "__main__" user> (.put main-globals "my_var" 200) nil user> (run-simple-string "print('your variable is:' + str(my_var))") your variable is:200 {:globals {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , 'my_var': 200}, :locals {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , 'my_var': 200}} ``` -------------------------------- ### deps.edn Configuration for JVM Options Source: https://github.com/clj-python/libpython-clj/blob/master/docs/embedded.html This configuration in deps.edn allows you to specify JVM options and properties that will be applied when the JVM is started via aliases. It's crucial for setting up specific environments or features for libpython-clj. ```clojure :aliases { :fastcall {:jvm-opts ["-Dlibpython_clj.manual_gil=true"]} :jdk-17 {:jvm-opts ["--add-modules=jdk.incubator.foreign" "--enable-native-access=ALL-UNNAMED"]}} ``` -------------------------------- ### Manage Python Global Variables Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Shows how to get and set global variables in the Python environment. The globals map represents the main module's global dictionary. ```clojure (def main-globals (-> (add-module "__main__") (module-dict))) (keys main-globals) (get main-globals "__name__") (.put main-globals "my_var" 200) (run-simple-string "print('your variable is:' + str(my_var))") ``` -------------------------------- ### Get Attribute from Python Object Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Retrieves an attribute from a Python object. For example, getting the 'ones' function from the 'numpy' module. ```java Object ones = java_api.getAttr(np, "ones"); ``` -------------------------------- ### initialize! Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Initializes the Python library. Options can be provided directly or loaded from a `python.edn` file in the classpath. It returns `:ok` on success or `:already-initialized` if Python is already running. ```APIDOC ## initialize! ### Description Initializes the Python library. If the library path is not provided, the system attempts to execute a simple Python program to gather system information. Options can be provided directly or loaded from a `python.edn` file in the classpath. This function can also execute custom hooks before and after initialization. ### Signature `(initialize! & {:keys [windows-anaconda-activate-bat library-path no-io-redirect?], :as options})` ### Options * `:library-path` - Library path of the Python library to use. * `:program-name` - Optional; will show up in error messages from Python. * `:no-io-redirect?` - If true, Python stdout and stderr will not be redirected to `_out` and `_err`. * `:python-executable` - The Python executable to use for finding system information. * `:python-home` - Python home directory. This is checked in order: system variable, environment variable `PYTHON_HOME`, and information returned from Python system info. * `:signals?` - Defaults to false. If true, Python will initialize signals. Be aware that the JVM uses signals, so enabling this might have implications. * `:pre-initialize-fn` - Custom function to run code just before Python is initialized. * `:post-initialize-fn` - Custom function to run code just after Python is initialized. ### Returns Returns either `:ok` in which case the initialization completed successfully or `:already-initialized` in which case we detected that Python has already been initialized via `Py_IsInitialized` and we do nothing more. ``` -------------------------------- ### Initialize Python Environment Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Initializes the Python environment. Pass null for default configuration. ```java java_api.initialize(null); ``` -------------------------------- ### Initialize Clojure and Interact with Python Modules Source: https://github.com/clj-python/libpython-clj/blob/master/docs/embedded.html This sequence demonstrates initializing the Clojure environment from a Clojure REPL, requiring the libpython-clj library, and interacting with Python's main module. It shows how to add Python modules and access their dictionaries. ```clojure ;; M-x cider-connect ...localhost...40241 ;; I am not sure why but to initialize the user namespace I have to eval ns user user> (eval '(ns user)) nil user> (require '[libpython-clj2.python :as py]) nil ;; Python has been initialized and libpython-clj can detect this user> (py/initialize!) :already-initialized user> ;;We can share data via the main module user> (def main-mod (py/add-module "__main__")) #'user/main-mod user> (def mod-dict (py/module-dict main-mod)) #'user/mod-dict user> (keys mod-dict) ("__name__" "__doc__" "__package__" "__loader__" "__spec__" "__annotations__" "__builtins__" "cljbridge" "test_var") user> (get mod-dict "test_var") 10 user> (.put mod-dict "clj_fn" (fn [& args] (println "Printing from Clojure: " (vec args)))) nil ``` -------------------------------- ### Initialize libpython-clj and use stack-resource-context Source: https://github.com/clj-python/libpython-clj/blob/master/docs/scopes-and-gc.html Initializes the Python environment and demonstrates using a stack resource context to manage a Python dictionary. Ensure you call `->jvm` or return a keyword at the end of the scope. ```clojure (require '[libpython-clj.python :as py]) nil (py/initialize!) ... (logging elided) :ok (py/stack-resource-context (-> (py/->py-dict {:a 1 :b 2}) ;;Note - Without this call you guarantee a crash. (py/->jvm))) {"a" 1, "b" 2} ``` -------------------------------- ### Get Attribute from Python Object Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Retrieves a named attribute from a Python object. ```clojure (get-attr pyobj attname) ``` -------------------------------- ### Get Directory of Python Object Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Returns a list of attributes and methods available on a Python object. ```clojure (dir pyobj) ``` -------------------------------- ### Initialize Python Library Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Initializes the Python library. Options can be provided directly or loaded from a `python.edn` file. Returns `:ok` on success or `:already-initialized` if Python is already running. ```clojure (initialize! :library-path "/usr/lib/libpython3.7m.so") (initialize! :python-executable "env/bin/python") ``` -------------------------------- ### Get Item from Python Object Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Retrieves an item from a Python object using its `__getitem__` method. ```clojure (get-item pyobj item-name) ``` -------------------------------- ### Initialize Clojure REPL and Load Namespace Source: https://github.com/clj-python/libpython-clj/blob/master/topics/embedded.md Connect to a Clojure REPL using cider-connect and initialize the 'user' namespace. ```clojure ;; M-x cider-connect ...localhost...40241 ;; I am not sure why but to initialize the user namespace I have to eval ns user user> (eval '(ns user)) nil ``` -------------------------------- ### Initialize Python Environment Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Initializes the Python environment. This is a prerequisite for most other operations. It detects startup information and loads the Python library. ```clojure (require '[libpython-clj2.python :as py]) (py/initialize!) ``` -------------------------------- ### Get Python Object Type with `python-type` Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html The `python-type` function retrieves the type of a Python object, returning it as a Clojure keyword. ```clojure (python-type v) ``` -------------------------------- ### Stop Clojure REPL Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.embedded.html Call `stop-repl!` to terminate the Clojure REPL started by `start-repl!`, returning control to the calling thread. ```clojure (stop-repl!) ``` -------------------------------- ### Batch process with GIL and stack resource context Source: https://github.com/clj-python/libpython-clj/blob/master/docs/scopes-and-gc.html This snippet demonstrates the recommended approach for production use cases: acquiring the GIL and opening a stack resource context simultaneously using `with-gil-stack-rc-context`. It processes a large number of Python dictionaries, ensuring all allocated Python objects are released within the scope. ```clojure (def ignored (time (py/with-gil-stack-rc-context (->> (repeatedly 1000 #(py/->py-dict {:a 1 :b 2})) (py/->py-list) (py/as-jvm) (mapv py/->jvm))))) "Elapsed time: 3246.847595 msecs" #'user/ignored ``` -------------------------------- ### Require Module with Common Prefix and Aliases/Referrals Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.require.html Loads 'foo.bar' with an alias 'baz' and refers to 'qux', using shorthand notation. ```clojure (require-python '(foo [bar :as baz :refer [qux]])) ``` -------------------------------- ### Initialize JVM with aliases and JVM arguments Source: https://github.com/clj-python/libpython-clj/blob/master/topics/embedded.md Initialize the JVM with specific aliases defined in deps.edn, allowing for custom JVM arguments and properties. This is useful for configuring specific Java module access or native access. ```python cljbridge.init_jvm(aliases=["jdk-17","fastcall"],start_repl=True) ``` -------------------------------- ### Batch processing with GIL and stack resource context Source: https://github.com/clj-python/libpython-clj/blob/master/topics/scopes-and-gc.md Demonstrates using `with-gil-stack-rc-context` for production use cases, ensuring the GIL is acquired and a resource context is opened to guarantee the release of all Python objects allocated within the scope. This provides more assurance than relying solely on JVM garbage collection. ```clojure user> (def ignored (time (py/with-gil-stack-rc-context (->> (repeatedly 1000 #(py/->py-dict {:a 1 :b 2})) (py/->py-list) (py/as-jvm) (mapv py/->jvm))))) "Elapsed time: 3246.847595 msecs" #'user/ignored ``` -------------------------------- ### Slice a numpy array (last row, columns 1 to end) Source: https://github.com/clj-python/libpython-clj/blob/master/docs/slicing.html Extracts elements from the last row of 'ary', starting from the second column. ```clojure (py/get-item ary [(builtins/slice -1) (builtins/slice 1 nil)]) ``` -------------------------------- ### Get Global Variable Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Retrieves the value of a global variable from the Python environment. This allows accessing variables defined at the module level or in the global scope. ```APIDOC ## getGlobal ### Description Retrieves the value of a global variable from the Python environment. This allows accessing variables defined at the module level or in the global scope. ### Method `getGlobal(String varName)` ### Parameters * **varName** (String) - Required - The name of the global variable to retrieve. ``` -------------------------------- ### Slice a numpy array (rows 1 to end, columns 1 to end) Source: https://github.com/clj-python/libpython-clj/blob/master/docs/slicing.html Extracts a sub-array from 'ary' starting from the second row and second column to the end. ```clojure (py/get-item ary [(builtins/slice 1 nil) (builtins/slice 1 nil)]) ``` -------------------------------- ### -initialize Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Initializes the Python interpreter with specified options. It allows passing keyword arguments as strings and notes the underlying GIL for single-threaded access. ```APIDOC ## -initialize ### Description Initializes the Python interpreter with specified options. It allows passing keyword arguments as strings and notes the underlying GIL for single-threaded access. ### Method (Not specified, likely a constructor or initialization method) ### Parameters * **options** (map) - A map of options for initialization. Keyword arguments can be provided as strings (e.g., `:library-path` becomes the key `"library-path"`). ### Notes * Relies on the GIL, requiring single-threaded pathways for Java access. * See options for [libpython-clj2.python/initialize!](libpython-clj2.python.html#var-initialize.21). ``` -------------------------------- ### initialize! Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.embedded.html Initializes the Python environment when libpython-clj2 is called from a Python program. If `libpath` is not provided, the system searches for Python symbols in the current executable. ```APIDOC ## initialize! ### Description Initializes the Python environment when this library is being called _from_ a python program. In that case, unless libpath is explicitly provided the system will look for the python symbols in the current executable. ### Signature `(initialize!)` `(initialize! libpath)` ``` -------------------------------- ### Initialization Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Initializes the libpython-clj2 environment. This must be called before any other Java API methods. It can be called with null or a custom Python home directory. ```APIDOC ## initialize ### Description Initializes the libpython-clj2 environment. This must be called before any other Java API methods. It can be called with null or a custom Python home directory. ### Method `initialize(String pythonHome)` ### Parameters * **pythonHome** (String) - Optional - The path to the Python home directory. If null, the default Python installation will be used. ``` -------------------------------- ### Import Python Module and Call Attributes Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Demonstrates importing a Python module (numpy) and calling its attributes and methods, such as 'ones'. Also shows calling methods on returned objects like '__len__'. ```clojure (def np (import-module "numpy")) (def ones-ary (call-attr np "ones" [2 3])) ones-ary (call-attr ones-ary "__len__") (vec ones-ary) (type (first *1)) (get-attr ones-ary "shape") (vec (get-attr ones-ary "shape")) (dir ones-ary) ``` -------------------------------- ### Accessing Generated Python Namespace Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.codegen.html After generating a Clojure namespace from a Python module, you can require and use it like any other Clojure namespace. This example shows how to require the 'python.builtins' namespace and inspect the 'list' function. ```clojure (require '[python.builtins :as python]) nil (doc python/list) ``` -------------------------------- ### Initialize Python Interpreter (Linux/macOS) Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Initializes the Python interpreter on Linux and macOS systems. This is a common first step before interacting with Python objects. ```clojure (require '[libpython-clj2.python :refer [as-python as-jvm ->python ->jvm get-attr call-attr call-attr-kw get-item initialize! run-simple-string add-module module-dict import-module python-type dir] :as py]) ; Mac and Linux (initialize!) ``` -------------------------------- ### Initialize Python Interpreter Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Initializes the Python interpreter with optional configuration. Keyword arguments can be passed as strings. Note that operations are subject to the GIL. ```java java_api.initialize(options); ``` -------------------------------- ### Deserialize Pickled Bytes to Clojure Map Source: https://github.com/clj-python/libpython-clj/blob/master/docs/Usage.html Deserializes a byte string (previously created using pickle.dumps) back into a Python object, which is then implicitly converted to a Clojure data structure (a map in this example) using the 'pickle' module's 'loads' function. ```clojure (py/py. pickle loads py-bytes) ``` -------------------------------- ### Initialize libpython-clj and Access Python Modules Source: https://github.com/clj-python/libpython-clj/blob/master/topics/embedded.md Require the libpython-clj library, initialize the Python environment, and access the main module's dictionary. ```clojure user> (require '[libpython-clj2.python :as py]) nil ;; Python has been initialized and libpython-clj can detect this user> (py/initialize!) :already-initialized user> ;;We can share data via the main module user> (def main-mod (py/add-module "__main__")) #'user/main-mod user> (def mod-dict (py/module-dict main-mod)) #'user/mod-dict user> (keys mod-dict) ("__name__" "__doc__" "__package__" "__loader__" "__spec__" "__annotations__" "__builtins__" "cljbridge" "test_var") user> (get mod-dict "test_var") 10 ``` -------------------------------- ### Calling Superclass Constructor Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.class.html Demonstrates how to call the `__init__` method of a superclass when defining a new Python class from Clojure. This is a non-obvious way to handle inheritance. ```clojure (py. (py/get-item (py.. self -__class__ -__mro__) 1) __init__ self) ``` -------------------------------- ### from-import Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Supports Python's `from module import item` style of importing. ```APIDOC ## from-import ### Description Supports the `from module import a,b,c` style of importing modules and symbols in Python. ### Signature `(from-import module-path item & args)` ### Parameters * `module-path` - The path to the Python module. * `item` - The item to import from the module. * `&args` - Additional items to import. ### Example ```clojure (py/from-import "os" "path") ``` ``` -------------------------------- ### Require Mixed Modules with Common Prefix Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.require.html Loads 'foo.bar' with alias and referral, and 'foo.buster', using shorthand notation. ```clojure (require-python '(foo [bar :as baz :refer [qux]] buster)) ``` -------------------------------- ### with Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Provides support for Python's `with` statement, enabling context management for Python objects. ```APIDOC ## `with` ### Description Support for the `with` statement in Python. This macro allows you to manage Python context managers within Clojure. ### Usage Example ```clojure (py/with [item (py/call-attr testcode-module "WithObjClass" true fn-list)] (py/call-attr item "doit_err")) ``` ### Signature `(with bind-vec & body)` ### Parameters - `bind-vec` - A vector binding Python objects to local names, similar to `let`. - `body` - The expressions to execute within the `with` context. ``` -------------------------------- ### with-gil-stack-rc-context Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Combines the functionality of `with-gil` and `stack-resource-context` to manage the GIL and resource cleanup within a stack-based context. ```APIDOC ## `with-gil-stack-rc-context` ### Description This function likely combines the functionality of `with-gil` and `stack-resource-context`, providing a context where the Global Interpreter Lock (GIL) is held and Python objects are managed for automatic cleanup. ### Signature `(with-gil-stack-rc-context & body)` ### Parameters - `body` - The expressions to execute within this combined context. ``` -------------------------------- ### run-simple-string Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Executes a Python program provided as a string and returns a map containing the global and local dictionaries. It uses the `__main__` dictionary internally. ```APIDOC ## `run-simple-string` ### Description Run a string expression returning a map of `{:globals :locals}`. This uses the global `__main__` dict under the covers, matching the behavior of the cpython implementation, except for returning the various maps used. Note that this function will never return the result of the expression. ### Signature `(run-simple-string program & {:keys [globals locals]})` ### Parameters - `program` - The Python code to execute as a string. - `globals` - Optional map of global variables. - `locals` - Optional map of local variables. ### Behavior Implemented in CPython as: ```c PyObject *m, *d, *v; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; d = PyModule_GetDict(m); v = PyRun_StringFlags(command, Py_file_input, d, d, flags); if (v == NULL) { PyErr_Print(); return -1; } Py_DECREF(v); return 0; ``` ``` -------------------------------- ### create-class Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Creates a new Python class object. Instance methods can be defined using `make-instance-fn`. The `__init__` method should return nil. ```APIDOC ## create-class ### Description Creates a new Python class object. Any callable values in the `cls-hashmap` will be presented as instance methods. If you want access to the 'this' object then you must use `make-instance-fn`. ### Signature `(create-class name bases cls-hashmap)` ### Parameters * `name` - The name of the class. * `bases` - A tuple of base classes. * `cls-hashmap` - A map where keys are attribute names and values are attributes. Callables are treated as instance methods. ### Example ```clojure (require '[libpython-clj2.python :as py]) (def cls-obj (py/create-class "myfancyclass" nil {"__init__" (py/make-instance-fn (fn [this arg] (py/set-attr! this "arg" arg) nil)) "addarg" (py/make-instance-fn (fn [this otherarg] (+ (py/get-attr this "arg") otherarg))) })) (def inst (cls-obj 10)) (py/call-attr inst "addarg" 10) ;=> 20 ``` ``` -------------------------------- ### Capture GIL and Open Resource Context Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Use `with-gil-stack-rc-context` to capture the GIL and open a resource context. The context is released before the GIL, improving resource collection. This is recommended for production use for defined behavior and timings. ```clojure (with-gil-stack-rc-context ...) ``` -------------------------------- ### Creating a Keyword Instance Function Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.class.html Creates an instance function for a Python class where arguments are passed as JVM objects and keyword arguments are directly passed to the Clojure function. Supports custom argument and result converters. ```clojure (make-kw-instance-fn clj-fn & [{:keys [arg-converter result-converter], :or {arg-converter py-base/as-jvm}, :as options}]) ``` -------------------------------- ### make-instance-fn Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Creates a callable instance function. This function will receive the 'this' object as its first argument and defaults to using `as-jvm` for argument conversion. ```APIDOC ## `make-instance-fn` ### Description Makes a callable instance function, which is a function that will be passed the 'this' object as its first argument. It also calls `make-callable` with `as-jvm` as the default `arg-converter`. ### Signature `(make-instance-fn ifn options)` `(make-instance-fn ifn)` ### See Also - [make-callable](libpython-clj2.python.html#var-make-callable) - [libpython-clj2.python.class/make-tuple-instance-fn](libpython-clj2.python.class.html#var-make-tuple-instance-fn) ``` -------------------------------- ### Creating a NumPy array and slicing Source: https://github.com/clj-python/libpython-clj/blob/master/topics/slicing.md Creates a 3x3 NumPy array and demonstrates various slicing techniques using slice objects for rows and columns. ```clojure user> (def ary (-> (np/arange 9) (np/reshape [3 3]))) #'user/ary user> ary [[0 1 2] [3 4 5] [6 7 8]] user> (py/get-item ary [(builtins/slice 1 nil) (builtins/slice 1 nil)]) [[4 5] [7 8]] user> (py/get-item ary [(builtins/slice -1) (builtins/slice 1 nil)]) [[1 2] [4 5]] user> (py/get-item ary [(builtins/slice nil) (builtins/slice 1 nil)]) [[1 2] [4 5] [7 8]] user> (py/get-item ary [(builtins/slice nil) (builtins/slice 1 2)]) [[1] [4] [7]] user> (py/get-item ary [(builtins/slice nil) (builtins/slice 1 3)]) [[1 2] [4 5] [7 8]] user> (py/get-item ary [(builtins/slice nil) (builtins/slice 1 4)]) [[1 2] [4 5] [7 8]] ``` -------------------------------- ### py** Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html A macro similar to `py*`, but assumes the last argument provided is the keyword arguments map. ```APIDOC ## `py**` ### Description Similar to `py*`, but it is assumed that the LAST argument is the keyword arguments map. ### Signature `(py** x method kwargs)` `(py** x method arg & args)` ``` -------------------------------- ### Initialize Python Embedding Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.embedded.html Call `initialize!` to set up the Python environment when libpython-clj is invoked from Python. Optionally provide a `libpath` if Python symbols are not in the current executable. ```clojure (initialize!) (initialize! libpath) ``` -------------------------------- ### py* Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Provides special syntax for passing `*args` and `**kwargs` to Python methods, mimicking Python's argument unpacking. ```APIDOC ## `py*` ### Description Special syntax for passing along `*args` and `**kwargs` style arguments to methods, similar to Python's argument unpacking. ### Signature `(py* x method args)` `(py* x method args kwargs)` ### Usage `(py* obj method args kwargs)` ### Example ```clojure (def d (python/dict)) (def iterable [[:a 1] {:a 1} [:b 2] {:b 2}]) (def kwargs {:cat "dog" :name "taco"}) (py* d update [iterable](iterable) kwargs) ;; d will be updated with {"a": 1, "b": 2, "cat": "dog", "name": "taco"} ``` ``` -------------------------------- ### Require Custom Module from Specific Path Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.require.html Loads the custom Python module 'foo' from a specified directory '/path/to/foodir'. ```clojure (require-python :from "/path/to/foodir" 'foo) ``` ```clojure (require-python "/path/to/foodir" 'foo) ``` ```clojure (require-python {:from "/path/to/foodir"} 'foo) ``` -------------------------------- ### Importing necessary libraries Source: https://github.com/clj-python/libpython-clj/blob/master/topics/slicing.md Requires the libpython-clj python and require namespaces, and then loads the builtins and numpy libraries. ```clojure user> (require '[libpython-clj.python :as py]) nil user> (require '[libpython-clj.require :refer [require-python]]) ... lotta logs ... user> (require-python '[builtins]) WARNING: AssertionError already refers to: class java.lang.AssertionError in namespace: builtins, being replaced by: #'builtins/AssertionError WARNING: Exception already refers to: class java.lang.Exception in namespace: builtins, being replaced by: #'builtins/Exception :ok user> (doc builtins/slice) ------------------------- builtins/slice [[self & [args {:as kwargs}]]] slice(stop) slice(start, stop[, step]) Create a slice object. This is used for extended slicing (e.g. a[0:10:2]). nil user> (require-python '[numpy :as np]) :ok ``` -------------------------------- ### create-class Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.class.html Create a new class object. Any callable values in the cls-hashmap will be presented as instance methods. Things in the cls hashmap had better be either atoms or already converted python objects. ```APIDOC ## create-class ### Description Create a new class object. Any callable values in the cls-hashmap will be presented as instance methods. Things in the cls hashmap had better be either atoms or already converted python objects. You may get surprised otherwise; you have been warned. See the classes-test file in test/libpython-clj. Calling `super.init()` may be done in a non-obvious way: ```clojure (py. (py/get-item (py.. self -__class__ -__mro__) 1) __init__ self) ``` More feedback/research in this area is needed to integrated deeper into the python class hierarchies. ### Signature `(create-class name bases cls-hashmap)` ``` -------------------------------- ### Run String as File Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.java-api.html Executes a Python script provided as a string, treating it as if it were a file. This is useful for running scripts that expect to be executed from a file context. ```APIDOC ## runStringAsFile ### Description Executes a Python script provided as a string, treating it as if it were a file. This is useful for running scripts that expect to be executed from a file context. ### Method `runStringAsFile(String script, String filename)` ### Parameters * **script** (String) - Required - The Python script content as a string. * **filename** (String) - Required - A name for the script, used for error reporting and module context. ``` -------------------------------- ### Deploy to Clojars Source: https://github.com/clj-python/libpython-clj/blob/master/README.md Deploys the project's jar file to the Clojars repository. This command automatically signs the jar using your GPG key before deployment. ```bash $ clj -X:deploy ``` -------------------------------- ### Create Python Class with Methods Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Defines a Python class with an initializer and an instance method. Instance methods defined in the `cls-hashmap` are callable on instances. Use `make-instance-fn` for methods that need access to the 'this' object. ```clojure (require '[libpython-clj2.python :as py]) (def cls-obj (py/create-class "myfancyclass" nil {"__init__" (py/make-instance-fn (fn [this arg] (py/set-attr! this "arg" arg) nil)) "addarg" (py/make-instance-fn (fn [this otherarg] (+ (py/get-attr this "arg") otherarg)))} )) cls-obj (def inst (cls-obj 10)) inst (py/call-attr inst "addarg" 10) ``` -------------------------------- ### Process a batch of items with mapv, time, and with-gil Source: https://github.com/clj-python/libpython-clj/blob/master/docs/scopes-and-gc.html Similar to the previous snippet, this processes a batch of Python dictionaries but explicitly acquires the Global Interpreter Lock (GIL) using `with-gil` before mapping to JVM objects. This can sometimes improve performance for batch operations. ```clojure (def ignored (time (py/with-gil (mapv py/->jvm dict-seq)))) "Elapsed time: 2095.815518 msecs" #'user/ignored ``` -------------------------------- ### py. Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Provides syntax for calling methods on Python objects or classes, analogous to Python's `obj.method(arg1, arg2, ...)`. ```APIDOC ## `py.` ### Description Class/object method syntax. `(py. obj method arg1 arg2 ... argN)` is equivalent to Python's `obj.method(arg1, arg2, ..., argN)` syntax. ### Signature `(py. x method-name & args)` ``` -------------------------------- ### Python `*args` and `**kwargs` Syntax Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Special syntax is provided to programmatically handle Python's `*args` and `**kwargs`. These forms are useful when you need to pass a map of options similar to Python's `f(*args, **kwargs)`. ```clojure (= (py.. obj (_method args)) (py_ obj methods args)) ``` ```clojure (= (py.. obj (_method args kwargs)) (py_ obj method args kwargs)) ``` ```clojure (= (py.. obj (**method kwargs)) (py** obj method kwargs)) ``` ```clojure (= (py.. obj (**method arg1 arg2 arg3 ... argN kwargs)) (py** obj method arg1 arg2 arg3 ... argN kwargs) (py* obj method [arg1 arg2 arg3 ... argN](arg1 arg2 arg3 ... argN) kwargs)) ``` -------------------------------- ### import-as Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Imports a Python module and assigns it to a specified variable name. ```APIDOC ## import-as ### Description Import a module and assign it to a var. ### Signature `(import-as module-path varname)` ### Parameters * `module-path` - The path to the Python module. * `varname` - The name to assign the imported module to. ### Example ```clojure (py/import-as "math" "my-math") ``` ``` -------------------------------- ### make-kw-instance-fn Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.class.html Make an instance function - a function which will be passed the 'this' object as it's first argument. The default behavior is to pass as-jvm bridged python object ptr args and kw dict args to the clojure function without marshalling. ```APIDOC ## make-kw-instance-fn ### Description Make an instance function - a function which will be passed the 'this' object as it's first argument. In this case the default behavior is to pass as-jvm bridged python object ptr args and kw dict args to the clojure function without marshalling. Self will be the first argument of the arg vector. See options to [libpython-clj2.python/make-callable](libpython-clj2.python.html#var-make-callable). ### Signature `(make-kw-instance-fn clj-fn & [{:keys [arg-converter result-converter], :or {arg-converter py-base/as-jvm}, :as options}])` ### Options * `:arg-converter` - gets one argument and must convert into jvm space - defaults to as-jvm. * `:result-converter` - gets one argument and must convert to python space. Has reasonable default. ``` -------------------------------- ### Process a batch of items with mapv and time Source: https://github.com/clj-python/libpython-clj/blob/master/docs/scopes-and-gc.html Converts a sequence of Python dictionaries to JVM objects using `mapv` and measures the execution time. This shows a basic batch processing approach without explicit GIL management. ```clojure (def dict-seq (py/as-jvm (py/->py-list (repeat 1000 (py/->py-dict {:a 1 :b 2}))))) #'user/dict-seq (def ignored (time (mapv py/->jvm dict-seq))) "Elapsed time: 2200.556506 msecs" #'user/ignored ``` -------------------------------- ### py-fn->instance-fn Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.class.html Given a python callable, return an instance function meant to be used in class definitions. ```APIDOC ## py-fn->instance-fn ### Description Given a python callable, return an instance function meant to be used in class definitions. ### Signature `(py-fn->instance-fn py-fn)` ``` -------------------------------- ### Batch processing with GIL and mapv Source: https://github.com/clj-python/libpython-clj/blob/master/topics/scopes-and-gc.md Compares the performance of converting Python lists to JVM objects with and without explicitly acquiring the Global Interpreter Lock (GIL). Acquiring the GIL can sometimes offer minor performance benefits for batch operations. ```clojure user> (def dict-seq (py/as-jvm (py/->py-list (repeat 1000 (py/->py-dict {:a 1 :b 2}))))) #'user/dict-seq user> (def ignored (time (mapv py/->jvm dict-seq))) "Elapsed time: 2200.556506 msecs" #'user/ignored user> (def ignored (time (py/with-gil (mapv py/->jvm dict-seq)))) "Elapsed time: 2095.815518 msecs" #'user/ignored ``` -------------------------------- ### Call Function from Required Module Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.require.html Demonstrates calling a function (sin) from a previously required Python module (math). ```clojure (math/sin 1.0) ``` -------------------------------- ### Run Python String with `run-simple-string` Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Execute a Python program provided as a string. This function returns a map of {:globals :locals} and uses the global `__main__` dictionary internally. Note that this function does not return the result of the expression. ```clojure (run-simple-string program & {:keys [globals locals]}) ``` -------------------------------- ### $c Source: https://github.com/clj-python/libpython-clj/blob/master/docs/libpython-clj2.python.html Calls a Python object, automatically detecting Python keyword arguments. Keywords must be compile-time constants. Argument mapping is done at compile time. ```APIDOC ## $c ### Description Calls a Python object, automatically detecting Python keyword arguments. Keywords must be compile-time constants. Argument mapping is done at compile time. ### Signature `($c item & args)` ``` -------------------------------- ### Accessing Python attributes with $ . and $.. Source: https://github.com/clj-python/libpython-clj/blob/master/topics/Usage.md Illustrates experimental syntax sugar for accessing Python attributes and methods using `$.` for direct access and `$..` for chained access. ```clojure user> (py/$. numpy linspace) user> (py/$.. numpy random shuffle) ```