We aim to provide an interface that is close enough to allow developing Prolog code that uses Python and visa versa. Differences between the two Prolog implementation make this non-trivial. SWI-Prolog has native support for dicts, strings, unbounded integers, rational numbers and blobs that provide safe pointers to external objects that are subject to (atom) garbage collection.
We try to find a compromise to make the data conversion as close as 
possible while supporting both systems as good as possible. For this 
reason we support creating a Python dict both from a SWI-Prolog dict and 
from the Prolog term py({k1:v1, k2:v2, ...}). With
py defined as a prefix operator, this may be written 
without parenthesis and is thus equivalent to the SWI-Prolog dict 
syntax. The library(janus) library provides access 
predicates that are supported by both systems and where the SWI-Prolog 
version supports both SWI-Prolog dicts and the above Prolog 
representation. See
items/2, values/3, key/2 
and items/2.
Calling Python from Prolog provides a low-level and a more high level interface. The high level interface is realized by py_call/[2,3] and py_iter/[2,3]. We realize the low level interfaces py_func/[3,4] and py_dot/[4,5] on top of py_call/2. The interface for calling Prolog from Python is settled on the five primitives described in section 5.
We are discussing to minimize the differences. Below we summarize the known differences.
py() wrapper is optional. The 
predicate py_is_dict/1 
may be used to test that a Prolog term represents a Python dict. The 
predicates values/3, keys/2, key/2 
and items/2 
can be used to access either representation.prolog(Term) to be sent to 
Python, creating an instance of janus.Term().janus.undefined) 
are supported in a portable way. Delay lists, providing details 
on why the result is undefined, are represented differently.
This section will be written after the dust has settled. Topics