{"id":13803935,"url":"https://github.com/pinterface/burgled-batteries","last_synced_at":"2026-01-10T21:40:17.136Z","repository":{"id":78326471,"uuid":"11207092","full_name":"pinterface/burgled-batteries","owner":"pinterface","description":"A bridge between Python and Lisp (FFI bindings, etc.)","archived":false,"fork":false,"pushed_at":"2017-10-21T02:15:34.000Z","size":174,"stargazers_count":113,"open_issues_count":7,"forks_count":21,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-11-18T20:49:28.248Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pinterface.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-07-05T19:38:34.000Z","updated_at":"2024-07-13T16:21:06.000Z","dependencies_parsed_at":"2023-03-08T14:30:23.926Z","dependency_job_id":null,"html_url":"https://github.com/pinterface/burgled-batteries","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinterface%2Fburgled-batteries","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinterface%2Fburgled-batteries/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinterface%2Fburgled-batteries/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pinterface%2Fburgled-batteries/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pinterface","download_url":"https://codeload.github.com/pinterface/burgled-batteries/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253992930,"owners_count":21996200,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T01:00:39.305Z","updated_at":"2026-01-10T21:40:17.091Z","avatar_url":"https://github.com/pinterface.png","language":"Common Lisp","funding_links":[],"categories":["Python ##"],"sub_categories":[],"readme":"#+TITLE: burgled-batteries: A Common Lisp / Python Bridge\n\nburgled-batteries provides a shim between Python (specifically, the CPython\nimplementation of Python) and Common Lisp.\n\n* Synopsis\n\n#+begin_src lisp\n  (asdf:load-system \"burgled-batteries\")\n  (in-package #:burgled-batteries)\n  (startup-python)\n  \n  (run \"1+1\") ; =\u003e 2\n  \n  (import \"feedparser\")\n  (defpyfun \"feedparser.parse\" (thing))\n  (documentation 'feedparser.parse 'function)\n  ; =\u003e \"Parse a feed from a URL, file, stream, or string\"\n  (feedparser.parse \"http://pinterface.livejournal.com/data/atom\")\n  ; =\u003e #\u003cHASH-TABLE\u003e\n  \n  (shutdown-python)\n#+end_src\n\n* Why burgled-batteries\nCLPython is great when it works.  However, if you're using a low-resource\ncomputer—perhaps an underpowered VPS, or a Linux box salvaged from the 90s—, or\nneed access to a Python library written in C, or there's a bug and you can't be\nbothered to narrow it down to a small test case, CLPython can't help you.  Two\nout of three of those are more your problem than CLPython's, but hey, I'm not\nhere to judge.\n\nWhile a number of other Python-by-FFI options exist, burgled-batteries aims for\na CLPython-esque level of integration.  In other words, *deep* integration.  You\nshouldn't have to care that the library you're using was written in Python—it\nshould Just Work.\n\nCertainly, b-b is not there yet.  It may never be there completely.  But we'll\n/try/, dagnabbit.\n\n* Basic Type Mapping\nPython objects are converted to a Lisp object where possible.  Where a\nconversion is unknown, a pointer to the CPython object is returned (or, if\ninside a refcnt barrier, a wrapper around the pointer which will become invalid\nupon exiting the barrier).  In general, this mapping follows the lead of\nCLPython.\n\n| Python Type   | Lisp Type         |\n|---------------+-------------------|\n| Boolean       | (member T NIL)    |\n| Integer, Long | Integer           |\n| Float         | Double-float      |\n| Dict          | Hashtable         |\n| Unicode       | String            |\n| List          | Adjustable vector |\n| Tuple         | List              |\n| Complex       | Complex           |\n| ByteArray     | Octet vector      |\n| Exception     | Condition         |\n| \u003cUnknown\u003e     | \u003cpointer\u003e         |\n\n* CPython FFI\nAnything dealing with the CPython API can be found in the PYTHON.CFFI package.\nSee the docstring for that package for more information, as well as Python's [[http://docs.python.org/c-api/][C API]].\n\n* Calling Python from Lisp\n * IMPORT   :: Equivalent to \"import \u003cfoo\u003e\" in Python.\n * RUN      :: Mimicks the RUN function from CLPython.\n * DEFPYFUN :: Similar to CFFI's DEFCFUN—defines a Lisp function which calls a\n               Python function.  Ideally, this will eventually be obviated by\n               something which uses Python introspection to figure out an\n               apropriate argument list so you don't have to, but it'll get you\n               going for now.\n\n* Calling Lisp from Python\nNot yet supported, but see ffi-callbacks.lisp for some experimentation and notes\nalong those lines.\n\n* Avoid the Hassle of Reference Counts\nBecause dealing with reference counts is Just No Fun and Not Lispy At All, as\nwell as Inevitable—at some point there will be an object for which no\ntranslation is known—, b-b provides multiple options to avoid dealing with\nrefcnts for those untranslatable pointers.  See the macro\nCPYTHON:WITH-UNKNOWN-TRANSLATION-POLICY.\n\nNote that this policy also also affects the EXCEPTION-* slots of\nPYTHON-CONDITION, and so they may or may not be available for inspection\ndepending on the translation policy in effect and the manner of handling.\n\nFor example, under the default policy of :DISCARD, you would see something like:\n#+begin_src lisp\n(defun reveal-effect (c)\n  (format t \"~A~%\" (slot-value c 'exception-type)))\n\n(handler-bind ((python-condition #'reveal-effect))\n  (burgled-batteries:run \"1/0\"))\n; prints #.(SB-SYS:INT-SAP #X?????)\n\n(handler-case (burgled-batteries:run \"1/0\")\n  (python-condition (c) (reveal-effect c)))\n; prints NIL\n#+end_src\n\nIf you'd like access to Python types without a known translation, :BARRIER\nor :FINALIZE are highly recommended over :PASS-THROUGH.  They do, however, come\nwith [[http://pinterface.livejournal.com/40934.html][some caveats]] which you should be aware of.\n\n* Requirements\n\nBurgled-batteries links with C code, and accordingly requires the appropriate\nheaders and library files.  On Debian-based systems, you can get these via:\n#+begin_src sh\n  sudo apt-get install python-dev\n#+end_src\n\n* Testing\n\n#+begin_src\n  (asdf:test-system \"burgled-batteries\")\n#+end_src\n\nTests have been run under SBCL, Clozure CL, and CLISP.\n\n* To Do\n * Output redirection\n * Callbacks\n * Whole-module import (into own package?)\n * Python object \u003c-\u003e CLOS mappings\n * Provide facilities for user code to define own Lisp-Python mappings\n * Better integrate Quickcheck tests, so LIFT knows about quickcheck failures\n * Pathname support (requires FILE* support)\n\n* Prior Art / Other Solutions\n * [[http://common-lisp.net/project/python-on-lisp/][Python-on-Lisp]] :: It was a good try back in 2006, but unfortunately has\n   experienced significant bitrot.  It did manage to provide callbacks and\n   writing to Lisp streams, however (both of which are still on b-b's TODO\n   list).  Very handy features!\n * [[http://www2s.biglobe.ne.jp/~niitsuma/pythononlispex.html][pythononlisp-ex]] :: A fork of Python-on-Lisp which shimmies things between\n   Lisp and Python using JSON.  As you might expect, this falls down as soon as\n   you hit something which can't be represented in JSON, which covers quite a\n   lot of types.\n * [[http://www.cliki.net/Pyffi][Pyffi]] :: A more streamlined, and less featureful, Python FFI which came after\n   PoL.  Technically, burgled-batteries began life as some patches to Pyffi\n   because it seemed to be the best place to start.  (Almost nothing of Pyffi\n   remains.)\n * [[http://common-lisp.net/project/clpython/][CLPython]] :: A very fine Python compiler written in Common Lisp.  It requires\n   a somewhat beefier machine than CPython.  Unfortunately, it doesn't work with\n   Python libraries written in C (e.g., numpy), and so is unable to handle the\n   full gamut of Python libraries one might wish to borrow.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpinterface%2Fburgled-batteries","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpinterface%2Fburgled-batteries","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpinterface%2Fburgled-batteries/lists"}