inline-python-0.2.0.1: src/Python/Inline.hs
-- | This library allows to embed as quasiquotes and execute arbitrary
-- python code in haskell programs. Take for example following program:
--
-- > {-# LANGUAGE QuasiQuotes #-}
-- > import Control.Monad
-- > import Python.Inline
-- > import Python.Inline.QQ
-- >
-- > main :: IO ()
-- > main = withPython $ do
-- > let input = [1..10] :: [Int]
-- > let square :: Int -> Py Int
-- > square x = pure (x * x)
-- > print <=< runPy $ do
-- > fromPy' @[Int] =<< [pye| [ square_hs(x) for x in input_hs ] |]
--
-- Quasiquotation 'Python.Inline.QQ.pye' captures variables @input@
-- and @square@ from environment and produces python object which
-- `fromPy'` converts to haskell list. As one expect it would output:
--
-- > [1,4,9,16,25,36,49,64,81,100]
--
-- Module "Python.Inline.QQ" provides several quasiquoters with
-- different semantics but general rules are:
--
-- 1. All python variables ending with @_hs@ are captured from
-- environment and converted to python objects according to their
-- 'ToPy' instance.
--
-- 2. Syntax errors in embedded python will be caught during
-- compilation.
--
-- 3. All code interacting with python must be in 'Py' monad which
-- could be run using 'runPy'.
--
-- 4. Python interpreter must be initialized before calling any
-- python code.
module Python.Inline
( -- * Interpreter initialization
-- $initialization
initializePython
, finalizePython
, withPython
-- * Core data types
, Py
, runPy
, runPyInMain
, PyObject
, PyError(..)
, PyException(..)
-- * Conversion between haskell and python
-- $conversion
, toPy
, fromPyEither
, fromPy
, fromPy'
, ToPy
, FromPy
-- * Troubleshooting
-- $troubleshooting
) where
import Python.Inline.Literal
import Python.Internal.Types
import Python.Internal.Eval
-- $initialization
--
-- Python supports being initialized and shut down multiple times.
-- This however has caveats. Quoting it documentation:
--
-- > Bugs and caveats: The destruction of modules and objects in
-- > modules is done in random order; this may cause destructors
-- > (__del__() methods) to fail when they depend on other objects
-- > (even functions) or modules. Dynamically loaded extension
-- > modules loaded by Python are not unloaded. Small amounts of
-- > memory allocated by the Python interpreter may not be freed (if
-- > you find a leak, please report it). Memory tied up in circular
-- > references between objects is not freed. Some memory allocated
-- > by extension modules may not be freed. Some extensions may not
-- > work properly if their initialization routine is called more
-- > than once.
--
-- More importantly for this library. All pointers held by 'PyObject'
-- becomes invalid after interpreter is shut down. If GC tries to run
-- finalizers after interpreter is intialized again program will
-- surely segfault.
--
-- For that reason it's only possible to initialize python once and
-- attempts to initialize python after is was shut down will raise
-- exceptions.
-- $conversion
--
-- Python objects are opaque blobs and accessing them may involve
-- running arbitrary python code. Most notable iteration protocol or
-- any of dunder methods. For that reason conversion from python to
-- haskell must happen in 'Py' monad. Conversion also always performs
-- full copy. Conversion from haskell to python is stateful as well.
-- $troubleshooting
--
-- Here's list of common problems and solutions and workarounds.
--
-- 1. __@inline-python@ cannot find libraries__
--
-- @inline-python@ may look for modules in wrong place. Set
-- environment variables @PYTHONHOME@ or @PYTHONPATH@ to point it
-- right way.
--
--
-- 2. __Linker error in GHCi__
--
-- Attempting to import library using C extensions from ghci may
-- result in linker failing to find symbols from @libpython@ like
-- @PyFloat_Type@ or some other. Only known workaround is to set
-- @LD_PRELOAD=/path/to/libpython3.XX.so@ environment variable.