Conversion Rules

This page documents the rules used to convert values between Julia and Python.

In both directions, the default behaviour is to allow conversion between immutable values. Mutable values will be "wrapped" so that mutations on the wrapper affect the original object.

Julia to Python

When a Julia object is converted to a Python one (e.g. by calling PyObject, by interpolating it into a @py command, or passing it as an argument to a Python function) the following rules are used by default.

The user can always explicitly choose a different conversion (e.g. by calling pylist or pydict).

FromTo
Any Python object type (PyObject, PyList, etc.)itself
Nothing, MissingNone
Boolbool
Standard integer (IntXX, UIntXX, BigInt)int
Standard rational (Rational{T}, T a standard integer)fractions.Fraction
Standard float (FloatXX)float
Standard complex (Complex{T}, T a standard float)complex
Standard string/char (String and SubString{String}, Char)str
Tupletuple
Standard integer range (AbstractRange{T}, T a standard integer)range
Date, Time, DateTime (from Dates)date, time, datetime (from datetime)
Second, Millisecond, Microsecond, Nanosecond (from Dates)timedelta (from datetime)
Numberjuliacall.NumberValue, juliacall.ComplexValue, etc.
AbstractArrayjuliacall.ArrayValue, juliacall.VectorValue
AbstractDictjuliacall.DictValue
AbstractSetjuliacall.SetValue
IOjuliacall.BufferedIOValue
Modulejuliacall.ModuleValue
Typejuliacall.TypeValue
Anything elsejuliacall.AnyValue

The juliacall.*Value types are all subtypes of juliacall.AnyValue. They wrap a Julia value, providing access to Julia semantics: it can be called, indexed, and so on. Subtypes add additional Pythonic semantics. Read more here.

This conversion policy is defined/implemented by PythonCall.C.PyObject_From and PythonCall.C.PyJuliaValue_From. Package authors can (carefully) overload these with additional rules for custom types.

Python to Julia

From Julia, one can convert Python objects to a desired type using pyconvert(T, x) for example, or @pyv `...`::T.

From Python, when a value is passed to Julia, it is typically converted to a corresponding Julia value using pyconvert(Any, x).

Quite general conversions are allowed, and the target type T can be as specific as you like. For example

@pyv `[1, None, 3]`::Tuple{Vararg{Union{AbstractFloat,Missing}}}

evaluates to (1.0, missing, 2.0).

The following table specifies the conversion rules in place. If the initial Python type matches the "From" column and the desired type T intersects with the "To" column, then that conversion is attempted. Conversions are tried in priority order, then in specificity order.

FromTo
Top priority (wrapped values).
juliacall.AnyValueAny
Very high priority (arrays).
Objects satisfying the buffer or array interface (inc. bytes, bytearray, array.array, numpy.ndarray)PyArray
High priority (canonical conversions).
NoneNothing
boolBool
numbers.Integral (inc. int)Integer (prefers Int, or BigInt on overflow)
floatFloat64
complexComplex{Float64}
rangeStepRange
strString
tupleTuple
collections.abc.Mapping (inc. dict)PyDict
collections.abc.Sequence (inc. list)PyList
collections.abc.Set (inc. set, frozenset)PySet
io.IOBase (includes open files)PyIO
datetime.date/datetime.time/datetime.datetimeDate/Time/DateTime
datetime.timedeltaMicrosecond (or Millisecond or Second on overflow)
numpy.intXX/numpy.uintXX/numpy.floatXXIntXX/UIntXX/FloatXX
Standard priority (other reasonable conversions).
NoneMissing
bytesVector{UInt8}, Vector{Int8}, String
strString, Symbol, Char, Vector{UInt8}, Vector{Int8}
rangeUnitRange
collections.abc.MappingDict
collections.abc.IterableVector, Set, Tuple, NamedTuple, Pair
datetime.timedeltaDates.CompoundPeriod
numbers.IntegralInteger, Rational, Real, Number
numbers.RealAbstractFloat, Number
numbers.ComplexComplex, Number
ctypes.c_int and other integersInteger, Rational, Real, Number
ctypes.c_float/ctypes.c_doubleCfloat/Cdouble, AbstractFloat, Real, Number
ctypes.c_voidpPtr{Cvoid}, Ptr
ctypes.c_char_pCstring, Ptr{Cchar}, Ptr
ctypes.c_wchar_pCwstring, Ptr{Cwchar}, Ptr
numpy.intXX/numpy.uintXX/numpy.floatXXInteger, Rational, Real, Number
Low priority (fallback to PyObject).
AnythingPyObject
Bottom priority (must be explicitly specified by excluding PyObject).
Objects satisfying the buffer interfacePyBuffer
AnythingPyRef

Package authors can (carefully) add extra rules by calling PythonCall.C.PyObject_TryConvert_AddRule in __init__.