The Julia module PythonCall

Installation

This package is in the general registry, so to install just type ] in the Julia REPL and run:

pkg> add PythonCall

Getting started

Import the module with:

julia> using PythonCall

By default this will initialize a conda environment in your Julia environment, install Python into it, load the corresponding Python library and initialize an interpreter.

Now you can interact with Python as follows:

julia> re = pyimport("re")
Python module: <module 're' from '[...]/lib/re.py'>

julia> words = re.findall("[a-zA-Z]+", "PythonCall.jl is very useful!")
Python list: ['PythonCall', 'jl', 'is', 'very', 'useful']

julia> sentence = Py(" ").join(words)
Python str: 'PythonCall jl is very useful'

julia> pyconvert(String, sentence)
"PythonCall jl is very useful"

In this example:

  • We used pyimport to import the re module. Equivalently we could have done @py import re (see @py).
  • We called its findall function on a pair of strings, which were automatically converted to Python strings (see Conversion to Python).
  • We called Py to explicitly convert a string to a Python string, so that we could call its join method. All Python objects are of type Py.
  • We called pyconvert to convert the Python string sentence to a Julia string (see Conversion to Julia).

Read on to find out what else you can do.

Py

PythonCall.@pyconstMacro
@pyconst ex

Equivalent to Py(ex) but always returns the exact same Julia object.

That is, if foo() = @pyconst ex then foo() === foo().

The expression ex is evaluated the first time the code is run.

If ex is a string literal, the string is interned.

Do not use this macro at the top level of a module. Instead, use pynew() and pycopy!().

The object pybuiltins has all the standard Python builtin objects as its properties. Hence you can access pybuiltins.None and pybuiltins.TypeError.

@py

PythonCall.@pyMacro
@py expr

Evaluate the given expression using Pythonic semantics.

For example:

  • f(x, y) is translated to pycall(f, x, y)
  • x + y is translated to pyadd(x, y)
  • x === y is translated to pyis(x, y)
  • x.foo is translated to pygetattr(x, "foo")

Compound statements such as begin, if, while and for are supported.

See the online documentation for more details.

Python functions

Most of the functions in this section are essentially Python builtins with a py prefix. For example pyint(x) converts x to a Python int and is equivalent to int(x) in Python when x is a Python object.

Notable exceptions are:

  • pyconvert to convert a Python object to a Julia object.
  • pyimport to import a Python module.
  • pyjl to directly wrap a Julia object as a Python object.
  • pyclass to construct a new class.
  • pywith to emulate the Python with statement.

If a Julia value is passed as an argument to one of these functions, it is converted to a Python value using the rules documented here.

Constructors

These functions construct Python objects of builtin types from Julia values.

PythonCall.pycomplexFunction
pycomplex(x=0.0)
pycomplex(re, im)

Convert x to a Python complex, or create one from given real and imaginary parts.

PythonCall.pytupleFunction
pytuple(x=())

Convert x to a Python tuple.

If x is a Python object, this is equivalent to tuple(x) in Python. Otherwise x must be iterable.

PythonCall.pylistFunction
pylist(x=())

Convert x to a Python list.

If x is a Python object, this is equivalent to list(x) in Python. Otherwise x must be iterable.

PythonCall.pycollistFunction
pycollist(x::AbstractArray)

Create a nested Python list-of-lists from the elements of x. For matrices, this is a list of columns.

PythonCall.pyrowlistFunction
pyrowlist(x::AbstractArray)

Create a nested Python list-of-lists from the elements of x. For matrices, this is a list of rows.

PythonCall.pysetFunction
pyset(x=())

Convert x to a Python set.

If x is a Python object, this is equivalent to set(x) in Python. Otherwise x must be iterable.

PythonCall.pyfrozensetFunction
pyfrozenset(x=())

Convert x to a Python frozenset.

If x is a Python object, this is equivalent to frozenset(x) in Python. Otherwise x must be iterable.

PythonCall.pydictFunction
pydict(x)
pydict(; x...)

Convert x to a Python dict. In the second form, the keys are strings.

If x is a Python object, this is equivalent to dict(x) in Python. Otherwise x must iterate over key-value pairs.

PythonCall.pysliceFunction
pyslice([start], stop, [step])

Construct a Python slice. Unspecified arguments default to None.

PythonCall.pyrangeFunction
pyrange([[start], [stop]], [step])

Construct a Python range. Unspecified arguments default to None.

PythonCall.pyclassFunction
pyclass(name, bases=(); members...)

Construct a new Python type with the given name, bases and members.

Equivalent to pytype(name, bases, members).

Builtins

These functions mimic the Python builtin functions or keywords of the same name.

PythonCall.pyimportFunction
pyimport(m)
pyimport(m => k)
pyimport(m => (k1, k2, ...))
pyimport(m1, m2, ...)

Import a module m, or an attribute k, or a tuple of attributes.

If several arguments are given, return the results of importing each one in a tuple.

PythonCall.pywithFunction
pywith(f, o, d=nothing)

Equivalent to with o as x: f(x) in Python, where x is a Py.

On success, the value of f(x) is returned.

If an exception occurs but is suppressed then d is returned.

PythonCall.pyisFunction
pyis(x, y)

True if x and y are the same Python object. Equivalent to x is y in Python.

PythonCall.pygetattrFunction
pygetattr(x, k, [d])

Equivalent to getattr(x, k) or x.k in Python.

If d is specified, it is returned if the attribute does not exist.

PythonCall.pysetattrFunction
pysetattr(x, k, v)

Equivalent to setattr(x, k, v) or x.k = v in Python.

PythonCall.pycallFunction
pycall(f, args...; kwargs...)

Call the Python object f with the given arguments.

PythonCall.pylenFunction
pylen(x)

The length of x. Equivalent to len(x) in Python, converted to an Integer.

PythonCall.pysetitemFunction
pysetitem(x, k, v)

Equivalent to setitem(x, k, v) or x[k] = v in Python.

PythonCall.pyissubclassFunction
pyissubclass(s, t)

Test if s is a subclass of t. Equivalent to issubclass(s, t) in Python.

PythonCall.pyisinstanceFunction
pyisinstance(x, t)

Test if x is of type t. Equivalent to isinstance(x, t) in Python.

PythonCall.pyhashFunction
pyhash(x)

Equivalent to hash(x) in Python, converted to an Integer.

Conversion to Julia

These functions convert Python values to Julia values, using the rules documented here.

PythonCall.pyconvertFunction
pyconvert(T, x, [d])

Convert the Python object x to a T.

If d is specified, it is returned on failure instead of throwing an error.

PythonCall.@pyconvertMacro
@pyconvert(T, x, [onfail])

Convert the Python object x to a T.

On failure, evaluates to onfail, which defaults to return pyconvert_unconverted() (mainly useful for writing conversion rules).

Wrap Julia values

These functions explicitly wrap Julia values into Python objects, documented here.

As documented here, Julia values are wrapped like this automatically on conversion to Python, unless the value is immutable and has a corresponding Python type.

PythonCall.pyjlFunction
pyjl([t], x)

Create a Python object wrapping the Julia object x.

If x is mutable, then mutating the returned object also mutates x, and vice versa.

Its Python type is normally inferred from the type of x, but can be specified with t.

For example if x is an AbstractVector then the object will have type juliacall.VectorValue. This object will satisfy the Python sequence interface, so for example uses 0-up indexing.

PythonCall.pyjlrawFunction
pyjlraw(v)

Create a Python object wrapping the Julia object x.

It has type juliacall.RawValue. This has a much more rigid "Julian" interface than pyjl(v). For example, accessing attributes or calling this object will always return a RawValue.

PythonCall.pyisjlFunction
pyisjl(x)

Test whether x is a wrapped Julia value, namely an instance of juliacall.ValueBase.

PythonCall.pybinaryioFunction
pybinaryio(io::IO)

Wrap io as a Python binary IO object.

This is the default behaviour of Py(io).

Arithmetic

These functions are equivalent to the corresponding Python arithmetic operators.

Note that the equivalent Julia operators are overloaded to call these when all arguments are Py (or Number). Hence the following are equivalent: Py(1)+Py(2), Py(1)+2, pyadd(1, 2), pyadd(Py(1), Py(2)), etc.

PythonCall.pypowFunction
pypow(x, y, z=None)

Equivalent to x ** y or pow(x, y, z) in Python.

PythonCall.pyiaddFunction
pyiadd(x, y)

In-place add. x = pyiadd(x, y) is equivalent to x += y in Python.

PythonCall.pyisubFunction
pyisub(x, y)

In-place subtract. x = pyisub(x, y) is equivalent to x -= y in Python.

PythonCall.pyimulFunction
pyimul(x, y)

In-place multiply. x = pyimul(x, y) is equivalent to x *= y in Python.

PythonCall.pyimatmulFunction
pyimatmul(x, y)

In-place matrix multiply. x = pyimatmul(x, y) is equivalent to x @= y in Python.

PythonCall.pyipowFunction
pyipow(x, y, z=None)

In-place power. x = pyipow(x, y) is equivalent to x **= y in Python.

PythonCall.pyifloordivFunction
pyifloordiv(x, y)

In-place floor divide. x = pyifloordiv(x, y) is equivalent to x //= y in Python.

PythonCall.pyitruedivFunction
pyitruediv(x, y)

In-place true division. x = pyitruediv(x, y) is equivalent to x /= y in Python.

PythonCall.pyimodFunction
pyimod(x, y)

In-place subtraction. x = pyimod(x, y) is equivalent to x %= y in Python.

PythonCall.pyilshiftFunction
pyilshift(x, y)

In-place left shift. x = pyilshift(x, y) is equivalent to x <<= y in Python.

PythonCall.pyirshiftFunction
pyirshift(x, y)

In-place right shift. x = pyirshift(x, y) is equivalent to x >>= y in Python.

PythonCall.pyiandFunction
pyiand(x, y)

In-place and. x = pyiand(x, y) is equivalent to x &= y in Python.

PythonCall.pyixorFunction
pyixor(x, y)

In-place xor. x = pyixor(x, y) is equivalent to x ^= y in Python.

PythonCall.pyiorFunction
pyior(x, y)

In-place or. x = pyior(x, y) is equivalent to x |= y in Python.

Logic

These functions are equivalent to the corresponding Python logical operators.

Note that the equivalent Julia operators are overloaded to call these when all arguments are Py (or Number). Hence the following are equivalent: Py(1) < Py(2), Py(1) < 2, pylt(1, 2), pylt(Py(1), Py(2)), etc.

Note that the binary operators by default return Py (not Bool) since comparisons in Python do not necessarily return bool.

PythonCall.pytruthFunction
pytruth(x)

The truthyness of x. Equivalent to bool(x) in Python, converted to a Bool.

PythonCall.pynotFunction
pynot(x)

The falsyness of x. Equivalent to not x in Python, converted to a Bool.

PythonCall.pyeqFunction
pyeq(x, y)
pyeq(Bool, x, y)

Equivalent to x == y in Python. The second form converts to Bool.

PythonCall.pyneFunction
pyne(x, y)
pyne(Bool, x, y)

Equivalent to x != y in Python. The second form converts to Bool.

PythonCall.pyleFunction
pyle(x, y)
pyle(Bool, x, y)

Equivalent to x <= y in Python. The second form converts to Bool.

PythonCall.pyltFunction
pylt(x, y)
pylt(Bool, x, y)

Equivalent to x < y in Python. The second form converts to Bool.

PythonCall.pygeFunction
pyge(x, y)
pyge(Bool, x, y)

Equivalent to x >= y in Python. The second form converts to Bool.

PythonCall.pygtFunction
pygt(x, y)
pygt(Bool, x, y)

Equivalent to x > y in Python. The second form converts to Bool.

Managing Python dependencies

PythonCall manages its Python dependencies using Conda. A Conda environment is automatically created in your active Julia environment when PythonCall is loaded, is initialised with at least python and pip, and is activated.

If your project requires more Python dependencies, use the mechanisms below to ensure they are automatically installed.

PythonCallDeps.toml

If you put a file called PythonCallDeps.toml in a project/package/environment which depends on PythonCall, then the dependencies therein will be automatically installed into the Conda environment.

Here is an example (all parts are optional):

[conda]
packages = ["python>=3.6", "scikit-learn"]
channels = ["conda-forge"]

[pip]
packages = ["numpy>=1.21"]
# indexes = [...]

[script]
# expr = "some_julia_expression()"
# file = "/path/to/julia/script.jl"

When PythonCall starts, it will ensure the Conda environment has the given Conda and pip packages installed, and will run the script if specified.

The Deps submodule

Instead of manually editing PythonCallDeps.toml, you can use the submodule PythonCall.Deps to manage the Python dependencies of the current Julia project.

PythonCall.Deps.addFunction
add(...)

Add Python dependencies to the current Julia project.

Keyword arguments (all optional):

  • conda_channels: An iterable of conda channels to use.
  • conda_packages: An iterable of conda packages to install.
  • pip_indexes: An iterable of pip indexes to use.
  • pip_packages: An iterable of pip packages to install.
  • script_expr: An expression to evaluate in the Deps module.
  • script_file: The path to a Julia file to evaluate in the Deps module.
  • resolve=true: When true, immediately resolve the dependencies. Otherwise, the dependencies are not resolved until you call resolve or load PythonCall in a new Julia session.
  • create=true: When true, creates the environment from scratch when resolving.

The conda and pip packages can include version specifiers, such as python>=3.6.

PythonCall.Deps.rmFunction
rm(...)

Remove Python dependencies from the current Julia project.

Keyword arguments (all optional):

  • conda_channels: An iterable of conda channels to remove.
  • conda_packages: An iterable of conda packages to remove.
  • pip_indexes: An iterable of pip indexes to remove.
  • pip_packages: An iterable of pip packages to remove.
  • script_expr=false: When true, remove the script expression.
  • script_file=false: When true, remove the script file.
  • resolve=true: When true, immediately resolve the dependencies. Otherwise, the dependencies are not resolved until you call resolve or load PythonCall in a new Julia session.
  • create=true: When true, creates the environment from scratch when resolving.
PythonCall.Deps.resolveFunction
resolve(; create=true, force=false)

Resolve all Python dependencies.

If create=true then a new Conda environment is created and activated. Otherwise, the existing one is updated.

By default, if no dependencies have actually changed, then resolving them is skipped. Specify force=true to skip this check and force resolving dependencies.