PyJulia

repository·master·Indexed 21 days ago

https://github.com/juliapy/pyjulia

A Python 3 interface to the Julia programming language (v1.0+) that allows developers to call Julia functions and modules directly from Python. It provides the julia.api.Julia class for session management, julia.api.LibJulia for low-level access, and a pytest plugin for Julia-specific testing. Note: Ongoing development has transitioned to PythonCall.jl/juliacall, which is recommended for new projects.

Tokens
11.1K
Snippets
44
Records
67
Agent score
75%

What's inside pyjulia

  1. Overview of PyJulia

    master
    PyJulia provides a Python 3 interface to the Julia language (v1.0+). It allows developers to bridge Python and Julia, enabling the use of Julia's computational capabilities within Python environments. PyJulia is compatible with Python 3.5 and newer.
  2. Use a custom Julia system image to avoid precompilation issues

    master
    Instead of disabling the compilation cache (which is slow), you can create a custom Julia system image. This avoids precompilation cache issues and makes PyJulia initialization nearly instant. Refer to the sysimage documentation for specific instructions on how to create and use one.
  3. Understanding GIL and Parallelism limitations

    master
    PyJulia does not release the Global Interpreter Lock (GIL) while calling Julia functions. This is because PyCall requires the GIL to be acquired at all times. As a result, Python code and Julia code cannot run in parallel; they will execute sequentially.
  4. Use PyJulia in Python virtual environments

    master

    PyJulia is compatible with virtual environments created by virtualenv, venv, and pipenv.

    Requirement: The Python executable used in the virtual environment must be linked to the same libpython used by PyCall. If there is a mismatch, PyJulia will print an error message detailing the detected paths to libpython during initialization.

    Warning: Python environments created by conda are not supported.

  5. Handling Unicode identifier mismatches

    master
    PyJulia cannot access Julia methods or variables that use non-ASCII Unicode identifiers if they are not compatible with Python's identifier rules. Even in Python 3, where Unicode is supported, Python's aggressive normalization can cause mismatches. For example, ϵ (GREEK LUNATE EPSILON SYMBOL) and ε (GREEK SMALL LETTER EPSILON) are treated as identical in Python 3 but are distinct in Julia. Avoid using highly specialized Unicode characters in Julia code if you need to access them via PyJulia.
  6. How PyJulia manages memory and object conversion

    master

    PyJulia operates by loading the libjulia library and executing statements directly within it.

    To facilitate communication between Python and Julia, PyJulia utilizes the Julia PyCall package for variable conversion. Memory management is handled through a coordinated reference counting mechanism:

    1. Python Side: Python maintains reference counts for Python references to Julia objects.
    2. Julia Side: These objects are retained in the PyCall.pycall_gc mapping on the Julia side.
    3. Cleanup: When a Python reference count drops to zero, the entry is removed from the PyCall.pycall_gc mapping, allowing the underlying Julia object to be garbage collected.
  7. Use the Low-level interface for custom Julia runtimes

    master

    If your Julia executable is not in your PATH or you need to use a specific version (e.g., custom_julia), you must use the low-level interface.

    Crucial: You must initialize the Julia object with your custom runtime before importing any other Julia modules (like julia.Base or julia.Main).

    from julia import Julia
    # Initialize before importing other julia modules
    jl = Julia(runtime="custom_julia")
    
    from julia import Base
  8. Use the `python-jl` command for basic use-cases

    master

    PyJulia bundles a python-jl command that launches the Python interpreter inside Julia. This is an easy workaround for basic scripts or interactive sessions.

    Requirement: PyJulia must be installed in the Python environment that PyCall is configured to use. You can verify this in the Julia REPL by running:

    using PyCall
    pyimport("julia")
    # Should return a PyObject for the 'julia' module
    $ python-jl your_script.py
    $ python-jl -c 'from julia.Base import banner; banner()'
    $ python-jl -m IPython
  9. Use IPython/Jupyter %julia magic

    master

    In IPython or Jupyter environments, you can execute Julia code directly using the %julia magic command.

    Accessing Python variables in Julia

    • Use $var to access a single Python variable.
    • Use py"..." for more complex Python expressions.

    Escaping Python calls

    Inside strings, quote blocks, or macro arguments, $var and py"..." behave like standard Julia syntax. To force a Python call in these contexts, escape the symbol one extra time (e.g., \$var or \py"...").

    Type Conversion

    Results are automatically converted between equivalent Python and Julia types. To prevent this conversion and keep the result as a PyObject, append o to the Python string (e.g., py"1"o).

    # Load the extension
    %load_ext julia.magic
    
    # Execute Julia code
    %julia [1 2; 3 4] .+ 1 
    
    # Access Python variables
    arr = [1, 2, 3]
    %julia $arr .+ 1
    %julia sum(py"[x**2 for x in arr]")
    
    # Escaping Python calls in strings
    foo = "Python"
    %julia ("this is $foo", "this is $($foo)") # Returns 'this is Python'
    %julia ("this is \$foo", "this is \$(\$(foo))") # Returns 'this is Python' (escaped)
    
    # Disabling automatic type conversion
    %julia typeof(py"1"), typeof(py"1"o)
  10. Quick start with PyJulia

    master

    After installing the package, you must run julia.install() to set up the necessary Julia components like PyCall.jl. Once installed, you can import Julia modules directly into Python. For example, you can access the Base module from Julia and call functions like sind.

    import julia
    
    # Install PyCall.jl and other dependencies
    julia.install()
    
    # Import a Julia module
    from julia import Base
    
    # Call a Julia function
    result = Base.sind(90)
    print(result)  # Output: 1.0