Julia/Python bridge with IPython support.
PyJulia is tested against Python versions 2.7, 3.5, 3.6, and 3.7.
Note: If you are using Python installed with Ubuntu or
PyJulia may not work with Julia ≥ 0.7. For workarounds, see
Troubleshooting below. Same caution applies to
any Debian-based and possibly other GNU/Linux distributions.
You will need to install PyCall in your existing Julia installation
julia> using Pkg # for julia ≥ 0.7 julia> Pkg.add("PyCall")
Your python installation must be able to call command line program
julia. If your installer does not add the Julia binary directory to
PATH, you will have to add it. An alias will not work.
Then finally you have to install PyJulia.
Note: If you are not familiar with
pip and have some troubles
with the following installation steps, we recommend going through the
Tutorials in Python Packaging User Guide.
To get released versions you can use:
$ python3 -m pip install --user julia $ python2 -m pip install --user julia # If you need Python 2
--user should be omitted if you are using virtual environment
If you are interested in using the development version, you can install PyJulia directly from GitHub:
$ python3 -m pip install --user 'https://github.com/JuliaPy/pyjulia/archive/master.zip#egg=julia'
You may clone it directly to (say) your home directory.
$ git clone https://github.com/JuliaPy/pyjulia
then inside the
pyjulia directory you need to run the python setup file
$ cd pyjulia $ python3 -m pip install --user . $ python3 -m pip install --user -e . # If you want "development install"
-e flag makes a development install, meaning that any change to PyJulia
source tree will take effect at next python interpreter restart without having
to reissue an install command.
See Testing below for how to run tests.
PyJulia provides a high-level interface which assumes a "normal" setup
julia program is in your
PATH) and a low-level interface
which can be used in a customized setup.
To call a Julia function in a Julia module, import the Julia module
>>> from julia import Base
and then call Julia functions in
Base from python, e.g.,
Other variants of Python import syntax also work:
>>> import julia.Base >>> from julia.Base import Enums # import a submodule >>> from julia.Base import sin # import a function from a module
The global namespace of Julia's interpreter can be accessed via a
>>> from julia import Main
You can set names in this module to send Python values to Julia:
>>> Main.xs = [1, 2, 3]
which allows it to be accessed directly from Julia code, e.g., it can be evaluated at Julia side using Julia syntax:
If you need a custom setup for PyJulia, it must be done before
importing any Julia modules. For example, to use the Julia
>>> from julia import Julia >>> jl = julia.Julia(runtime="custom_julia")
You can then use, e.g.,
>>> from julia import Base
In IPython (and therefore in Jupyter), you can directly execute Julia
In : %load_ext julia.magic Initializing Julia interpreter. This may take some time... In : %%julia ...: Base.banner(IOContext(stdout, :color=>true)) _ _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.0.1 (2018-09-29) _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release |__/ |
PyJulia can be used in Python virtual environments created by
venv, and any tools wrapping them such as
provided that Python executable used in such environments are linked
to identical libpython used by PyCall. If this is not the case,
initializing PyJulia (e.g.,
import julia.Main) prints an informative
error message with detected paths to libpython. See
PyCall documentation for how
to configure Python executable.
Note that Python environment created by
conda is not supported.
Your Python interpreter is statically linked to libpython
If you use Python installed with Debian-based Linux distribution such
as Ubuntu or install Python by
conda, you might have noticed that
PyJulia cannot be initialized properly with Julia ≥ 0.7. This is
because those Python executables are statically linked to libpython.
(See Limitations below for why that's a problem.)
If you are unsure if your
python has this problem, you can quickly
check it by:
$ ldd /usr/bin/python linux-vdso.so.1 (0x00007ffd73f7c000) libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f10ef84e000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f10ef68a000) libpython3.7m.so.1.0 => /usr/lib/libpython3.7m.so.1.0 (0x00007f10ef116000) /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f10efaa4000) libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f10ef111000) libutil.so.1 => /usr/lib/libutil.so.1 (0x00007f10ef10c000) libm.so.6 => /usr/lib/libm.so.6 (0x00007f10eef87000)
in Linux where
/usr/bin/python should be replaced with the path to
python command (use
which python to find it out). In macOS,
otool -L instead of
ldd. If it does not print the path to
/usr/lib/libpython3.7m.so.1.0 in above example, you
need to use one of the workaround below.
The easiest workaround is to use the
python-jl command bundled in
PyJulia. This can be used instead of normal
python command for
basic use-cases such as:
$ python-jl your_script.py $ python-jl -c 'from julia.Base import banner; banner()' $ python-jl -m IPython
python-jl --help for more information.
python-jl works by launching Python interpreter inside
Julia. Importantly, it means that PyJulia has to be installed in the
Python environment with which PyCall is configured. That is to say,
following commands must work for
python-jl to be usable:
julia> using PyCall julia> pyimport("julia") PyObject <module 'julia' from '/.../julia/__init__.py'>
In fact, you can simply use PyJulia inside the Julia REPL, if you are comfortable with working in it:
julia> using PyCall julia> py""" from julia import Julia Julia(init_julia=False) from your_module_using_pyjulia import function function() """
$ PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.6.6 Downloading Python-3.6.6.tar.xz... -> https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz Installing Python-3.6.6... Installed Python-3.6.6 to /home/USER/.pyenv/versions/3.6.6 $ ldd ~/.pyenv/versions/3.6.6/bin/python3.6 | grep libpython libpython3.6m.so.1.0 => /home/USER/.pyenv/versions/3.6.6/lib/libpython3.6m.so.1.0 (0x00007fca44c8b000)
For more discussion, see: https://github.com/JuliaPy/pyjulia/issues/185
Segmentation fault in IPython
You may experience segmentation fault when using PyJulia in old
versions of IPython. You can avoid this issue by updating IPython to
7.0 or above. Alternatively, you can use IPython via Jupyter (e.g.,
jupyter console) to workaround the problem.
How it works
PyJulia loads the
libjulia library and executes the statements therein.
To convert the variables, the
PyCall package is used. Python references
to Julia objects are reference counted by Python, and retained in the
PyCall.pycall_gc mapping on the Julia side (the mapping is removed
when reference count drops to zero, so that the Julia object may be freed).
Mismatch in valid set of identifiers
Not all valid Julia identifiers are valid Python identifiers. Unicode
identifiers are invalid in Python 2.7 and so PyJulia cannot call or
access Julia methods/variables with names that are not ASCII only.
Although Python 3 allows Unicode identifiers, they are more
aggressively normalized than Julia. For example,
ϵ (GREEK LUNATE
EPSILON SYMBOL) and
ε (GREEK SMALL LETTER EPSILON) are identical in
Python 3 but different in Julia. Additionally, it is a common idiom
in Julia to append a
! character to methods which mutate their
arguments. These method names are invalid Python identifers.
PyJulia renames these methods by subsituting
example, the Julia method
sum! can be called in PyJulia using
Pre-compilation mechanism in Julia 1.0
There was a major overhaul in the module loading system between Julia 0.6 and 1.0. As a result, the "hack" supporting the PyJulia to load PyCall stopped working. For the implementation detail of the hack, see: https://github.com/JuliaPy/pyjulia/tree/master/julia/fake-julia
For the update on this problem, see: https://github.com/JuliaLang/julia/issues/28518
Ctrl-C does not work / terminates the whole Python process
Currently, initializing PyJulia (e.g., by
from julia import Main)
KeyboardInterrupt handling in the Python process. If you
are using normal
python interpreter, it means that canceling the
input by Ctrl-C does not work and repeatedly providing
Ctrl-C terminates the whole Python process with the error
WARNING: Force throwing a SIGINT. Using IPython 7.0 or
above is recommended to avoid such accidental shutdown.
It also means that there is no safe way to cancel long-running computations or I/O at the moment. Sending SIGINT with Ctrl-C will terminate the whole Python process.
For the update on this problem, see: https://github.com/JuliaPy/pyjulia/issues/211
No threading support
PyJulia cannot be used in different threads since libjulia is not
thread safe. However, you can
use multiple threads within Julia.
For example, start IPython by
JULIA_NUM_THREADS=4 ipython and then
In : %load_ext julia.magic Initializing Julia interpreter. This may take some time... In : %%julia ...: a = zeros(10) ...: Threads.@threads for i = 1:10 ...: a[i] = Threads.threadid() ...: end ...: a Out: array([1., 1., 1., 2., 2., 2., 3., 3., 4., 4.])
PyJulia does not release GIL
PyJulia does not release the Global Interpreter Lock (GIL) while calling Julia functions since PyCall expects the GIL to be acquired always. It means that Python code and Julia code cannot run in parallel.
PyJulia can be tested by simply running
The full syntax for invoking
[PYJULIA_TEST_REBUILD=yes] [JULIA_EXE=<julia>] tox [options] [-- pytest options]
PYJULIA_TEST_REBUILD: Be careful using this environment variable! When it is set to
PyCall.jlinstallation will be rebuilt using the Python interpreter used for testing. The test suite tries to build back to the original configuration but the precompilation would be in the stale state after the test. Note also that it does not work if you unconditionally set
PYTHONenvironment variable in your Julia startup file.
juliaexecutable to be used for testing.
Positional arguments after
--are passed to
$ PYJULIA_TEST_REBUILD=yes JULIA_EXE=~/julia/julia tox -e py37 -- -s
means to execute tests with
- PyJulia in shared-cache mode
- Python 3.7
pytest's capturing mode turned off
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
|Filename, size & hash SHA256 hash help||File type||Python version||Upload date|
|julia-0.2.0-py2.py3-none-any.whl (238.5 kB) Copy SHA256 hash SHA256||Wheel||py2.py3|
|julia-0.2.0.tar.gz (244.8 kB) Copy SHA256 hash SHA256||Source||None|