From 278ea81a49ec568e1630f55e2fac09fb6f92f333 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Fri, 2 Aug 2024 21:13:09 +0000 Subject: [PATCH] build based on bcd2bbb --- dev/.documenter-siteinfo.json | 2 +- dev/compat/index.html | 4 ++-- dev/conversion-to-julia/index.html | 2 +- dev/conversion-to-python/index.html | 2 +- dev/faq/index.html | 4 ++-- dev/index.html | 2 +- dev/juliacall-reference/index.html | 2 +- dev/juliacall/index.html | 2 +- dev/objects.inv | Bin 3307 -> 3316 bytes dev/pycall/index.html | 2 +- dev/pythoncall-reference/index.html | 32 ++++++++++++++-------------- dev/pythoncall/index.html | 2 +- dev/releasenotes/index.html | 2 +- dev/search_index.js | 2 +- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 71e5d7cd..1c49e91f 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.4","generation_timestamp":"2024-07-24T17:22:48","documenter_version":"1.5.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.4","generation_timestamp":"2024-08-02T21:13:03","documenter_version":"1.5.0"}} \ No newline at end of file diff --git a/dev/compat/index.html b/dev/compat/index.html index 89cead6c..78161169 100644 --- a/dev/compat/index.html +++ b/dev/compat/index.html @@ -1,5 +1,5 @@ -Compatibility Tools · PythonCall & JuliaCall

Compatibility Tools

Some packages require a little extra help to work nicely with PythonCall.

Some of these are "fixes" that are silently applied for you, and some are just extra functions to bridge a gap. We aim to keep these as minimal as possible.

Python standard library

Whenever a Python exception is displayed by Julia, sys.last_traceback and friends are set. This allows the post-mortem debugger pdb.pm() to work. Disable by setting PythonCall.CONFIG.auto_sys_last_traceback = false.

Julia standard library

Python objects can be serialised with the Serialization stdlib. This uses pickle library under the hood. You can opt into using dill instead by setting the environment variable JULIA_PYTHONCALL_PICKLE="dill".

Tabular data / Pandas

The abstract type PyTable is for wrapper types around Python tables, providing the Tables.jl interface. PyTable(x) is shorthand for pyconvert(PyTable, x).

The subtype PyPandasDataFrame wraps a pandas.DataFrame.

For example, if x is a pandas.DataFrame then PyTable(x) is a PyPandasDataFrame and DataFrame(PyTable(x)) is a DataFrame.

In the other direction, the following functions can be used to convert any Tables.jl-compatible table to a Python table.

PythonCall.Compat.pytableFunction
pytable(src, format=:pandas; ...)

Construct a Python table from the Tables.jl-compatible table src.

The format controls the type of the resulting table, and is one of:

  • :pandas: A pandas.DataFrame. Keyword arguments are passed to the DataFrame constructor.
  • :columns: A dict mapping column names to columns.
  • :rows: A list of rows, which are namedtuples.
  • :rowdicts: A list of rows, which are dicts.
source

MatPlotLib / PyPlot / Seaborn

MatPlotLib figures can be shown with Julia's display mechanism, like display(fig) or display(mime, fig).

This means that if you return a figure from a Jupyter or Pluto notebook cell, it will be shown. You can call display(plt.gcf()) to display the current figure.

We also provide a simple MatPlotLib backend: mpl.use("module://juliacall.matplotlib"). Now you can call plt.show() to display the figure with Julia's display mechanism. You can specify the format like plt.show(format="png").

Python GUIs (including MatPlotLib)

Event loops

If for example you wish to use PyPlot in interactive mode (matplotlib.pyplot.ion()) then activating the correct event loop will allow it to work.

PythonCall.Compat.event_loop_onFunction
event_loop_on(g::Symbol; interval=0.04, fix=false)

Activate an event loop for the GUI framework g, so that the framework can run in the background of a Julia session.

The event loop runs every interval seconds. If fix is true and g is a Qt framework, then fix_qt_plugin_path is called.

Supported values of g (and the Python module they relate to) are: :pyqt4 (PyQt4), :pyqt5 (PyQt5), :pyside (PySide), :pyside2 (PySide2), :gtk (gtk), :gtk3 (gi), :wx (wx), :tkinter (tkinter).

source

Qt path fix

PythonCall.Compat.fix_qt_plugin_pathFunction
fix_qt_plugin_path()

Try to set the QT_PLUGIN_PATH environment variable in Python, if not already set.

This fixes the problem that Qt does not know where to find its qt.conf file, because it always looks relative to sys.executable, which can be the Julia executable not the Python one when using this package.

If CONFIG.auto_fix_qt_plugin_path is true, then this is run automatically before PyQt4, PyQt5, PySide or PySide2 are imported.

source

IPython

The juliacall IPython extension adds these features to your IPython session:

  • The line magic %julia code executes the given Julia code in-line.
  • The cell magic %%julia executes a cell of Julia code.
  • Julia's stdout and stderr are redirected to IPython.
  • Calling display(x) from Julia will display x in IPython.

The extension is experimental and unstable - the API can change at any time.

You can explicitly enable the extension with %load_ext juliacall, but it will automatically be loaded if juliacall is imported and IPython is detected. You can disable this behavior with an environment variable.

The %%julia cell magic can synchronise variables between Julia and Python by listing them on the first line:

In [1]: %load_ext juliacall
+Compatibility Tools · PythonCall & JuliaCall

Compatibility Tools

Some packages require a little extra help to work nicely with PythonCall.

Some of these are "fixes" that are silently applied for you, and some are just extra functions to bridge a gap. We aim to keep these as minimal as possible.

Python standard library

Whenever a Python exception is displayed by Julia, sys.last_traceback and friends are set. This allows the post-mortem debugger pdb.pm() to work. Disable by setting PythonCall.CONFIG.auto_sys_last_traceback = false.

Julia standard library

Python objects can be serialised with the Serialization stdlib. This uses pickle library under the hood. You can opt into using dill instead by setting the environment variable JULIA_PYTHONCALL_PICKLE="dill".

Tabular data / Pandas

The abstract type PyTable is for wrapper types around Python tables, providing the Tables.jl interface. PyTable(x) is shorthand for pyconvert(PyTable, x).

The subtype PyPandasDataFrame wraps a pandas.DataFrame.

For example, if x is a pandas.DataFrame then PyTable(x) is a PyPandasDataFrame and DataFrame(PyTable(x)) is a DataFrame.

In the other direction, the following functions can be used to convert any Tables.jl-compatible table to a Python table.

PythonCall.Compat.pytableFunction
pytable(src, format=:pandas; ...)

Construct a Python table from the Tables.jl-compatible table src.

The format controls the type of the resulting table, and is one of:

  • :pandas: A pandas.DataFrame. Keyword arguments are passed to the DataFrame constructor.
  • :columns: A dict mapping column names to columns.
  • :rows: A list of rows, which are namedtuples.
  • :rowdicts: A list of rows, which are dicts.
source

MatPlotLib / PyPlot / Seaborn

MatPlotLib figures can be shown with Julia's display mechanism, like display(fig) or display(mime, fig).

This means that if you return a figure from a Jupyter or Pluto notebook cell, it will be shown. You can call display(plt.gcf()) to display the current figure.

We also provide a simple MatPlotLib backend: mpl.use("module://juliacall.matplotlib"). Now you can call plt.show() to display the figure with Julia's display mechanism. You can specify the format like plt.show(format="png").

Python GUIs (including MatPlotLib)

Event loops

If for example you wish to use PyPlot in interactive mode (matplotlib.pyplot.ion()) then activating the correct event loop will allow it to work.

PythonCall.Compat.event_loop_onFunction
event_loop_on(g::Symbol; interval=0.04, fix=false)

Activate an event loop for the GUI framework g, so that the framework can run in the background of a Julia session.

The event loop runs every interval seconds. If fix is true and g is a Qt framework, then fix_qt_plugin_path is called.

Supported values of g (and the Python module they relate to) are: :pyqt4 (PyQt4), :pyqt5 (PyQt5), :pyside (PySide), :pyside2 (PySide2), :gtk (gtk), :gtk3 (gi), :wx (wx), :tkinter (tkinter).

source

Qt path fix

PythonCall.Compat.fix_qt_plugin_pathFunction
fix_qt_plugin_path()

Try to set the QT_PLUGIN_PATH environment variable in Python, if not already set.

This fixes the problem that Qt does not know where to find its qt.conf file, because it always looks relative to sys.executable, which can be the Julia executable not the Python one when using this package.

If CONFIG.auto_fix_qt_plugin_path is true, then this is run automatically before PyQt4, PyQt5, PySide or PySide2 are imported.

source

IPython

The juliacall IPython extension adds these features to your IPython session:

  • The line magic %julia code executes the given Julia code in-line.
  • The cell magic %%julia executes a cell of Julia code.
  • Julia's stdout and stderr are redirected to IPython.
  • Calling display(x) from Julia will display x in IPython.

The extension is experimental and unstable - the API can change at any time.

You can explicitly enable the extension with %load_ext juliacall, but it will automatically be loaded if juliacall is imported and IPython is detected. You can disable this behavior with an environment variable.

The %%julia cell magic can synchronise variables between Julia and Python by listing them on the first line:

In [1]: %load_ext juliacall
 
 In [2]: x = 2
 
@@ -11,4 +11,4 @@
    ...:
 
 In [5]: z
-Out[5]: '2^8 = 256'

Also see the IPython docs for more information on extensions.

Asynchronous Julia code (including Makie)

Asynchronous Julia code will not normally run while Python is executing, unless it is in a separate thread.

This can be fixed by calling jl.yield() periodically from Python code, allowing the Julia scheduler to run.

When working at the Python REPL, you may call juliacall.interactive() which will allow Julia async code to run while the prompt is showing. This will allow interactive plots such as Makie to work.

+Out[5]: '2^8 = 256'

Also see the IPython docs for more information on extensions.

Asynchronous Julia code (including Makie)

Asynchronous Julia code will not normally run while Python is executing, unless it is in a separate thread.

This can be fixed by calling jl.yield() periodically from Python code, allowing the Julia scheduler to run.

When working at the Python REPL, you may call juliacall.interactive() which will allow Julia async code to run while the prompt is showing. This will allow interactive plots such as Makie to work.

diff --git a/dev/conversion-to-julia/index.html b/dev/conversion-to-julia/index.html index 4f7a2714..c1b4465d 100644 --- a/dev/conversion-to-julia/index.html +++ b/dev/conversion-to-julia/index.html @@ -1,2 +1,2 @@ -Python to Julia · PythonCall & JuliaCall

Conversion to Julia

Conversion Rules

The following table specifies the conversion rules used whenever converting a Python object to a Julia object. 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.

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

From Python, the arguments to a Julia function will be converted according to these rules with T=Any.

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
BaseExceptionPyException
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, Missing/Nothing (if NaN)
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.bool_/numpy.intXX/numpy.uintXX/numpy.floatXXBool, Integer, Rational, Real, Number
Objects satisfying the buffer or array interfaceArray, AbstractArray
Low priority (fallback to Py).
AnythingPy
Bottom priority (must be explicitly specified by excluding Py).
Objects satisfying the buffer interfacePyBuffer
AnythingPyRef

See here for an explanation of the Py* wrapper types (PyList, PyIO, etc).

Custom rules

To add a custom conversion rule, you must define a function to do the conversion and call pyconvert_add_rule to register it.

You must not do this while precompiling, so these calls will normally be in the __init__ function of your module.

PythonCall.Convert.pyconvert_add_ruleFunction
pyconvert_add_rule(tname::String, T::Type, func::Function, priority::PyConvertPriority=PYCONVERT_PRIORITY_NORMAL)

Add a new conversion rule for pyconvert.

Arguments

  • tname is a string of the form "__module__:__qualname__" identifying a Python type t, such as "builtins:dict" or "sympy.core.symbol:Symbol". This rule only applies to Python objects of this type.
  • T is a Julia type, such that this rule only applies when the target type intersects with T.
  • func is the function implementing the rule.
  • priority determines whether to prioritise this rule above others.

When pyconvert(R, x) is called, all rules such that typeintersect(T, R) != Union{} and pyisinstance(x, t) are considered. These rules are sorted first by priority, then by the specificity of t (e.g. bool is more specific than int is more specific than object) then by the order they were added. The rules are tried in turn until one succeeds.

Implementing func

func is called as func(S, x::Py) for some S <: T.

It must return one of:

  • pyconvert_return(ans) where ans is the result of the conversion (and must be an S).
  • pyconvert_unconverted() if the conversion was not possible (e.g. converting a list to Vector{Int} might fail if some of the list items are not integers).

The target type S is never a union or the empty type, i.e. it is always a data type or union-all.

Priority

Most rules should have priority PYCONVERT_PRIORITY_NORMAL (the default) which is for any reasonable conversion rule.

Use priority PYCONVERT_PRIORITY_CANONICAL for canonical conversion rules. Immutable objects may be canonically converted to their corresponding Julia type, such as int to Integer. Mutable objects must be converted to a wrapper type, such that the original Python object can be retrieved. For example a list is canonically converted to PyList and not to a Vector. There should not be more than one canonical conversion rule for a given Python type.

Other priorities are reserved for internal use.

source
+Python to Julia · PythonCall & JuliaCall

Conversion to Julia

Conversion Rules

The following table specifies the conversion rules used whenever converting a Python object to a Julia object. 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.

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

From Python, the arguments to a Julia function will be converted according to these rules with T=Any.

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
BaseExceptionPyException
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, Missing/Nothing (if NaN)
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.bool_/numpy.intXX/numpy.uintXX/numpy.floatXXBool, Integer, Rational, Real, Number
Objects satisfying the buffer or array interfaceArray, AbstractArray
Low priority (fallback to Py).
AnythingPy
Bottom priority (must be explicitly specified by excluding Py).
Objects satisfying the buffer interfacePyBuffer
AnythingPyRef

See here for an explanation of the Py* wrapper types (PyList, PyIO, etc).

Custom rules

To add a custom conversion rule, you must define a function to do the conversion and call pyconvert_add_rule to register it.

You must not do this while precompiling, so these calls will normally be in the __init__ function of your module.

PythonCall.Convert.pyconvert_add_ruleFunction
pyconvert_add_rule(tname::String, T::Type, func::Function, priority::PyConvertPriority=PYCONVERT_PRIORITY_NORMAL)

Add a new conversion rule for pyconvert.

Arguments

  • tname is a string of the form "__module__:__qualname__" identifying a Python type t, such as "builtins:dict" or "sympy.core.symbol:Symbol". This rule only applies to Python objects of this type.
  • T is a Julia type, such that this rule only applies when the target type intersects with T.
  • func is the function implementing the rule.
  • priority determines whether to prioritise this rule above others.

When pyconvert(R, x) is called, all rules such that typeintersect(T, R) != Union{} and pyisinstance(x, t) are considered. These rules are sorted first by priority, then by the specificity of t (e.g. bool is more specific than int is more specific than object) then by the order they were added. The rules are tried in turn until one succeeds.

Implementing func

func is called as func(S, x::Py) for some S <: T.

It must return one of:

  • pyconvert_return(ans) where ans is the result of the conversion (and must be an S).
  • pyconvert_unconverted() if the conversion was not possible (e.g. converting a list to Vector{Int} might fail if some of the list items are not integers).

The target type S is never a union or the empty type, i.e. it is always a data type or union-all.

Priority

Most rules should have priority PYCONVERT_PRIORITY_NORMAL (the default) which is for any reasonable conversion rule.

Use priority PYCONVERT_PRIORITY_CANONICAL for canonical conversion rules. Immutable objects may be canonically converted to their corresponding Julia type, such as int to Integer. Mutable objects must be converted to a wrapper type, such that the original Python object can be retrieved. For example a list is canonically converted to PyList and not to a Vector. There should not be more than one canonical conversion rule for a given Python type.

Other priorities are reserved for internal use.

source
diff --git a/dev/conversion-to-python/index.html b/dev/conversion-to-python/index.html index bd7c84a3..51407fef 100644 --- a/dev/conversion-to-python/index.html +++ b/dev/conversion-to-python/index.html @@ -1,2 +1,2 @@ -Julia to Python · PythonCall & JuliaCall

Conversion to Python

Conversion Rules

The following table specifies the conversion rules used whenever converting a Julia object to a Python object.

From Julia, this occurs explicitly with Py(x) or implicitly when passing Julia objects as the argument to a Python function. To avoid this automatic conversion, the user can convert objects explicitly, such as by calling pylist or pydict.

From Python, this occurs when converting the return value of a Julia function.

FromTo
Any Python object type (Py, 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

See here for an explanation of the juliacall.*Value wrapper types.

Custom rules

You may define a new conversion rule for your new type T by overloading Py(::T).

If T is a wrapper type (such as PyList) where Py(x) simply returns the stored Python object, then also define ispy(::T) = true.

PythonCall.Core.ispyFunction
ispy(x)

True if x is a Python object.

This includes Py and Python wrapper types such as PyList.

source

Alternatively, if you define a wrapper type (a subtype of juliacall.AnyValue) then you may instead define pyjltype(::T) to be that type.

PythonCall.JlWrap.pyjltypeFunction
pyjltype(x)

The subtype of juliacall.AnyValue which the Julia object x is wrapped as by pyjl(x).

Overload pyjltype(::T) to define a custom conversion for your type T.

source
+Julia to Python · PythonCall & JuliaCall

Conversion to Python

Conversion Rules

The following table specifies the conversion rules used whenever converting a Julia object to a Python object.

From Julia, this occurs explicitly with Py(x) or implicitly when passing Julia objects as the argument to a Python function. To avoid this automatic conversion, the user can convert objects explicitly, such as by calling pylist or pydict.

From Python, this occurs when converting the return value of a Julia function.

FromTo
Any Python object type (Py, 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

See here for an explanation of the juliacall.*Value wrapper types.

Custom rules

You may define a new conversion rule for your new type T by overloading Py(::T).

If T is a wrapper type (such as PyList) where Py(x) simply returns the stored Python object, then also define ispy(::T) = true.

PythonCall.Core.ispyFunction
ispy(x)

True if x is a Python object.

This includes Py and Python wrapper types such as PyList.

source

Alternatively, if you define a wrapper type (a subtype of juliacall.AnyValue) then you may instead define pyjltype(::T) to be that type.

PythonCall.JlWrap.pyjltypeFunction
pyjltype(x)

The subtype of juliacall.AnyValue which the Julia object x is wrapped as by pyjl(x).

Overload pyjltype(::T) to define a custom conversion for your type T.

source
diff --git a/dev/faq/index.html b/dev/faq/index.html index 0cb118b9..8cb5a3bc 100644 --- a/dev/faq/index.html +++ b/dev/faq/index.html @@ -1,5 +1,5 @@ -FAQ & Troubleshooting · PythonCall & JuliaCall

FAQ & Troubleshooting

Is PythonCall/JuliaCall thread safe?

No.

Some rules if you are writing multithreaded code:

  • Only call Python functions from the first thread.
  • You probably also need to call PythonCall.GC.disable() on the main thread before any threaded block of code. Remember to call PythonCall.GC.enable() again afterwards. (This is because Julia finalizers can be called from any thread.)
  • Julia intentionally causes segmentation faults as part of the GC safepoint mechanism. If unhandled, these segfaults will result in termination of the process. To enable signal handling, set PYTHON_JULIACALL_HANDLE_SIGNALS=yes before any calls to import juliacall. This is equivalent to starting julia with julia --handle-signals=yes, the default behavior in Julia. See discussion here for more information.
  • You may still encounter problems.

Related issues: #201, #202

Issues when Numpy arrays are expected

When a Julia array is passed to Python, it is wrapped as a ArrayValue. This type satisfies the Numpy array interface and the buffer protocol, so can be used in most places where a numpy array is valid.

However, some Python packages have functions which assume the input is an actual Numpy array. You may see errors such as:

AttributeError: Julia: type Array has no field dtype

To fix this you can convert the array x to a Numpy array as follows

Py(x).to_numpy()

If the array is being mutated, you will need to pass the argument copy=false.

Related issues: #280

Heap corruption when using PyTorch

On some systems, you may see an error like the following when using torch and juliacall:

Python(65251,0x104cf8580) malloc: Heap corruption detected, free list is damaged at 0x600001c17280
+FAQ & Troubleshooting · PythonCall & JuliaCall

FAQ & Troubleshooting

Is PythonCall/JuliaCall thread safe?

No.

However it is safe to use PythonCall with Julia with multiple threads, provided you only call Python code from the first thread. (Before v0.9.22, tricks such as disabling the garbage collector were required.)

From Python, to use JuliaCall with multiple threads you probably need to set PYTHON_JULIACALL_HANDLE_SIGNALS=yes before importing JuliaCall. This is because Julia intentionally causes segmentation faults as part of the GC safepoint mechanism. If unhandled, these segfaults will result in termination of the process. This is equivalent to starting julia with julia --handle-signals=yes, the default behavior in Julia. See discussion here for more information.

Related issues: #201, #202, #529

Issues when Numpy arrays are expected

When a Julia array is passed to Python, it is wrapped as a ArrayValue. This type satisfies the Numpy array interface and the buffer protocol, so can be used in most places where a numpy array is valid.

However, some Python packages have functions which assume the input is an actual Numpy array. You may see errors such as:

AttributeError: Julia: type Array has no field dtype

To fix this you can convert the array x to a Numpy array as follows

Py(x).to_numpy()

If the array is being mutated, you will need to pass the argument copy=false.

Related issues: #280

Heap corruption when using PyTorch

On some systems, you may see an error like the following when using torch and juliacall:

Python(65251,0x104cf8580) malloc: Heap corruption detected, free list is damaged at 0x600001c17280
 *** Incorrect guard value: 1903002876
 Python(65251,0x104cf8580) malloc: *** set a breakpoint in malloc_error_break to debug
 [1]    65251 abort      ipython

A solution is to ensure that juliacall is imported before torch.

Related issues: #215

ccall requires the compiler error when importing some Python libraries

On some systems, you may see an error like the following when import e.g. matplotlib before juliacall:

ERROR: `ccall` requires the compilerTraceback (most recent call last):
@@ -11,4 +11,4 @@
     init()
   File "/home/dingraha/projects/pythoncall_import_error/venv/lib/python3.9/site-packages/juliacall/__init__.py", line 214, in init
     raise Exception('PythonCall.jl did not start properly')
-Exception: PythonCall.jl did not start properly

The likely problem is that the "other" Python library (matplotlib, whatever) is loading the system libstdc++.so, which isn't compatible with the libstdc++.so that Julia ships with. Linux distributions with older libstdc++ versions seem more likely to suffer from this issue. The solution is to either:

  • use a Linux distribution with a more recent libstdc++
  • import juliacall before the other Python library, so that Julia's libstdc++ is loaded
  • use a Python from a conda environment, which will have a newer libstdc++ that is compatible with Julia's

Related issues: #255

Can I use JuliaCall to run Julia inside applications with embedded Python?

Yes, it may be possible. A good example of that is having Julia running inside the Python that is running inside Blender, as presented in this Discourse post. From the point that one has JuliaCall running inside Python, if it has access to the terminal, one can even launch a Julia REPL there, and if needed connect with VSCode Julia extension to it. The full Python script to install, launch JuliaCall, and launch a Julia REPL in Blender is here.

+Exception: PythonCall.jl did not start properly

The likely problem is that the "other" Python library (matplotlib, whatever) is loading the system libstdc++.so, which isn't compatible with the libstdc++.so that Julia ships with. Linux distributions with older libstdc++ versions seem more likely to suffer from this issue. The solution is to either:

  • use a Linux distribution with a more recent libstdc++
  • import juliacall before the other Python library, so that Julia's libstdc++ is loaded
  • use a Python from a conda environment, which will have a newer libstdc++ that is compatible with Julia's

Related issues: #255

Can I use JuliaCall to run Julia inside applications with embedded Python?

Yes, it may be possible. A good example of that is having Julia running inside the Python that is running inside Blender, as presented in this Discourse post. From the point that one has JuliaCall running inside Python, if it has access to the terminal, one can even launch a Julia REPL there, and if needed connect with VSCode Julia extension to it. The full Python script to install, launch JuliaCall, and launch a Julia REPL in Blender is here.

diff --git a/dev/index.html b/dev/index.html index ee5ab5b6..caf7784d 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Home · PythonCall & JuliaCall

PythonCall & JuliaCall

Bringing Python® and Julia together in seamless harmony:

  • Call Python code from Julia and Julia code from Python via a symmetric interface.
  • Simple syntax, so the Python code looks like Python and the Julia code looks like Julia.
  • Intuitive and flexible conversions between Julia and Python: anything can be converted, you are in control.
  • Fast non-copying conversion of numeric arrays in either direction: modify Python arrays (e.g. bytes, array.array, numpy.ndarray) from Julia or Julia arrays from Python.
  • Helpful wrappers: interpret Python sequences, dictionaries, arrays, dataframes and IO streams as their Julia counterparts, and vice versa.
  • Beautiful stack-traces.
  • Works anywhere: tested on Windows, MacOS and Linux, 32- and 64-bit, Julia Julia 1.6.1 upwards and Python 3.8 upwards.
+Home · PythonCall & JuliaCall

PythonCall & JuliaCall

Bringing Python® and Julia together in seamless harmony:

  • Call Python code from Julia and Julia code from Python via a symmetric interface.
  • Simple syntax, so the Python code looks like Python and the Julia code looks like Julia.
  • Intuitive and flexible conversions between Julia and Python: anything can be converted, you are in control.
  • Fast non-copying conversion of numeric arrays in either direction: modify Python arrays (e.g. bytes, array.array, numpy.ndarray) from Julia or Julia arrays from Python.
  • Helpful wrappers: interpret Python sequences, dictionaries, arrays, dataframes and IO streams as their Julia counterparts, and vice versa.
  • Beautiful stack-traces.
  • Works anywhere: tested on Windows, MacOS and Linux, 32- and 64-bit, Julia Julia 1.6.1 upwards and Python 3.8 upwards.
diff --git a/dev/juliacall-reference/index.html b/dev/juliacall-reference/index.html index a5c9c1d7..a1f6e4d8 100644 --- a/dev/juliacall-reference/index.html +++ b/dev/juliacall-reference/index.html @@ -2,4 +2,4 @@ Reference · PythonCall & JuliaCall

JuliaCall API Reference

Constants

juliacall.MainConstant

The Julia Main module, as a ModuleValue.

In interactive scripts, you can use this as the main entry-point to JuliaCall:

from juliacall import Main as jl
 jl.println("Hello, world!")

In packages, use newmodule instead.

source

The modules Base, Core and PythonCall are also available.

Utilities

juliacall.convertFunction
convert(T, x)

Convert x to a Julia object of type T.

You can use this to pass an argument to a Julia function of a specific type.

source

Wrapper types

Apart from a few fundamental immutable types, all Julia values are by default converted into Python to some AnyValue object, which wraps the original value, but giving it a Pythonic interface.

Subclasses of AnyValue provide additional Python semantics. For example a Julia vector is converted to a VectorValue which satisfies the Python sequence interface and behaves very similar to a list.

There is also a RawValue object, which gives a stricter "Julia-only" interface, documented below. These types all inherit from ValueBase:

juliacall.AnyValueClass

Wraps any Julia object, giving it some basic Python semantics. Subtypes provide extra semantics.

Supports repr(x), str(x), attributes (x.attr), calling (x(a,b)), iteration, comparisons, len(x), a in x, dir(x).

Calling, indexing, attribute access, etc. will convert the result to a Python object according to this table. This is typically a builtin Python type (for immutables) or a subtype of AnyValue.

Attribute access can be used to access Julia properties as well as normal class members. In the case of a name clash, the class member will take precedence. For convenience with Julia naming conventions, _b at the end of an attribute is replaced with ! and _bb is replaced with !!.

Members

  • _jl_raw(): Convert to a RawValue. (See also pyjlraw.)
  • _jl_display(): Display the object using Julia's display mechanism.
  • _jl_help(): Display help for the object.
source
juliacall.NumberValueClass

This wraps any Julia Number value. It is a subclass of numbers.Number and behaves similar to other Python numbers.

There are also subtypes ComplexValue, RealValue, RationalValue, IntegerValue which wrap values of the corresponding Julia types, and are subclasses of the corresponding numbers ABC.

source
juliacall.ArrayValueClass

This wraps any Julia AbstractArray value. It is a subclass of collections.abc.Collection.

It supports zero-up indexing, and can be indexed with integers or slices. Slicing returns a view of the original array.

If the array is strided and its eltype is supported (i.e. Bool, IntXX, UIntXX, FloatXX, Complex{FloatXX}, Ptr{Cvoid} or Tuple or NamedTuple of these) then it supports the buffer protocol and the numpy array interface. This means that numpy.asarray(this) will yield a view of the original array, so mutations are visible on the original.

Otherwise, the numpy __array__ method is supported, and this returns an array of Python objects converted from the contents of the array. In this case, numpy.asarray(this) is a copy of the original array.

Members

  • ndim: The number of dimensions.
  • shape: Tuple of lengths in each dimension.
  • copy(): A copy of the array.
  • reshape(shape): A reshaped view of the array.
  • to_numpy(dtype=None, copy=True, order="K"): Convert to a numpy array.
source
juliacall.VectorValueClass

This wraps any Julia AbstractVector value. It is a subclass of juliacall.ArrayValue and collections.abc.MutableSequence and behaves similar to a Python list.

Members

  • resize(size): Change the length of the vector.
  • sort(reverse=False, key=None): Sort the vector in-place.
  • reverse(): Reverse the vector.
  • clear(): Empty the vector.
  • insert(index, value): Insert the value at the given index.
  • append(value): Append the value to the end of the vector.
  • extend(values): Append the values to the end of the vector.
  • pop(index=-1): Remove and return the item at the given index.
  • remove(value): Remove the first item equal to the value.
  • index(value): The index of the first item equal to the value.
  • count(value): The number of items equal to the value.
source
juliacall.DictValueClass

This wraps any Julia AbstractDict value. It is a subclass of collections.abc.Mapping and behaves similar to a Python dict.

source
juliacall.SetValueClass

This wraps any Julia AbstractSet value. It is a subclass of collections.abc.Set and behaves similar to a Python set.

source
juliacall.IOValueClass

This wraps any Julia IO value. It is a subclass of io.IOBase and behaves like Python files.

There are also subtypes BinaryIOValue and TextIOValue, which are subclasses of io.BufferedIOBase (buffered bytes) and io.TextIOBase (text).

source
juliacall.ModuleValueClass

This wraps any Julia Module value.

It is the same as AnyValue except for one additional convenience method:

  • seval([module=self], code): Evaluates the given code (a string) in the given module.
source
juliacall.TypeValueClass

This wraps any Julia Type value.

It is the same as AnyValue except that indexing is used to access Julia's "curly" syntax for specifying parametric types:

from juliacall import Main as jl
 # equivalent to Vector{Int}() in Julia
-jl.Vector[jl.Int]()
source
juliacall.RawValueClass

Wraps any Julia value with a rigid interface suitable for generic programming.

Supports repr(x), str(x), attributes (x.attr), calling (x(a,b)), len(x), dir(x).

This is very similar to AnyValue except that indexing, calling, etc. will always return a RawValue.

Indexing with a tuple corresponds to indexing in Julia with multiple values. To index with a single tuple, it will need to be wrapped in another tuple.

Members

  • _jl_any(): Convert to a AnyValue (or subclass). (See also pyjl.)
source
+jl.Vector[jl.Int]()source
juliacall.RawValueClass

Wraps any Julia value with a rigid interface suitable for generic programming.

Supports repr(x), str(x), attributes (x.attr), calling (x(a,b)), len(x), dir(x).

This is very similar to AnyValue except that indexing, calling, etc. will always return a RawValue.

Indexing with a tuple corresponds to indexing in Julia with multiple values. To index with a single tuple, it will need to be wrapped in another tuple.

Members

  • _jl_any(): Convert to a AnyValue (or subclass). (See also pyjl.)
source
diff --git a/dev/juliacall/index.html b/dev/juliacall/index.html index 095fdd05..ff3afa09 100644 --- a/dev/juliacall/index.html +++ b/dev/juliacall/index.html @@ -25,4 +25,4 @@ "version": "0.5, 0.6" } } -}

Alternatively you can use add, rm, etc. from JuliaPkg to edit this file.

See JuliaPkg for more details.

Configuration

Some features of the Julia process, such as the optimization level or number of threads, may be configured in two ways:

-X optionEnvironment VariableDescription
-X juliacall-home=<dir>PYTHON_JULIACALL_BINDIR=<dir>The directory containing the julia executable.
-X juliacall-check-bounds=<yes|no|auto>PYTHON_JULIACALL_CHECK_BOUNDS=<yes|no|auto>Enable or disable bounds checking.
-X juliacall-compile=<yes|no|all|min>PYTHON_JULIACALL_COMPILE=<yes|no|all|min>Enable or disable JIT compilation.
-X juliacall-compiled-modules=<yes|no>PYTHON_JULIACALL_COMPILED_MODULES=<yes|no>Enable or disable incrementally compiling modules.
-X juliacall-depwarn=<yes|no|error>PYTHON_JULIACALL_DEPWARN=<yes|no|error>Enable or disable deprecation warnings.
-X juliacall-handle-signals=<yes|no>PYTHON_JULIACALL_HANDLE_SIGNALS=<yes|no>Enable or disable Julia signal handling.
-X juliacall-inline=<yes|no>PYTHON_JULIACALL_INLINE=<yes|no>Enable or disable inlining.
-X juliacall-min-optlevel=<0|1|2|3>PYTHON_JULIACALL_MIN_OPTLEVEL=<0|1|2|3>Optimization level.
-X juliacall-optimize=<0|1|2|3>PYTHON_JULIACALL_OPTIMIZE=<0|1|2|3>Minimum optimization level.
-X juliacall-procs=<N|auto>PYTHON_JULIACALL_PROCS=<N|auto>Launch N local worker process.
-X juliacall-startup-file=<yes|no>PYTHON_JULIACALL_STARTUP_FILE=<yes|no>Enable or disable your startup.jl file.
-X juliacall-sysimage=<file>PYTHON_JULIACALL_SYSIMAGE=<file>Use the given system image.
-X juliacall-threads=<N|auto>PYTHON_JULIACALL_THREADS=<N|auto>Launch N threads.
-X juliacall-warn-overwrite=<yes|no>PYTHON_JULIACALL_WARN_OVERWRITE=<yes|no>Enable or disable method overwrite warnings.
-X juliacall-autoload-ipython-extension=<yes|no>PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION=<yes|no>Enable or disable IPython extension autoloading.
+}

Alternatively you can use add, rm, etc. from JuliaPkg to edit this file.

See JuliaPkg for more details.

Configuration

Some features of the Julia process, such as the optimization level or number of threads, may be configured in two ways:

-X optionEnvironment VariableDescription
-X juliacall-home=<dir>PYTHON_JULIACALL_BINDIR=<dir>The directory containing the julia executable.
-X juliacall-check-bounds=<yes|no|auto>PYTHON_JULIACALL_CHECK_BOUNDS=<yes|no|auto>Enable or disable bounds checking.
-X juliacall-compile=<yes|no|all|min>PYTHON_JULIACALL_COMPILE=<yes|no|all|min>Enable or disable JIT compilation.
-X juliacall-compiled-modules=<yes|no>PYTHON_JULIACALL_COMPILED_MODULES=<yes|no>Enable or disable incrementally compiling modules.
-X juliacall-depwarn=<yes|no|error>PYTHON_JULIACALL_DEPWARN=<yes|no|error>Enable or disable deprecation warnings.
-X juliacall-handle-signals=<yes|no>PYTHON_JULIACALL_HANDLE_SIGNALS=<yes|no>Enable or disable Julia signal handling.
-X juliacall-inline=<yes|no>PYTHON_JULIACALL_INLINE=<yes|no>Enable or disable inlining.
-X juliacall-min-optlevel=<0|1|2|3>PYTHON_JULIACALL_MIN_OPTLEVEL=<0|1|2|3>Optimization level.
-X juliacall-optimize=<0|1|2|3>PYTHON_JULIACALL_OPTIMIZE=<0|1|2|3>Minimum optimization level.
-X juliacall-procs=<N|auto>PYTHON_JULIACALL_PROCS=<N|auto>Launch N local worker process.
-X juliacall-startup-file=<yes|no>PYTHON_JULIACALL_STARTUP_FILE=<yes|no>Enable or disable your startup.jl file.
-X juliacall-sysimage=<file>PYTHON_JULIACALL_SYSIMAGE=<file>Use the given system image.
-X juliacall-threads=<N|auto>PYTHON_JULIACALL_THREADS=<N|auto>Launch N threads.
-X juliacall-warn-overwrite=<yes|no>PYTHON_JULIACALL_WARN_OVERWRITE=<yes|no>Enable or disable method overwrite warnings.
-X juliacall-autoload-ipython-extension=<yes|no>PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION=<yes|no>Enable or disable IPython extension autoloading.
diff --git a/dev/objects.inv b/dev/objects.inv index 9f8ad91f6c0c852b980abb05c85015d31ee5d59d..708bae0c145d97724430a41c8f4a595f2165983d 100644 GIT binary patch delta 3161 zcmV-f45stz8T1*Dq6Z|cJ8|kHPLZh`fAD<(_r6P6Bs2a@@?!SOER6^q6Y_hyzb*-6ZPcBLhVe#ReS9j1^57-Z>&yf9j{0 zidYmYa+juY9?aQycPadOMBZI~BtMWlnU>R-=ZiEgMDhSy*wmDkAMnBgGMDKRPIHC# zZdd9suL8+q&T^il1l9kun}CDxoq?#Qf7xP#kE6rW z!!i9a9EBkrg)|)h)ZCFY6C!O zeV@2A!QFxzZGl<~E;GsD|9%1ntn~>83nosVBNTWTWnj_oV*YGm22JOk z4q_Gck~jd8&K=LuA-3ZPe{Jz~<1E*6x=KsRV#(QTMHlRmQ*gl<`(i;)U zRQ=ZdjGa6O;Z-Zs^_&2J7yv;4(Hj%JAeE$Ez7b1kROSU(X0MQqyWoj;6@Dqx4kHup&@-_aoIN_BFvC!*v2FGD2ALTcdH>~Y-cuCLDcSH zvuAa#LO^A+XT+rm>Y%1XSf`%`zw+)XX#P-Vso?D+PYN2R>AKO^u|+K*YKeN1DvM2M zxIK&Mf7O*&<9hoXRSr`mm>wsFcub+w*il%S<(k<5OnRIcYD?qxBPM@z2&v)bPA6j0 zM=i5EHZ5Z&>5LT&OC=CI>yTb!sVb55VsoG1eJqUB-QZSo?bNEo*`A0|i04ivy1Rip zZ&adH|8`DXlHhj^?h`=~TxNI(9kI$>SI~E_Gd=Ai9H(zSb%ay3&59(r%vVXYfL+ouH!&tkXPo{h zk|-`!n{mVb7W}7nYv_W*)@uZ~zq{H*CR|PG&4}Ji*TQ?{+OR#>hAp}F)QMXsyXAP= ze~4Qrl^{=vOQRjWQqh=(+o{d+>d*+N9KKSLqQPl_Y_Hk7E1xPhHmi26BPRPWhpFol~>iJ;|t=_DC&vT z-FYA8Nv*nbhj>C%y7EX+)e=!r9Qfao{_v5S)$FJ+H^6o%m6oaLPC10Np zkcwQ7Qudw2R>N>5^;?@F|MdFr5 zBDky>sVe&5OJYtx+xAS>hA-+Q7mjvH;lfRF;m8W%g197Fyb~i{yf@h`-bp21e+8(- zJ0UKOt{V5Qj_X$`?=C+o`(1mD(VBGIUwFJvbI7|q&-;x%tL1A$&#$VnZ?DO#HePk@ z=Hx1YjBUU<>!Yo3TnC&pM_u8VxHQ3a+cD~pX@Z?COvhoL6gaLcQw69LYD-g1UL6PG6VQs8rJOeH!eW$I@IhXD{&idyy-(-~e&!X)1jm-oetpa9o2p zHO(eljI+fU)Hgha%W%e_S05%v!w{u$Y@T}{!*qqSyy5ug)aU&1prad&-?6E7pPedi zG2e3PaqObZhB_{WcVw_iiR978Zt_To!T1MWWCQcgdJ&^~g5fdzjfnbX z?ZzWu8&D`ss;hf8f1BOo%aVdUsH404$giBmV@x>e;^z+F3#R`JPf#pHUf{n zNs45kL{;%O7ti< zDy2*+x&Cv{_AlX2=I!kM9%}m+p7>NhK0X!iH;AYo`$j#pSKphZJ|!crYH5G^oc%K| zd=3s--m~F`e{{gS!s(uBYfB0u_i8!7)jfqU6Fz9kv;Oc}^$^y5RNqWN|5D=VOfyO8 zHJUSD&hlbtt3CE%P=EB`q2=LoQY%ECo}Lv0+xkj=*=lH-MQm4|MYNAlhE^UrW%!K> zAH1Wd@Yaj)gG-h?_zdniew*zczs+`^&gXm8Z33E9f3J?4Kl7+mbHl++w>rx0>g{vH z^%t#%jV{>K$2W&6K<8hX{=*ZWq0{Zqfz3WePo1{@;`sM?Ue%U=Wu5Q`pJ3`Wk?=Kp z`*wKH3G|@obt50{G1<^?JKRtN9Tk;NsuX_jPz3&goL8k#F#KkiN9P4681gR08FM^Z z2N^1ae?3H4JLmPEK8}gspcpPR{jJ?MtYGgXTMm7XC5HE(BG1;}J@lF^Raz_fGvJ1l z@;Em4D&}SBRh&ZS@1eQRe89-sR#1CQS!$8toP3bPDs3r{&wP2K09rS_?e))s$Jvl+ z1=A)TnLoPP&rq;t^3b%;`yH?LO$>}JmA0oMM`3cchj+Gh`H@ezFypc3MDf9IOp?ho zgN!}s{c1&mK(E*B#sG)BZbxYAoYa1o8+r8rbKmgi@f`waqSB|mI?4Y7B)nYRGcqlF delta 3134 zcmV-E48imC8S5F4q6ajsGjZZ1Zjq@Re|A3rd*6jDk{N#{c`^HCmPUk*3Hc*k@*rCk zi!_N?9J`;@Z;#0DrI@*NRPs5OJc)QaNB#K``D`D9Z)Ggl`ZCo^yGr$K(c4ZJ!^JcL+*~l-#NpYba{TZV>hHkzqv;g$5YQj1^5bd~-yuf7DMg z6|pE*R-=ZiEgMDhSy*wmDkAK(H3nagwuySc)5 zw=1=oSApa)XE{&Og6A%;`yS<}ej^|7SEFw_xlZx|9&u?SgN#Lg zvj;%9O5rnEMnx(+Asjsd7==~Ce{V6ZMcm|T6Fsn9)#RVc7*}Qqy{2W(sS*GR0~utQ z=oeHZIanKISr&^3v;jM%Poh{*zMS&ejL)b(%&X@5sF)Z38u-ESTLNI@ngAH7z|e>Q z%$TJHBQ6+0Fk-=s*k1*g5?(KPA)>y*)+R&IWayg7tV3vZZ!#Q&Zw-q&f6W#fd>kE~ z9**gc;V2C0D5T-|r{*FJV|-!A55n`B;UK&q`aN-Bg3;l{;W$*#$LihrR%k=6p$!8< z>-WTk3GNo$XbaR@aG6OC|MwFx@LHd6c)`T!lLUS8Zm&S@ubPGws|+mqZOord%%JJK z(?P7FUJ{3aq;tn}bcpTPe?nV)-Pp_ZoUYQ6vRHC9ThRr3(p5ggwGF0HkKdL@!76ej^tG=M+Oti;XQF-f-5ljg3~Bw zdA@1a?SWSF5W^F^;TeZoH;F_yfHuOfkTTJmtVe)3ifDl~e-8jq@UPk}w})y4Q#lq< zFhs);@PZmfB@|sIEYlf8m!3;tF3|;nW^*A`oyC%(Uo5A=o!BhtYMG!7om$miz`vcA zcv@=~>8&B25*H+B)V);Iz3p!Jvb99Mg}gWY2EN_XCT=0^X?k19?n=7bQXZb?*b3zg zii4d(Ij)6*fAm%;$HWEEmCK2(T+V2Cy1Q~YsVf&`s4ABe;=-6TzgfQ5Ef<{fh9&F) zO;_92%<-HcGD7)Y3dkXlv%o7sF(T%Yaw#D-tKcn`St^wm<I???d_&#)Uc0K4r)(F_gfBa6$v5fRx8m}c8Ja*txjIk{U6DPudcxeB6o z51T!!a}_dFHhV@~n4k`7N`!U#Y2YjGu7c(db(RW#d*n$$<1}42`Z~5K5~4`dNvbS1 zq2cx{f2OG`uSR-%jw**K5KNB~13aeCY3wMh47o-&3?@BJ477!D`w^2rI)v14bEgwA z>7$m}9h;UhlXS)khNTh+o^?pCL8?k5O>Ev1e2;~ZdK=tIuAN$yINK933h~^jM0YoE z=Z#9V>fg?Z3ljXn!F?hqg3Amyp(9qA>k9fVf0dA>+u{?lk(y0MBgIAxTWb@tO3eCi0NYMT{EaG9@?XaTFFWo}|jl+HN) zQ6y1Zsy5?>{Vn)U?bgu64oj~A;QB7LiA+dM>cxm&OxMDD<=U`4*M=>*_SA`6C%ff% zf7*y!CzT*ii3_70zEaVchTEYHd9`U|s2sjhl7hi$fo!kYyDOh6Ha4qvts^WIXH3pa zie7aE%6De&si{rYU6~Nw8>PyEYcRi-B8JS~doHM?e&Hx@cUcPLuJWq7bbLWv7zI7C zx;yWKJgHT8?f_4S3lh9fANr5t+QNwue>G-8Q!35Y`+l4?;`nvFRo)$FjAF3Vu;Azw2ik?75l$BRARU~H43~P+e|)cTGzam;0tKH62wcU2&c$<=m_8K*NeGaDkv!3u zKXNs>>UW-s1yf&eSwhzW)o0Yh#41|XzLc!T^~J)thYyb3i-mFRgJa^t1iwAAWfpg) z^x9-j>Qbo3bl}7-h3etJ32{N1vzYEt(AwanwPozIEKO^9wJ6V>1m2^He?4y`@VbmW zCoW9zXMyL~m^F0Hztk1dsJ@BXJ-s}28^5rgUY^#SpMo(%m$vC|qaSMyf9rzn@G6!3 zFk1L%45O zH!PCrAx0ozU*a#Fye)hxe~2|9aiRjBzZbbu3yuZ1?xxcB;T@3vg+mzRQ!{F^#W-7x zL49vyxD00;I`Cm~Gzd`|$L8Dv5vD7g&<*E*PJQ+t58ArX_#K;S_t~lP7V|Bq9@{R; zY^dX6ct-@gcL%{ON!Hga6TEA@&sGV49iR z7_>(k$i6HGalea|8D^_*K8v$tQ`amM@&0WXs&+N%3Y@?sW z!vePv+wJP3y1}}{>+OLNNFs=jhqe$c#ayYi|L z#5_(@388L4r1(%Sr(F633y;N(b*^#tS=))u$}zT?bv+SkPtABy>t#@C)|hx@XgmbH z!=mZGm&xj9V*mS}vNUb;eND|pJ2?9lP!7VYgK*S%ID6A^e;9BNZ3G^DlN8B7iK^mn zE}rkd7x!6QK8U0(er~G+RnzdFUaPmV9)#mo)CJ2u<6j|5zK@@@v?6IbsFX6PNhK0X!iH;AZ@eWT9o)%RwpPsxZ>E$vUAy?^0_&&DCkdp6vV z4wzRs-BWFCe@Q{)UM&Z>x~C9k!iQV(tUr6LdI;-2s&A&Ce<|^FrkSMl8qJxnTzMh1 z)gJpGs6S=!(DLv(sTHD6PtS^hZG9!bY&A5^B5zloMQ$IV46QtL%J3T%K6pn@;jI_p z$1Yj&;4`@6_#L%-{EpgvI-l=Vw+U!cy*h6G%%f7xe+>sW-D)ehtKXg@uD?DtY;?h< zKE63r0XqN6^dFx144rO=4s7-*dg`?G7stP{^QyM|E9-_LlO9AZ(fx`!SMTD9-SBLV8~sJGv;`-4l+~-dx)@h z&g+jpOOA=(pcpPR{axHQtYB{?TMoU)62tpXk!S0754|Q!mDURW417aMc^sR274x$6 zDo&yE_t4xIK44^RE2zDuEVamRPCiItm9`X

whereas with PythonCall the following does mutate x:

x = ["foo", "bar"]
 Py(x).append("baz")
-@show x # --> ["foo", "bar", "baz"]

In fact, PythonCall has the policy that any mutable object will by default be wrapped in this way, which not only preserves mutability but makes conversion faster for large containers since it does not require taking a copy of all the data.

Automatic conversion

In PyCall, most function calls, attribute accesses, indexing, etc. of Python object by default automatically convert their result to a Julia object. This means that the following

pyimport("sys").modules["KEY"] = "VALUE"

does not actually modify the modules dict because it was copied to a new Julia Dict. This was probably not intended, plus it wasted time copying the whole dictionary. Instead you must do

set!(pyimport(os)."environ", "KEY", "VALUE")

In PythonCall, we don't do any such automatic conversion: we always return Py. This means that the first piece of code above does what you think.

Which Python

PyCall uses some global installation of Python - typically the version of Python installed on the system or used by Conda.

PythonCall uses a separate Conda environment for each Julia environment/project/package and installs Python (and other Python packages) into that. This means that different Julia projects can maintain an isolated set of Python dependencies (including the Python version itself).

Corresponding Python packages

PyCall has the corresponding Python package PyJulia for calling Julia from Python, and PythonCall similarly has JuliaCall.

One difference is between them is their code size: PyJulia is a large package, whereas JuliaCall is very small, with most of the implementation being in PythonCall itself. The practical up-shot is that PythonCall/JuliaCall have very symmetric interfaces; for example they use identical conversion policies and have the same set of wrapper types available.

Note also that JuliaCall will use a separate Julia project for each virtual/conda environment. This means that different Python environments can maintain an isolated set of Julia dependencies, including the versions of Julia and PythonCall themselves.

Compatibility

PyCall supports Julia 0.7+ and Python 2.7+, whereas PythonCall supports Julia 1.6.1+ and Python 3.8+. PyCall requires numpy to be installed, PythonCall doesn't (it provides the same fast array access through the buffer protocol and array interface).

+@show x # --> ["foo", "bar", "baz"]

In fact, PythonCall has the policy that any mutable object will by default be wrapped in this way, which not only preserves mutability but makes conversion faster for large containers since it does not require taking a copy of all the data.

Automatic conversion

In PyCall, most function calls, attribute accesses, indexing, etc. of Python object by default automatically convert their result to a Julia object. This means that the following

pyimport("sys").modules["KEY"] = "VALUE"

does not actually modify the modules dict because it was copied to a new Julia Dict. This was probably not intended, plus it wasted time copying the whole dictionary. Instead you must do

set!(pyimport(os)."environ", "KEY", "VALUE")

In PythonCall, we don't do any such automatic conversion: we always return Py. This means that the first piece of code above does what you think.

Which Python

PyCall uses some global installation of Python - typically the version of Python installed on the system or used by Conda.

PythonCall uses a separate Conda environment for each Julia environment/project/package and installs Python (and other Python packages) into that. This means that different Julia projects can maintain an isolated set of Python dependencies (including the Python version itself).

Corresponding Python packages

PyCall has the corresponding Python package PyJulia for calling Julia from Python, and PythonCall similarly has JuliaCall.

One difference is between them is their code size: PyJulia is a large package, whereas JuliaCall is very small, with most of the implementation being in PythonCall itself. The practical up-shot is that PythonCall/JuliaCall have very symmetric interfaces; for example they use identical conversion policies and have the same set of wrapper types available.

Note also that JuliaCall will use a separate Julia project for each virtual/conda environment. This means that different Python environments can maintain an isolated set of Julia dependencies, including the versions of Julia and PythonCall themselves.

Compatibility

PyCall supports Julia 0.7+ and Python 2.7+, whereas PythonCall supports Julia 1.6.1+ and Python 3.8+. PyCall requires numpy to be installed, PythonCall doesn't (it provides the same fast array access through the buffer protocol and array interface).

diff --git a/dev/pythoncall-reference/index.html b/dev/pythoncall-reference/index.html index 1357bc05..77c81e17 100644 --- a/dev/pythoncall-reference/index.html +++ b/dev/pythoncall-reference/index.html @@ -1,18 +1,18 @@ -Reference · PythonCall & JuliaCall

PythonCall API Reference

Py objects

PythonCall.Core.PyType
Py(x)

Convert x to a Python object, of type Py.

Conversion happens according to these rules.

Such an object supports attribute access (obj.attr), indexing (obj[idx]), calling (obj(arg1, arg2)), iteration (for x in obj), arithmetic (obj + obj2) and comparison (obj > obj2), among other things. These operations convert all their arguments to Py and return Py.

source
PythonCall.Core.pybuiltinsModule
pybuiltins

An object whose fields are the Python builtins, of type Py.

For example pybuiltins.None, pybuiltins.int, pybuiltins.ValueError.

source

Constructors

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

PythonCall.Core.pycollistFunction
pycollist(x::AbstractArray)

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

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

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

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source
PythonCall.Core.pyrowlistFunction
pyrowlist(x::AbstractArray)

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

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source

Builtins

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

PythonCall.Core.pyevalFunction
pyeval([T=Py], code, globals, locals=nothing)

Evaluate the given Python code, returning the result as a T.

If globals is a Module, then a persistent dict unique to that module is used.

By default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.

See also @pyeval.

Examples

The following computes 1.1+2.2 in the Main module as a Float64:

pyeval(Float64, "x+y", Main, (x=1.1, y=2.2))  # returns 3.3
source
PythonCall.Core.@pyevalMacro
@pyeval [inputs =>] code [=> T]

Evaluate the given code in a new local scope and return the answer as a T.

The global scope is persistent and unique to the current module.

The code must be a literal string or command.

The inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.

Examples

The following computes 1.1+2.2 and returns a Float64:

@pyeval (x=1.1, y=2.2) => `x+y` => Float64  # returns 3.3
source
PythonCall.Core.pyexecFunction
pyexec([T=Nothing], code, globals, locals=nothing)

Execute the given Python code.

If globals is a Module, then a persistent dict unique to that module is used.

By default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.

If T==Nothing then returns nothing. Otherwise T must be a concrete NamedTuple type and the corresponding items from locals are extracted and returned.

See also @pyexec.

Examples

The following computes 1.1+2.2 in the Main module as a Float64:

pyexec(@NamedTuple{ans::Float64}, "ans=x+y", Main, (x=1.1, y=2.2))  # returns (ans = 3.3,)

Marking variables as global saves them into the module scope, so that they are available in subsequent invocations:

pyexec("global x; x=12", Main)
-pyeval(Int, "x", Main)  # returns 12
source
PythonCall.Core.@pyexecMacro
@pyexec [inputs =>] code [=> outputs]

Execute the given code in a new local scope.

The global scope is persistent and unique to the current module.

The code must be a literal string or command.

The inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.

The outputs is a tuple of outputs of the form x::T=v, meaning that v is extracted from locals, converted to T and assigned to x. Only x is required: T defaults to Py and v defaults to x.

Examples

The following computes 1.1+2.2 and assigns its value to ans as a Float64:

@pyexec (x=1.1, y=2.2) => `ans=x+y` => ans::Float64  # returns 3.3

Marking variables as global saves them into the module scope, so that they are available in subsequent invocations:

@pyexec `global x; x=12`
-@pyeval `x` => Int  # returns 12
source
PythonCall.Core.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.

source
PythonCall.Core.pygetitemFunction
pygetitem(x, k, [d])

Equivalent x[k] in Python.

If d is specified, it is returned if the item does not exist (i.e. if x[k] raises a KeyError or IndexError).

source
PythonCall.Core.pyimportFunction
pyimport(m)
+Reference · PythonCall & JuliaCall

PythonCall API Reference

Py objects

PythonCall.Core.PyType
Py(x)

Convert x to a Python object, of type Py.

Conversion happens according to these rules.

Such an object supports attribute access (obj.attr), indexing (obj[idx]), calling (obj(arg1, arg2)), iteration (for x in obj), arithmetic (obj + obj2) and comparison (obj > obj2), among other things. These operations convert all their arguments to Py and return Py.

source
PythonCall.Core.pybuiltinsModule
pybuiltins

An object whose fields are the Python builtins, of type Py.

For example pybuiltins.None, pybuiltins.int, pybuiltins.ValueError.

source

Constructors

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

PythonCall.Core.pycollistFunction
pycollist(x::AbstractArray)

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

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

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

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source
PythonCall.Core.pyrowlistFunction
pyrowlist(x::AbstractArray)

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

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source

Builtins

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

PythonCall.Core.pyevalFunction
pyeval([T=Py], code, globals, locals=nothing)

Evaluate the given Python code, returning the result as a T.

If globals is a Module, then a persistent dict unique to that module is used.

By default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.

See also @pyeval.

Examples

The following computes 1.1+2.2 in the Main module as a Float64:

pyeval(Float64, "x+y", Main, (x=1.1, y=2.2))  # returns 3.3
source
PythonCall.Core.@pyevalMacro
@pyeval [inputs =>] code [=> T]

Evaluate the given code in a new local scope and return the answer as a T.

The global scope is persistent and unique to the current module.

The code must be a literal string or command.

The inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.

Examples

The following computes 1.1+2.2 and returns a Float64:

@pyeval (x=1.1, y=2.2) => `x+y` => Float64  # returns 3.3
source
PythonCall.Core.pyexecFunction
pyexec([T=Nothing], code, globals, locals=nothing)

Execute the given Python code.

If globals is a Module, then a persistent dict unique to that module is used.

By default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.

If T==Nothing then returns nothing. Otherwise T must be a concrete NamedTuple type and the corresponding items from locals are extracted and returned.

See also @pyexec.

Examples

The following computes 1.1+2.2 in the Main module as a Float64:

pyexec(@NamedTuple{ans::Float64}, "ans=x+y", Main, (x=1.1, y=2.2))  # returns (ans = 3.3,)

Marking variables as global saves them into the module scope, so that they are available in subsequent invocations:

pyexec("global x; x=12", Main)
+pyeval(Int, "x", Main)  # returns 12
source
PythonCall.Core.@pyexecMacro
@pyexec [inputs =>] code [=> outputs]

Execute the given code in a new local scope.

The global scope is persistent and unique to the current module.

The code must be a literal string or command.

The inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.

The outputs is a tuple of outputs of the form x::T=v, meaning that v is extracted from locals, converted to T and assigned to x. Only x is required: T defaults to Py and v defaults to x.

Examples

The following computes 1.1+2.2 and assigns its value to ans as a Float64:

@pyexec (x=1.1, y=2.2) => `ans=x+y` => ans::Float64  # returns 3.3

Marking variables as global saves them into the module scope, so that they are available in subsequent invocations:

@pyexec `global x; x=12`
+@pyeval `x` => Int  # returns 12
source
PythonCall.Core.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.

source
PythonCall.Core.pygetitemFunction
pygetitem(x, k, [d])

Equivalent x[k] in Python.

If d is specified, it is returned if the item does not exist (i.e. if x[k] raises a KeyError or IndexError).

source
PythonCall.Core.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.

source
PythonCall.Core.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.

source

Conversion to Julia

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

PythonCall.Core.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.

source
PythonCall.Convert.@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).

source

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.JlWrap.pyjlFunction
pyjl([t=pyjltype(x)], 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.

To define a custom conversion for your type T, overload pyjltype(::T).

source
PythonCall.JlWrap.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.

source

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.

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.Core.pyeqFunction
pyeq(x, y)
-pyeq(Bool, x, y)

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

source
PythonCall.Core.pyneFunction
pyne(x, y)
-pyne(Bool, x, y)

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

source
PythonCall.Core.pyleFunction
pyle(x, y)
-pyle(Bool, x, y)

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

source
PythonCall.Core.pyltFunction
pylt(x, y)
-pylt(Bool, x, y)

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

source
PythonCall.Core.pygeFunction
pyge(x, y)
-pyge(Bool, x, y)

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

source
PythonCall.Core.pygtFunction
pygt(x, y)
-pygt(Bool, x, y)

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

source

Create classes

These functions can be used to create new Python classes where the functions are implemented in Julia. You can instead use @pyeval etc. to create pure-Python classes.

PythonCall.Core.pytypeMethod
pytype(name, bases, dict)

Create a new type. Equivalent to type(name, bases, dict) in Python.

If bases is not a Python object, it is converted to one using pytuple.

The dict may either by a Python object or a Julia iterable. In the latter case, each item may either be a name => value pair or a Python object with a __name__ attribute.

In order to use a Julia Function as an instance method, it must be wrapped into a Python function with pyfunc. Similarly, see also pyclassmethod, pystaticmethod or pyproperty. In all these cases, the arguments passed to the function always have type Py. See the example below.

Example

Foo = pytype("Foo", (), [
+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.

source
PythonCall.Core.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.

source

Conversion to Julia

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

PythonCall.Core.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.

source
PythonCall.Convert.@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).

source

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.JlWrap.pyjlFunction
pyjl([t=pyjltype(x)], 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.

To define a custom conversion for your type T, overload pyjltype(::T).

source
PythonCall.JlWrap.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.

source

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.

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.Core.pyeqFunction
pyeq(x, y)
+pyeq(Bool, x, y)

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

source
PythonCall.Core.pyneFunction
pyne(x, y)
+pyne(Bool, x, y)

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

source
PythonCall.Core.pyleFunction
pyle(x, y)
+pyle(Bool, x, y)

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

source
PythonCall.Core.pyltFunction
pylt(x, y)
+pylt(Bool, x, y)

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

source
PythonCall.Core.pygeFunction
pyge(x, y)
+pyge(Bool, x, y)

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

source
PythonCall.Core.pygtFunction
pygt(x, y)
+pygt(Bool, x, y)

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

source

Create classes

These functions can be used to create new Python classes where the functions are implemented in Julia. You can instead use @pyeval etc. to create pure-Python classes.

PythonCall.Core.pytypeMethod
pytype(name, bases, dict)

Create a new type. Equivalent to type(name, bases, dict) in Python.

If bases is not a Python object, it is converted to one using pytuple.

The dict may either by a Python object or a Julia iterable. In the latter case, each item may either be a name => value pair or a Python object with a __name__ attribute.

In order to use a Julia Function as an instance method, it must be wrapped into a Python function with pyfunc. Similarly, see also pyclassmethod, pystaticmethod or pyproperty. In all these cases, the arguments passed to the function always have type Py. See the example below.

Example

Foo = pytype("Foo", (), [
     "__module__" => "__main__",
 
     pyfunc(
@@ -56,9 +56,9 @@
             nothing
         end,
     ),
-])
source
PythonCall.JlWrap.pyfuncFunction
pyfunc(f; [name], [qualname], [doc], [signature])

Wrap the callable f as an ordinary Python function.

The name, qualname, docstring or signature can optionally be set with name, qualname, doc or signature.

Unlike Py(f) (or pyjl(f)), the arguments passed to f are always of type Py, i.e. they are never converted.

source
PythonCall.JlWrap.pyclassmethodFunction
pyclassmethod(f; ...)

Convert callable f to a Python class method.

If f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Keyword arguments are passed to pyfunc.

source
PythonCall.JlWrap.pystaticmethodFunction
pystaticmethod(f; ...)

Convert callable f to a Python static method.

If f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Any keyword arguments are passed to pyfunc.

source
PythonCall.JlWrap.pypropertyFunction
pyproperty(; get=nothing, set=nothing, del=nothing, doc=nothing)
-pyproperty(get)

Create a Python property with the given getter, setter and deleter.

If get, set or del is not a Python object (e.g. if it is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to it are always of type Py.

source

Wrapper types

The following types wrap a Python object, giving it the semantics of a Julia object. For example PyList(x) interprets the Python sequence x as a Julia abstract vector.

Apart from a few fundamental immutable types, conversion from Python to Julia Any will return a wrapper type such as one of these, or simply Py if no wrapper type is suitable.

PythonCall.Wrap.PyListType
PyList{T=Py}([x])

Wraps the Python list x (or anything satisfying the sequence interface) as an AbstractVector{T}.

If x is not a Python object, it is converted to one using pylist.

source
PythonCall.Wrap.PySetType
PySet{T=Py}([x])

Wraps the Python set x (or anything satisfying the set interface) as an AbstractSet{T}.

If x is not a Python object, it is converted to one using pyset.

source
PythonCall.Wrap.PyDictType
PyDict{K=Py,V=Py}([x])

Wraps the Python dict x (or anything satisfying the mapping interface) as an AbstractDict{K,V}.

If x is not a Python object, it is converted to one using pydict.

source
PythonCall.Wrap.PyArrayType
PyArray{T,N,M,L,R}(x; copy=true, array=true, buffer=true)

Wrap the Python array x as a Julia AbstractArray{T,N}.

The input x can be bytes, bytearray, array.array, numpy.ndarray or anything satisfying the buffer protocol (if buffer=true) or the numpy array interface (if array=true).

If copy=false then the resulting array is guaranteed to directly wrap the data in x. If copy=true then a copy is taken if necessary to produce an array.

The type parameters are all optional, and are:

  • T: The element type.
  • N: The number of dimensions.
  • M: True if the array is mutable.
  • L: True if the array supports fast linear indexing.
  • R: The element type of the underlying buffer. Often equal to T.
source
PythonCall.Wrap.PyIOType
PyIO(x; own=false, text=missing, line_buffering=false, buflen=4096)

Wrap the Python IO stream x as a Julia IO stream.

When this goes out of scope and is finalized, it is automatically flushed. If own=true then it is also closed.

If text=false then x must be a binary stream and arbitrary binary I/O is possible. If text=true then x must be a text stream and only UTF-8 must be written (i.e. use print not write). If text is not specified then it is chosen automatically. If x is a text stream and you really need a binary stream, then often PyIO(x.buffer) will work.

If line_buffering=true then output is flushed at each line.

For efficiency, reads and writes are buffered before being sent to x. The size of the buffers is buflen. The buffers are cleared using flush.

source
PythonCall.Wrap.PyPandasDataFrameType
PyPandasDataFrame(x; [indexname::Union{Nothing,Symbol}], [columnnames::Function], [columntypes::Function])

Wraps the pandas DataFrame x as a Tables.jl-compatible table.

  • indexname: The name of the column including the index. The default is nothing, meaning to exclude the index.
  • columnnames: A function mapping the Python column name (a Py) to the Julia one (a Symbol). The default is x -> Symbol(x).
  • columntypes: A function taking the column name (a Symbol) and returning either the desired element type of the column, or nothing to indicate automatic inference.
source
PythonCall.JlWrap.PyObjectArrayType
PyObjectArray(undef, dims...)
-PyObjectArray(array)

An array of Pys which supports the Python buffer protocol.

Internally, the objects are stored as an array of pointers.

source

Custom wrappers

Here is a minimal example of defining a wrapper type. You may add methods, fields and a supertype to the type to specialise its behaviour. See any of the above wrapper types for examples.

# The new type with a field for the Python object being wrapped.
+])
source
PythonCall.JlWrap.pyfuncFunction
pyfunc(f; [name], [qualname], [doc], [signature])

Wrap the callable f as an ordinary Python function.

The name, qualname, docstring or signature can optionally be set with name, qualname, doc or signature.

Unlike Py(f) (or pyjl(f)), the arguments passed to f are always of type Py, i.e. they are never converted.

source
PythonCall.JlWrap.pyclassmethodFunction
pyclassmethod(f; ...)

Convert callable f to a Python class method.

If f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Keyword arguments are passed to pyfunc.

source
PythonCall.JlWrap.pystaticmethodFunction
pystaticmethod(f; ...)

Convert callable f to a Python static method.

If f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Any keyword arguments are passed to pyfunc.

source
PythonCall.JlWrap.pypropertyFunction
pyproperty(; get=nothing, set=nothing, del=nothing, doc=nothing)
+pyproperty(get)

Create a Python property with the given getter, setter and deleter.

If get, set or del is not a Python object (e.g. if it is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to it are always of type Py.

source

Wrapper types

The following types wrap a Python object, giving it the semantics of a Julia object. For example PyList(x) interprets the Python sequence x as a Julia abstract vector.

Apart from a few fundamental immutable types, conversion from Python to Julia Any will return a wrapper type such as one of these, or simply Py if no wrapper type is suitable.

PythonCall.Wrap.PyListType
PyList{T=Py}([x])

Wraps the Python list x (or anything satisfying the sequence interface) as an AbstractVector{T}.

If x is not a Python object, it is converted to one using pylist.

source
PythonCall.Wrap.PySetType
PySet{T=Py}([x])

Wraps the Python set x (or anything satisfying the set interface) as an AbstractSet{T}.

If x is not a Python object, it is converted to one using pyset.

source
PythonCall.Wrap.PyDictType
PyDict{K=Py,V=Py}([x])

Wraps the Python dict x (or anything satisfying the mapping interface) as an AbstractDict{K,V}.

If x is not a Python object, it is converted to one using pydict.

source
PythonCall.Wrap.PyArrayType
PyArray{T,N,M,L,R}(x; copy=true, array=true, buffer=true)

Wrap the Python array x as a Julia AbstractArray{T,N}.

The input x can be bytes, bytearray, array.array, numpy.ndarray or anything satisfying the buffer protocol (if buffer=true) or the numpy array interface (if array=true).

If copy=false then the resulting array is guaranteed to directly wrap the data in x. If copy=true then a copy is taken if necessary to produce an array.

The type parameters are all optional, and are:

  • T: The element type.
  • N: The number of dimensions.
  • M: True if the array is mutable.
  • L: True if the array supports fast linear indexing.
  • R: The element type of the underlying buffer. Often equal to T.
source
PythonCall.Wrap.PyIOType
PyIO(x; own=false, text=missing, line_buffering=false, buflen=4096)

Wrap the Python IO stream x as a Julia IO stream.

When this goes out of scope and is finalized, it is automatically flushed. If own=true then it is also closed.

If text=false then x must be a binary stream and arbitrary binary I/O is possible. If text=true then x must be a text stream and only UTF-8 must be written (i.e. use print not write). If text is not specified then it is chosen automatically. If x is a text stream and you really need a binary stream, then often PyIO(x.buffer) will work.

If line_buffering=true then output is flushed at each line.

For efficiency, reads and writes are buffered before being sent to x. The size of the buffers is buflen. The buffers are cleared using flush.

source
PythonCall.Wrap.PyPandasDataFrameType
PyPandasDataFrame(x; [indexname::Union{Nothing,Symbol}], [columnnames::Function], [columntypes::Function])

Wraps the pandas DataFrame x as a Tables.jl-compatible table.

  • indexname: The name of the column including the index. The default is nothing, meaning to exclude the index.
  • columnnames: A function mapping the Python column name (a Py) to the Julia one (a Symbol). The default is x -> Symbol(x).
  • columntypes: A function taking the column name (a Symbol) and returning either the desired element type of the column, or nothing to indicate automatic inference.
source
PythonCall.JlWrap.PyObjectArrayType
PyObjectArray(undef, dims...)
+PyObjectArray(array)

An array of Pys which supports the Python buffer protocol.

Internally, the objects are stored as an array of pointers.

source

Custom wrappers

Here is a minimal example of defining a wrapper type. You may add methods, fields and a supertype to the type to specialise its behaviour. See any of the above wrapper types for examples.

# The new type with a field for the Python object being wrapped.
 struct MyType
     py::Py
 end
@@ -67,4 +67,4 @@
 ispy(x::MyType) = true
 
 # Says how to access the underlying Python object.
-Py(x::MyType) = x.py

@py and @pyconst

PythonCall.PyMacro.@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 is y in Python)
  • x.foo is translated to pygetattr(x, "foo")
  • import x: f as g is translated to g = pyimport("x" => "f") (from x import f as g in Python)

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

See the online documentation for more details.

Warning

This macro is experimental. It may be modified or removed in a future release.

source
PythonCall.Core.@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!().

source

The Python interpreter

These functions are not exported. They give information about which Python interpreter is being used.

Low-level API

The functions here are not exported. They are mostly unsafe in the sense that you can crash Julia by using them incorrectly.

PythonCall.Core.pynewFunction
pynew([ptr])

A new Py representing the Python object at ptr (NULL by default).

If ptr is given and non-NULL, this function steals a reference to the Python object it points at, i.e. the new Py object owns a reference.

Note that NULL Python objects are not safe in the sense that most API functions will probably crash your Julia session if you pass a NULL argument.

source
PythonCall.Core.pycopy!Function
pycopy!(dst::Py, src)

Copy the Python object src into dst, so that they both represent the same object.

This function exists to support module-level constant Python objects. It is illegal to call most PythonCall API functions at the top level of a module (i.e. before __init__() has run) so you cannot do const x = pything() at the top level. Instead do const x = pynew() at the top level then pycopy!(x, pything()) inside __init__().

Assumes dst is NULL, otherwise a memory leak will occur.

source
PythonCall.Core.pydel!Function
pydel!(x::Py)

Delete the Python object x.

DANGER! Use this function ONLY IF the Julia object x could have been garbage-collected anyway, i.e. was about to become unreachable. This means you MUST KNOW that no other part of the program has the Julia object x.

This decrements the reference count, sets the pointer to NULL and appends x to a cache of unused objects (PYNULL_CACHE).

This is an optimization to avoid excessive allocation and deallocation in Julia, which can be a significant source of slow-down in code which uses a lot of Python objects. It allows pynew() to pop an item from PYNULL_CACHE instead of allocating one, and avoids calling the relatively slow finalizer on x.

source
+Py(x::MyType) = x.py

@py and @pyconst

PythonCall.PyMacro.@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 is y in Python)
  • x.foo is translated to pygetattr(x, "foo")
  • import x: f as g is translated to g = pyimport("x" => "f") (from x import f as g in Python)

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

See the online documentation for more details.

Warning

This macro is experimental. It may be modified or removed in a future release.

source
PythonCall.Core.@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!().

source

The Python interpreter

These functions are not exported. They give information about which Python interpreter is being used.

Low-level API

The functions here are not exported. They are mostly unsafe in the sense that you can crash Julia by using them incorrectly.

PythonCall.Core.pynewFunction
pynew([ptr])

A new Py representing the Python object at ptr (NULL by default).

If ptr is given and non-NULL, this function steals a reference to the Python object it points at, i.e. the new Py object owns a reference.

Note that NULL Python objects are not safe in the sense that most API functions will probably crash your Julia session if you pass a NULL argument.

source
PythonCall.Core.pycopy!Function
pycopy!(dst::Py, src)

Copy the Python object src into dst, so that they both represent the same object.

This function exists to support module-level constant Python objects. It is illegal to call most PythonCall API functions at the top level of a module (i.e. before __init__() has run) so you cannot do const x = pything() at the top level. Instead do const x = pynew() at the top level then pycopy!(x, pything()) inside __init__().

Assumes dst is NULL, otherwise a memory leak will occur.

source
PythonCall.Core.pydel!Function
pydel!(x::Py)

Delete the Python object x.

DANGER! Use this function ONLY IF the Julia object x could have been garbage-collected anyway, i.e. was about to become unreachable. This means you MUST KNOW that no other part of the program has the Julia object x.

This decrements the reference count, sets the pointer to NULL and appends x to a cache of unused objects (PYNULL_CACHE).

This is an optimization to avoid excessive allocation and deallocation in Julia, which can be a significant source of slow-down in code which uses a lot of Python objects. It allows pynew() to pop an item from PYNULL_CACHE instead of allocating one, and avoids calling the relatively slow finalizer on x.

source
diff --git a/dev/pythoncall/index.html b/dev/pythoncall/index.html index e952c08f..c7e6e700 100644 --- a/dev/pythoncall/index.html +++ b/dev/pythoncall/index.html @@ -123,4 +123,4 @@ end

or even cache the imported function

module MyModule
   using PythonCall
   bar() = @pyconst(pyimport("foo").bar)()
-end

Dependencies

If your package depends on some Python packages, you must generate a CondaPkg.toml file. See Installing Python packages.

+end

Dependencies

If your package depends on some Python packages, you must generate a CondaPkg.toml file. See Installing Python packages.

diff --git a/dev/releasenotes/index.html b/dev/releasenotes/index.html index 0a3bf36c..db7a6546 100644 --- a/dev/releasenotes/index.html +++ b/dev/releasenotes/index.html @@ -1,2 +1,2 @@ -Release Notes · PythonCall & JuliaCall

Release Notes

0.9.21 (2024-07-20)

  • Serialization.serialize can use dill instead of pickle by setting the env var JULIA_PYTHONCALL_PICKLE=dill.
  • numpy.bool_ can now be converted to Bool and other number types.
  • datetime.timedelta can now be converted to Dates.Nanosecond, Microsecond, Millisecond and Second. This behaviour was already documented.
  • In JuliaCall, the Julia runtime is now properly terminated when Python exits. This means all finalizers should always run.
  • NULL Python objects (such as from pynew()) can be safely displayed in multimedia contexts (VSCode/Pluto/etc.)

0.9.20 (2024-05-01)

  • The IPython extension is now automatically loaded upon import if IPython is detected.
  • JuliaCall now compatible with Julia 1.10.3.
  • Minimum supported Python version is now 3.8.

0.9.19 (2024-03-19)

  • Bug fixes.

0.9.18 (2024-03-18)

  • Bug fixes.

0.9.17 (2024-03-16)

  • Bug fixes.

0.9.16 (2024-03-14)

  • Big internal refactor.
  • New unexported functions: python_executable_path, python_library_path, python_library_handle and python_version.
  • Py is now treated as a scalar when broadcasting.
  • PyArray is now serializable.
  • Removed compatibility with Julia 1.10.1 and 1.10.2 (to be fixed in 1.10.3 and 1.11.0) due to an upstream bug.
  • Bug fixes.

0.9.15 (2023-10-25)

  • JuliaCall now supports -X juliacall-startup-file=no to disable running startup.jl.
  • If you are using CondaPkg then Python can optionally now be installed from the anaconda channel (instead of only conda-forge).
  • Bug fixes.

0.9.14 (2023-07-26)

  • Wrapped Julia values support truthiness (__bool__) better: all values are true, except for zero numbers and empty arrays, dicts and sets.
  • JuliaCall now supports the Julia --handle-signals option. Setting this to yes allows allocating multithreaded Julia code to be called from JuliaCall without segfaulting. The default is no while compatibility concerns are investigated, and may be changed to yes in a future release.

0.9.13 (2023-05-14)

  • Conversion to wrapper types PyList, PySet, PyDict or PyIterable now default to having element type Any instead of Py.
  • The __repr__ method of wrapped Julia objects now uses the 3-arg show method for nicer (richer and truncated) display at the Python REPL.
  • The IPython extension can now be loaded as just %load_ext juliacall.
  • The %%julia IPython magic can now synchronise variables between Python and Julia.
  • Bug fixes.

0.9.12 (2023-02-28)

  • Bug fixes.

0.9.11 (2023-02-15)

  • In PyArray{T}(x), the eltype T no longer needs to exactly match the stored data type. If x has numeric elements, then any number type T is allowed. If x has string elements, then any string type T is allowed.
  • StaticString (the inline string type used by PyArray) supports the AbstractString interface better.

0.9.10 (2022-12-02)

  • Bug fixes.

0.9.9 (2022-10-20)

  • Bug fixes.

0.9.8 (2022-10-18)

  • Adds line_buffering option to PyIO.
  • Improvements to stdout when using juliacall.ipython including line-buffering.

0.9.7 (2022-10-11)

  • If CondaPkg is using the Null backend, PythonCall will now use python from the PATH.
  • Bug fixes.

0.9.6 (2022-09-09)

  • When using JuliaCall from an interactive Python session, Julia is put into interactive mode: isinteractive() is true, InteractiveUtils is loaded, and a nicer display is used.
  • Wrapped Julia values now truncate their output when displayed via _repr_mimebundle_.
  • Numpy arrays with structured dtypes can now be converted to PyArray, provided the fields are aligned.
  • Python named tuples can be converted to Julia named tuples.
  • Bug fixes.

0.9.5 (2022-08-19)

  • Adds PythonCall.GC.disable() and PythonCall.GC.enable().
  • Experimental new function juliacall.interactive() allows the Julia async event loop to run in the background of the Python REPL.
  • Experimental new IPython extension juliacall.ipython providing the %julia and %%julia magics for executing Julia code.
  • Experimental new module juliacall.importer allowing you to write Python modules in Julia.
  • Bug fixes.

0.9.4 (2022-07-26)

  • Bug fixes.

0.9.3 (2022-07-02)

  • Bug fixes.

0.9.2 (2022-07-02)

  • Many Julia CLI options (such sysimage or number of threads) can be set from JuliaCall.
  • Bug fixes.

0.9.1 (2022-06-18)

  • PyArray can be constructed using the __array_struct__ part of the Numpy array interface. Constructing PyArray(x) is now about 50x faster, or 175x faster if you fully specify the type.
  • JuliaCall can now be imported on Apple M1.

0.9.0 (2022-05-27)

  • Breaking. Removes getpy: you may now overload Py directly, which now need not always return a new object (e.g. for singletons or wrappers).
  • Breaking. Conversion rules no longer take a new object every time.
  • Breaking. Improved Tables-interface support for PyPandasDataFrame: better inferred column types; better handling of non-string column names; columns are usually wrappers (PyArray or PyList). Constructor arguments have changed. Dict methods have been removed (basically only the Tables interface is supported).
  • Breaking. A Py which is convertible to PyTable is no longer considered to be a table itself; you must convert explicitly.
  • Adds pyhasitem and 3-arg pygetitem.
  • Extends Base.get, Base.get!, Base.haskey and 2-arg Base.hash for Py.
  • PyArray can now have any element type when the underlying array is of Python objects.
  • Adds ArrayValue.to_numpy().
  • Bug fixes.

v0.8.0 (2022-03-17)

  • Breaking: Removes pymethod and pyclass. In the future, pyclass may become sugar for types.new_class (namely you can specify a metaclass).
  • Adds pyfunc, pyclassmethod, pystaticmethod and pyproperty.
  • pyconvert_add_rule is now documented. Its semantics have changed, including the separator of the first argument from / to :.
  • A pandas <NA> value is now converted to missing.
  • A NaN in a PyPandasDataFrame is converted to missing.
  • Breaking: Removes using and As from JuliaCall.
  • Adds convert to JuliaCall (replacing As).
  • Bug fixes.

v0.6.1 (2022-02-21)

  • Conversions from simple ctypes types, e.g. ctypes.c_float to Cfloat.
  • Conversions from simple numpy types, e.g. numpy.float32 to Float32.
  • Bug fixes.

v0.6.0 (2022-02-17)

  • Breaking: JuliaCall now uses JuliaPkg to manage Julia dependencies.
  • Bug fixes.

v0.5.1 (2022-01-24)

  • Bug fixes.

v0.5.0 (2021-12-11)

  • Breaking: PythonCall now uses CondaPkg to manage Python dependencies.
  • Python objects can be shared with PyCall provided it uses the same interpreter, using methods PythonCall.Py(::PyCall.PyObject) and PyCall.PyObject(::PythonCall.Py).
  • Adds PythonDisplay which displays objects by printing to Python's sys.stdout. Used automatically in IPython in addition to IPythonDisplay.
  • Removes the GLOBAL mode from @pyexec. Use global in the code instead.
  • Bug fixes.
+Release Notes · PythonCall & JuliaCall

Release Notes

Unreleased

  • Finalizers are now thread-safe, meaning PythonCall now works in the presence of multi-threaded Julia code. Previously, tricks such as disabling the garbage collector were required. Python code must still be called on the main thread.
  • GC.disable() and GC.enable() are now a no-op and deprecated since they are no longer required for thread-safety. These will be removed in v1.
  • Adds GC.gc().

0.9.21 (2024-07-20)

  • Serialization.serialize can use dill instead of pickle by setting the env var JULIA_PYTHONCALL_PICKLE=dill.
  • numpy.bool_ can now be converted to Bool and other number types.
  • datetime.timedelta can now be converted to Dates.Nanosecond, Microsecond, Millisecond and Second. This behaviour was already documented.
  • In JuliaCall, the Julia runtime is now properly terminated when Python exits. This means all finalizers should always run.
  • NULL Python objects (such as from pynew()) can be safely displayed in multimedia contexts (VSCode/Pluto/etc.)

0.9.20 (2024-05-01)

  • The IPython extension is now automatically loaded upon import if IPython is detected.
  • JuliaCall now compatible with Julia 1.10.3.
  • Minimum supported Python version is now 3.8.

0.9.19 (2024-03-19)

  • Bug fixes.

0.9.18 (2024-03-18)

  • Bug fixes.

0.9.17 (2024-03-16)

  • Bug fixes.

0.9.16 (2024-03-14)

  • Big internal refactor.
  • New unexported functions: python_executable_path, python_library_path, python_library_handle and python_version.
  • Py is now treated as a scalar when broadcasting.
  • PyArray is now serializable.
  • Removed compatibility with Julia 1.10.1 and 1.10.2 (to be fixed in 1.10.3 and 1.11.0) due to an upstream bug.
  • Bug fixes.

0.9.15 (2023-10-25)

  • JuliaCall now supports -X juliacall-startup-file=no to disable running startup.jl.
  • If you are using CondaPkg then Python can optionally now be installed from the anaconda channel (instead of only conda-forge).
  • Bug fixes.

0.9.14 (2023-07-26)

  • Wrapped Julia values support truthiness (__bool__) better: all values are true, except for zero numbers and empty arrays, dicts and sets.
  • JuliaCall now supports the Julia --handle-signals option. Setting this to yes allows allocating multithreaded Julia code to be called from JuliaCall without segfaulting. The default is no while compatibility concerns are investigated, and may be changed to yes in a future release.

0.9.13 (2023-05-14)

  • Conversion to wrapper types PyList, PySet, PyDict or PyIterable now default to having element type Any instead of Py.
  • The __repr__ method of wrapped Julia objects now uses the 3-arg show method for nicer (richer and truncated) display at the Python REPL.
  • The IPython extension can now be loaded as just %load_ext juliacall.
  • The %%julia IPython magic can now synchronise variables between Python and Julia.
  • Bug fixes.

0.9.12 (2023-02-28)

  • Bug fixes.

0.9.11 (2023-02-15)

  • In PyArray{T}(x), the eltype T no longer needs to exactly match the stored data type. If x has numeric elements, then any number type T is allowed. If x has string elements, then any string type T is allowed.
  • StaticString (the inline string type used by PyArray) supports the AbstractString interface better.

0.9.10 (2022-12-02)

  • Bug fixes.

0.9.9 (2022-10-20)

  • Bug fixes.

0.9.8 (2022-10-18)

  • Adds line_buffering option to PyIO.
  • Improvements to stdout when using juliacall.ipython including line-buffering.

0.9.7 (2022-10-11)

  • If CondaPkg is using the Null backend, PythonCall will now use python from the PATH.
  • Bug fixes.

0.9.6 (2022-09-09)

  • When using JuliaCall from an interactive Python session, Julia is put into interactive mode: isinteractive() is true, InteractiveUtils is loaded, and a nicer display is used.
  • Wrapped Julia values now truncate their output when displayed via _repr_mimebundle_.
  • Numpy arrays with structured dtypes can now be converted to PyArray, provided the fields are aligned.
  • Python named tuples can be converted to Julia named tuples.
  • Bug fixes.

0.9.5 (2022-08-19)

  • Adds PythonCall.GC.disable() and PythonCall.GC.enable().
  • Experimental new function juliacall.interactive() allows the Julia async event loop to run in the background of the Python REPL.
  • Experimental new IPython extension juliacall.ipython providing the %julia and %%julia magics for executing Julia code.
  • Experimental new module juliacall.importer allowing you to write Python modules in Julia.
  • Bug fixes.

0.9.4 (2022-07-26)

  • Bug fixes.

0.9.3 (2022-07-02)

  • Bug fixes.

0.9.2 (2022-07-02)

  • Many Julia CLI options (such sysimage or number of threads) can be set from JuliaCall.
  • Bug fixes.

0.9.1 (2022-06-18)

  • PyArray can be constructed using the __array_struct__ part of the Numpy array interface. Constructing PyArray(x) is now about 50x faster, or 175x faster if you fully specify the type.
  • JuliaCall can now be imported on Apple M1.

0.9.0 (2022-05-27)

  • Breaking. Removes getpy: you may now overload Py directly, which now need not always return a new object (e.g. for singletons or wrappers).
  • Breaking. Conversion rules no longer take a new object every time.
  • Breaking. Improved Tables-interface support for PyPandasDataFrame: better inferred column types; better handling of non-string column names; columns are usually wrappers (PyArray or PyList). Constructor arguments have changed. Dict methods have been removed (basically only the Tables interface is supported).
  • Breaking. A Py which is convertible to PyTable is no longer considered to be a table itself; you must convert explicitly.
  • Adds pyhasitem and 3-arg pygetitem.
  • Extends Base.get, Base.get!, Base.haskey and 2-arg Base.hash for Py.
  • PyArray can now have any element type when the underlying array is of Python objects.
  • Adds ArrayValue.to_numpy().
  • Bug fixes.

v0.8.0 (2022-03-17)

  • Breaking: Removes pymethod and pyclass. In the future, pyclass may become sugar for types.new_class (namely you can specify a metaclass).
  • Adds pyfunc, pyclassmethod, pystaticmethod and pyproperty.
  • pyconvert_add_rule is now documented. Its semantics have changed, including the separator of the first argument from / to :.
  • A pandas <NA> value is now converted to missing.
  • A NaN in a PyPandasDataFrame is converted to missing.
  • Breaking: Removes using and As from JuliaCall.
  • Adds convert to JuliaCall (replacing As).
  • Bug fixes.

v0.6.1 (2022-02-21)

  • Conversions from simple ctypes types, e.g. ctypes.c_float to Cfloat.
  • Conversions from simple numpy types, e.g. numpy.float32 to Float32.
  • Bug fixes.

v0.6.0 (2022-02-17)

  • Breaking: JuliaCall now uses JuliaPkg to manage Julia dependencies.
  • Bug fixes.

v0.5.1 (2022-01-24)

  • Bug fixes.

v0.5.0 (2021-12-11)

  • Breaking: PythonCall now uses CondaPkg to manage Python dependencies.
  • Python objects can be shared with PyCall provided it uses the same interpreter, using methods PythonCall.Py(::PyCall.PyObject) and PyCall.PyObject(::PythonCall.Py).
  • Adds PythonDisplay which displays objects by printing to Python's sys.stdout. Used automatically in IPython in addition to IPythonDisplay.
  • Removes the GLOBAL mode from @pyexec. Use global in the code instead.
  • Bug fixes.
diff --git a/dev/search_index.js b/dev/search_index.js index fb7fb720..eb333ccd 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"pythoncall/#The-Julia-module-PythonCall","page":"Guide","title":"The Julia module PythonCall","text":"","category":"section"},{"location":"pythoncall/#Installation","page":"Guide","title":"Installation","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"This package is in the general registry, so to install just type ] in the Julia REPL and run:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"pkg> add PythonCall","category":"page"},{"location":"pythoncall/#Getting-started","page":"Guide","title":"Getting started","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Import the module with:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> using PythonCall","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"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. See here to configure which Python to use.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Now you can interact with Python as follows:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> re = pyimport(\"re\")\nPython: \n\njulia> words = re.findall(\"[a-zA-Z]+\", \"PythonCall.jl is very useful!\")\nPython: ['PythonCall', 'jl', 'is', 'very', 'useful']\n\njulia> sentence = Py(\" \").join(words)\nPython: 'PythonCall jl is very useful'\n\njulia> pyconvert(String, sentence)\n\"PythonCall jl is very useful\"","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"In this example:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"We used pyimport to import the re module.\nWe called its findall function on a pair of strings, which were automatically converted to Python strings (see Conversion to Python).\nWe 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.\nWe called pyconvert to convert the Python string sentence to a Julia string (see Conversion to Julia).","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The values re, words and sentence in the example are all Python objects, which have type Py in Julia. As we have seen, these objects support attribute access (e.g. re.findall) and function calls (e.g. join(words)). They also support indexing, comparison and arithmetic:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pylist([3, 4, 5])\nPython: [3, 4, 5]\n\njulia> x[2] == 5\nPython: True\n\njulia> x[pyslice(0,2)] + pylist([1,2])\nPython: [3, 4, 1, 2]","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"We have just seen the functions pylist (for constructing a Python list) and pyslice (for constructing a Python slice). There are many such functions, mirroring most of the Python builtin functions and types. The API Reference documents them all.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Most of these functions 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.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Notable exceptions are:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"pyconvert to convert a Python object to a Julia object.\npyimport to import a Python module.\npyjl to directly wrap a Julia object as a Python object.\npywith to emulate the Python with statement.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"To access the Python builtins directly, you can access the fields of pybuiltins:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> pybuiltins.None\nPython: None\n\njulia> pybuiltins.True\nPython: True\n\njulia> pybuiltins.ValueError(\"some error\")\nPython: ValueError('some error')","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"With the functions introduced so far, you have access to the vast majority of Python's functionality.","category":"page"},{"location":"pythoncall/#Conversion-between-Julia-and-Python","page":"Guide","title":"Conversion between Julia and Python","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"A Julia object can be converted to a Python one either explicitly (such as Py(x)) or implicitly (such as the arguments when calling a Python function). Either way, it follows the default conversion rules here.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Most operations involving Python objects will return a Py and are not automatically converted to another Julia type. Instead, you can explicitly convert using pyconvert:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pylist([3.4, 5.6])\nPython: [3.4, 5.6]\n\njulia> pyconvert(Vector, x)\n2-element Vector{Float64}:\n 3.4\n 5.6\n\njulia> pyconvert(Vector{Float32}, x)\n2-element Vector{Float32}:\n 3.4\n 5.6\n\njulia> pyconvert(Any, x)\n2-element PyList{Any}:\n 3.4\n 5.6","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"In the above example, we converted a Python list to a Julia vector in three ways.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"pyconvert(Vector, x) returned a Vector{Float64} since all the list items are floats.\npyconvert(Vector{Float32}, x) specified the element type, so the floats were converted to Float32.\npyconvert(Any, x) returned a PyList{Py} which is a no-copy wrapper around the original list x, viewing it as a AbstractVector{Py}. Since it is a wrapper, mutating it mutates x and vice-versa.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See here for the rules regarding how pyconvert(T, x) works. If x is an immutable scalar type (such as an int or str) then pyconvert(Any, x) may return the corresponding Julia object (such as an Integer or String). Otherwise it will typically return either a wrapper type (such as PyList{Py} in the above example) or will fall back to returning a Py.","category":"page"},{"location":"pythoncall/#py-wrappers","page":"Guide","title":"Wrapper types","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"A wrapper is a type which wraps a Python object but provides it with the semantics of some other Julia type.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Since it is merely wrapping a Python object, if you mutate the wrapper you also mutate the wrapped object, and vice versa.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See here for details of all the wrapper types provided by PythonCall.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"We have already seen PyList. It wraps any Python sequence (such as a list) as a Julia vector:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pylist([3,4,5])\nPython: [3, 4, 5]\n\njulia> y = PyList{Union{Int,Nothing}}(x)\n3-element PyList{Union{Nothing, Int64}}:\n 3\n 4\n 5\n\njulia> push!(y, nothing)\n4-element PyList{Union{Nothing, Int64}}:\n 3\n 4\n 5\n nothing\n\njulia> append!(y, 1:2)\n6-element PyList{Union{Nothing, Int64}}:\n 3\n 4\n 5\n nothing\n 1\n 2\n\njulia> x\nPython: [3, 4, 5, None, 1, 2]","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"There are wrappers for other container types, such as PyDict and PySet.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The wrapper PyArray provides a Julia array view of any Python array, i.e. anything satisfying either the buffer protocol or the numpy array interface. This includes things like bytes, bytearray, array.array and numpy.ndarray:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pyimport(\"array\").array(\"i\", [3, 4, 5])\nPython: array('i', [3, 4, 5])\n\njulia> y = PyArray(x)\n3-element PyArray{Int32, 1, true, true, Int32}:\n 3\n 4\n 5\n\njulia> sum(y)\n12\n\njulia> y[1] = 0\n0\n\njulia> x\nPython: array('i', [0, 4, 5])","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"It directly wraps the underlying data buffer, so array operations such as indexing are about as fast as for an ordinary Array.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The PyIO wrapper type views a Python file object as a Julia IO object:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pyimport(\"io\").StringIO()\nPython: <_io.StringIO object at 0x000000006579BC70>\n\njulia> y = PyIO(x)\nPyIO(, false, true, false, 4096, UInt8[], 4096, UInt8[])\n\njulia> println(y, \"Hello, world!\")\n\njulia> flush(y)\n\njulia> x.seek(0)\nPython: 0\n\njulia> x.read()\nPython: 'Hello, world!\\n'","category":"page"},{"location":"pythoncall/#pythoncall-config","page":"Guide","title":"Configuration","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"By default, PythonCall uses CondaPkg.jl to manage its dependencies. This will install Conda and use it to create a Conda environment specific to your current Julia project containing Python and any required Python packages.","category":"page"},{"location":"pythoncall/#If-you-already-have-Python-and-required-Python-packages-installed","page":"Guide","title":"If you already have Python and required Python packages installed","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"ENV[\"JULIA_CONDAPKG_BACKEND\"] = \"Null\"\nENV[\"JULIA_PYTHONCALL_EXE\"] = \"/path/to/python\" # optional\nENV[\"JULIA_PYTHONCALL_EXE\"] = \"@PyCall\" # optional","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"By setting the CondaPkg backend to Null, it will never install any Conda packages. In this case, PythonCall will use whichever Python is currently installed and in your PATH. You must have already installed any Python packages that you need.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If python is not in your PATH, you will also need to set JULIA_PYTHONCALL_EXE to its path.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If you also use PyCall, you can set JULIA_PYTHONCALL_EXE=@PyCall to use the same Python interpreter.","category":"page"},{"location":"pythoncall/#If-you-already-have-a-Conda-environment","page":"Guide","title":"If you already have a Conda environment","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"ENV[\"JULIA_CONDAPKG_BACKEND\"] = \"Current\"\nENV[\"JULIA_CONDAPKG_EXE\"] = \"/path/to/conda\" # optional","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The Current backend to CondaPkg will use the currently activated Conda environment instead of creating a new one.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Note that this will still install any required Conda packages into your Conda environment. If you already have your dependencies installed and do not want the environment to be modified, then see the previous section.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If conda, mamba or micromamba is not in your PATH you will also need to set JULIA_CONDAPKG_EXE to its path.","category":"page"},{"location":"pythoncall/#If-you-already-have-Conda,-Mamba-or-MicroMamba","page":"Guide","title":"If you already have Conda, Mamba or MicroMamba","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"ENV[\"JULIA_CONDAPKG_BACKEND\"] = \"System\"\nENV[\"JULIA_CONDAPKG_EXE\"] = \"/path/to/conda\" # optional","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The System backend to CondaPkg will use your preinstalled Conda implementation instead of downloading one.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Note that this will still create a new Conda environment and install any required packages into it. If you want to use a pre-existing Conda environment, see the previous section.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If conda, mamba or micromamba is not in your PATH you will also need to set JULIA_CONDAPKG_EXE to its path.","category":"page"},{"location":"pythoncall/#python-deps","page":"Guide","title":"Installing Python packages","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Assuming you haven't opted out, PythonCall uses CondaPkg.jl to automatically install any required Python packages.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"This is as simple as","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> using CondaPkg\n\njulia> # press ] to enter the Pkg REPL\n\npkg> conda add some_package","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"This creates a CondaPkg.toml file in the active project specifying the dependencies, just like a Project.toml specifies Julia dependencies. Commit this file along with the rest of the project so that dependencies are automatically installed for everyone using it.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"To add dependencies to a Julia package, just ensure the package project is activated first.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See the CondaPkg.jl documentation.","category":"page"},{"location":"pythoncall/#Writing-packages-which-depend-on-PythonCall","page":"Guide","title":"Writing packages which depend on PythonCall","text":"","category":"section"},{"location":"pythoncall/#Example","page":"Guide","title":"Example","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See https://github.com/cjdoris/Faiss.jl for an example package which wraps the Python FAISS package.","category":"page"},{"location":"pythoncall/#Precompilation","page":"Guide","title":"Precompilation","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"You must not interact with Python during module precompilation. Therefore, instead of","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n const foo = pyimport(\"foo\")\n bar() = foo.bar() # will crash when called\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"you can do the import when the module is loaded, saving the result in a Ref","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n const foo = Ref{Py}()\n function __init__()\n foo[] = pyimport(\"foo\")\n end\n bar() = foo[].bar()\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"or you can perform any imports dynamically","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n bar() = pyimport(\"foo\").bar()\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"or if that is too slow, you can cache the import","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n bar() = @pyconst(pyimport(\"foo\")).bar()\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"or even cache the imported function","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n bar() = @pyconst(pyimport(\"foo\").bar)()\nend","category":"page"},{"location":"pythoncall/#Dependencies","page":"Guide","title":"Dependencies","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If your package depends on some Python packages, you must generate a CondaPkg.toml file. See Installing Python packages.","category":"page"},{"location":"juliacall-reference/#JuliaCall-API-Reference","page":"Reference","title":"JuliaCall API Reference","text":"","category":"section"},{"location":"juliacall-reference/#Constants","page":"Reference","title":"Constants","text":"","category":"section"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.Main - Constant\n\nThe Julia `Main` module, as a [`ModuleValue`](#juliacall.ModuleValue).\n\nIn interactive scripts, you can use this as the main entry-point to JuliaCall:\n```python\nfrom juliacall import Main as jl\njl.println(\"Hello, world!\")\n```\n\nIn packages, use [`newmodule`](#juliacall.newmodule) instead.","category":"page"},{"location":"juliacall-reference/#juliacall.Main","page":"Reference","title":"juliacall.Main","text":"The Julia Main module, as a ModuleValue.\n\nIn interactive scripts, you can use this as the main entry-point to JuliaCall:\n\nfrom juliacall import Main as jl\njl.println(\"Hello, world!\")\n\nIn packages, use newmodule instead.\n\n\n\n\n\n","category":"constant"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"The modules Base, Core and PythonCall are also available.","category":"page"},{"location":"juliacall-reference/#Utilities","page":"Reference","title":"Utilities","text":"","category":"section"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.convert - Function\n\n```python\nconvert(T, x)\n```\n\nConvert `x` to a Julia object of type `T`.\n\nYou can use this to pass an argument to a Julia function of a specific type.","category":"page"},{"location":"juliacall-reference/#juliacall.convert","page":"Reference","title":"juliacall.convert","text":"convert(T, x)\n\nConvert x to a Julia object of type T.\n\nYou can use this to pass an argument to a Julia function of a specific type.\n\n\n\n\n\n","category":"function"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.newmodule - Function\n\n```python\nnewmodule(name)\n```\n\nA new module with the given name.","category":"page"},{"location":"juliacall-reference/#juliacall.newmodule","page":"Reference","title":"juliacall.newmodule","text":"newmodule(name)\n\nA new module with the given name.\n\n\n\n\n\n","category":"function"},{"location":"juliacall-reference/#julia-wrappers","page":"Reference","title":"Wrapper types","text":"","category":"section"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"Apart from a few fundamental immutable types, all Julia values are by default converted into Python to some AnyValue object, which wraps the original value, but giving it a Pythonic interface.","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"Subclasses of AnyValue provide additional Python semantics. For example a Julia vector is converted to a VectorValue which satisfies the Python sequence interface and behaves very similar to a list.","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"There is also a RawValue object, which gives a stricter \"Julia-only\" interface, documented below. These types all inherit from ValueBase:","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"ValueBase\nRawValue\nAnyValue\nNumberValue\nComplexValue\nRealValue\nRationalValue\nIntegerValue\nArrayValue\nVectorValue\nDictValue\nSetValue\nIOValue\nBinaryIOValue\nTextIOValue\nModuleValue\nTypeValue","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.AnyValue - Class\n\nWraps any Julia object, giving it some basic Python semantics. Subtypes provide extra\nsemantics.\n\nSupports `repr(x)`, `str(x)`, attributes (`x.attr`), calling (`x(a,b)`), iteration,\ncomparisons, `len(x)`, `a in x`, `dir(x)`.\n\nCalling, indexing, attribute access, etc. will convert the result to a Python object\naccording to [this table](@ref jl2py). This is typically a builtin Python type (for\nimmutables) or a subtype of `AnyValue`.\n\nAttribute access can be used to access Julia properties as well as normal class members. In\nthe case of a name clash, the class member will take precedence. For convenience with Julia\nnaming conventions, `_b` at the end of an attribute is replaced with `!` and `_bb` is\nreplaced with `!!`.\n\n###### Members\n- `_jl_raw()`: Convert to a [`RawValue`](#juliacall.RawValue). (See also [`pyjlraw`](@ref).)\n- `_jl_display()`: Display the object using Julia's display mechanism.\n- `_jl_help()`: Display help for the object.","category":"page"},{"location":"juliacall-reference/#juliacall.AnyValue","page":"Reference","title":"juliacall.AnyValue","text":"Wraps any Julia object, giving it some basic Python semantics. Subtypes provide extra semantics.\n\nSupports repr(x), str(x), attributes (x.attr), calling (x(a,b)), iteration, comparisons, len(x), a in x, dir(x).\n\nCalling, indexing, attribute access, etc. will convert the result to a Python object according to this table. This is typically a builtin Python type (for immutables) or a subtype of AnyValue.\n\nAttribute access can be used to access Julia properties as well as normal class members. In the case of a name clash, the class member will take precedence. For convenience with Julia naming conventions, _b at the end of an attribute is replaced with ! and _bb is replaced with !!.\n\nMembers\n\n_jl_raw(): Convert to a RawValue. (See also pyjlraw.)\n_jl_display(): Display the object using Julia's display mechanism.\n_jl_help(): Display help for the object.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.NumberValue - Class\n\nThis wraps any Julia `Number` value. It is a subclass of `numbers.Number` and behaves\nsimilar to other Python numbers.\n\nThere are also subtypes `ComplexValue`, `RealValue`, `RationalValue`, `IntegerValue` which\nwrap values of the corresponding Julia types, and are subclasses of the corresponding\n`numbers` ABC.","category":"page"},{"location":"juliacall-reference/#juliacall.NumberValue","page":"Reference","title":"juliacall.NumberValue","text":"This wraps any Julia Number value. It is a subclass of numbers.Number and behaves similar to other Python numbers.\n\nThere are also subtypes ComplexValue, RealValue, RationalValue, IntegerValue which wrap values of the corresponding Julia types, and are subclasses of the corresponding numbers ABC.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.ArrayValue - Class\n\nThis wraps any Julia `AbstractArray` value. It is a subclass of\n`collections.abc.Collection`.\n\nIt supports zero-up indexing, and can be indexed with integers or slices. Slicing returns a\nview of the original array.\n\nIf the array is strided and its eltype is supported (i.e. `Bool`, `IntXX`, `UIntXX`,\n`FloatXX`, `Complex{FloatXX}`, `Ptr{Cvoid}` or `Tuple` or `NamedTuple` of these) then it\nsupports the buffer protocol and the numpy array interface. This means that\n`numpy.asarray(this)` will yield a view of the original array, so mutations are visible on\nthe original.\n\nOtherwise, the numpy `__array__` method is supported, and this returns an array of Python\nobjects converted from the contents of the array. In this case, `numpy.asarray(this)` is a\ncopy of the original array.\n\n###### Members\n- `ndim`: The number of dimensions.\n- `shape`: Tuple of lengths in each dimension.\n- `copy()`: A copy of the array.\n- `reshape(shape)`: A reshaped view of the array.\n- `to_numpy(dtype=None, copy=True, order=\"K\")`: Convert to a numpy array.","category":"page"},{"location":"juliacall-reference/#juliacall.ArrayValue","page":"Reference","title":"juliacall.ArrayValue","text":"This wraps any Julia AbstractArray value. It is a subclass of collections.abc.Collection.\n\nIt supports zero-up indexing, and can be indexed with integers or slices. Slicing returns a view of the original array.\n\nIf the array is strided and its eltype is supported (i.e. Bool, IntXX, UIntXX, FloatXX, Complex{FloatXX}, Ptr{Cvoid} or Tuple or NamedTuple of these) then it supports the buffer protocol and the numpy array interface. This means that numpy.asarray(this) will yield a view of the original array, so mutations are visible on the original.\n\nOtherwise, the numpy __array__ method is supported, and this returns an array of Python objects converted from the contents of the array. In this case, numpy.asarray(this) is a copy of the original array.\n\nMembers\n\nndim: The number of dimensions.\nshape: Tuple of lengths in each dimension.\ncopy(): A copy of the array.\nreshape(shape): A reshaped view of the array.\nto_numpy(dtype=None, copy=True, order=\"K\"): Convert to a numpy array.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.VectorValue - Class\n\nThis wraps any Julia `AbstractVector` value. It is a subclass of `juliacall.ArrayValue` and\n`collections.abc.MutableSequence` and behaves similar to a Python `list`.\n\n###### Members\n- `resize(size)`: Change the length of the vector.\n- `sort(reverse=False, key=None)`: Sort the vector in-place.\n- `reverse()`: Reverse the vector.\n- `clear()`: Empty the vector.\n- `insert(index, value)`: Insert the value at the given index.\n- `append(value)`: Append the value to the end of the vector.\n- `extend(values)`: Append the values to the end of the vector.\n- `pop(index=-1)`: Remove and return the item at the given index.\n- `remove(value)`: Remove the first item equal to the value.\n- `index(value)`: The index of the first item equal to the value.\n- `count(value)`: The number of items equal to the value.","category":"page"},{"location":"juliacall-reference/#juliacall.VectorValue","page":"Reference","title":"juliacall.VectorValue","text":"This wraps any Julia AbstractVector value. It is a subclass of juliacall.ArrayValue and collections.abc.MutableSequence and behaves similar to a Python list.\n\nMembers\n\nresize(size): Change the length of the vector.\nsort(reverse=False, key=None): Sort the vector in-place.\nreverse(): Reverse the vector.\nclear(): Empty the vector.\ninsert(index, value): Insert the value at the given index.\nappend(value): Append the value to the end of the vector.\nextend(values): Append the values to the end of the vector.\npop(index=-1): Remove and return the item at the given index.\nremove(value): Remove the first item equal to the value.\nindex(value): The index of the first item equal to the value.\ncount(value): The number of items equal to the value.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.DictValue - Class\nThis wraps any Julia `AbstractDict` value. It is a subclass of `collections.abc.Mapping` and\nbehaves similar to a Python `dict`.","category":"page"},{"location":"juliacall-reference/#juliacall.DictValue","page":"Reference","title":"juliacall.DictValue","text":"This wraps any Julia AbstractDict value. It is a subclass of collections.abc.Mapping and behaves similar to a Python dict.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.SetValue - Class\nThis wraps any Julia `AbstractSet` value. It is a subclass of `collections.abc.Set` and\nbehaves similar to a Python `set`.","category":"page"},{"location":"juliacall-reference/#juliacall.SetValue","page":"Reference","title":"juliacall.SetValue","text":"This wraps any Julia AbstractSet value. It is a subclass of collections.abc.Set and behaves similar to a Python set.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.IOValue - Class\n\nThis wraps any Julia `IO` value. It is a subclass of `io.IOBase` and behaves like Python\nfiles.\n\nThere are also subtypes `BinaryIOValue` and `TextIOValue`, which are subclasses of\n`io.BufferedIOBase` (buffered bytes) and `io.TextIOBase` (text).","category":"page"},{"location":"juliacall-reference/#juliacall.IOValue","page":"Reference","title":"juliacall.IOValue","text":"This wraps any Julia IO value. It is a subclass of io.IOBase and behaves like Python files.\n\nThere are also subtypes BinaryIOValue and TextIOValue, which are subclasses of io.BufferedIOBase (buffered bytes) and io.TextIOBase (text).\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.ModuleValue - Class\nThis wraps any Julia `Module` value.\n\nIt is the same as [`AnyValue`](#juliacall.AnyValue) except for one additional convenience\nmethod:\n- `seval([module=self], code)`: Evaluates the given code (a string) in the given module.","category":"page"},{"location":"juliacall-reference/#juliacall.ModuleValue","page":"Reference","title":"juliacall.ModuleValue","text":"This wraps any Julia Module value.\n\nIt is the same as AnyValue except for one additional convenience method:\n\nseval([module=self], code): Evaluates the given code (a string) in the given module.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.TypeValue - Class\n\nThis wraps any Julia `Type` value.\n\nIt is the same as [`AnyValue`](#juliacall.AnyValue) except that indexing is used to access\nJulia's \"curly\" syntax for specifying parametric types:\n\n```python\nfrom juliacall import Main as jl\n# equivalent to Vector{Int}() in Julia\njl.Vector[jl.Int]()\n```","category":"page"},{"location":"juliacall-reference/#juliacall.TypeValue","page":"Reference","title":"juliacall.TypeValue","text":"This wraps any Julia Type value.\n\nIt is the same as AnyValue except that indexing is used to access Julia's \"curly\" syntax for specifying parametric types:\n\nfrom juliacall import Main as jl\n# equivalent to Vector{Int}() in Julia\njl.Vector[jl.Int]()\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.RawValue - Class\n\nWraps any Julia value with a rigid interface suitable for generic programming.\n\nSupports `repr(x)`, `str(x)`, attributes (`x.attr`), calling (`x(a,b)`), `len(x)`, `dir(x)`.\n\nThis is very similar to [`AnyValue`](#juliacall.AnyValue) except that indexing, calling,\netc. will always return a `RawValue`.\n\nIndexing with a tuple corresponds to indexing in Julia with multiple values. To index with a\nsingle tuple, it will need to be wrapped in another tuple.\n\n###### Members\n- `_jl_any()`: Convert to a [`AnyValue`](#juliacall.AnyValue) (or subclass). (See also\n [`pyjl`](@ref).)","category":"page"},{"location":"juliacall-reference/#juliacall.RawValue","page":"Reference","title":"juliacall.RawValue","text":"Wraps any Julia value with a rigid interface suitable for generic programming.\n\nSupports repr(x), str(x), attributes (x.attr), calling (x(a,b)), len(x), dir(x).\n\nThis is very similar to AnyValue except that indexing, calling, etc. will always return a RawValue.\n\nIndexing with a tuple corresponds to indexing in Julia with multiple values. To index with a single tuple, it will need to be wrapped in another tuple.\n\nMembers\n\n_jl_any(): Convert to a AnyValue (or subclass). (See also pyjl.)\n\n\n\n\n\n","category":"class"},{"location":"conversion-to-python/#jl2py","page":"Julia to Python","title":"Conversion to Python","text":"","category":"section"},{"location":"conversion-to-python/#jl2py-conversion","page":"Julia to Python","title":"Conversion Rules","text":"","category":"section"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"The following table specifies the conversion rules used whenever converting a Julia object to a Python object.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"From Julia, this occurs explicitly with Py(x) or implicitly when passing Julia objects as the argument to a Python function. To avoid this automatic conversion, the user can convert objects explicitly, such as by calling pylist or pydict.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"From Python, this occurs when converting the return value of a Julia function.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"From To\nAny Python object type (Py, PyList, etc.) itself\nNothing, Missing None\nBool bool\nStandard integer (IntXX, UIntXX, BigInt) int\nStandard rational (Rational{T}, T a standard integer) fractions.Fraction\nStandard float (FloatXX) float\nStandard complex (Complex{T}, T a standard float) complex\nStandard string/char (String and SubString{String}, Char) str\nTuple tuple\nStandard integer range (AbstractRange{T}, T a standard integer) range\nDate, Time, DateTime (from Dates) date, time, datetime (from datetime)\nSecond, Millisecond, Microsecond, Nanosecond (from Dates) timedelta (from datetime)\nNumber juliacall.NumberValue, juliacall.ComplexValue, etc.\nAbstractArray juliacall.ArrayValue, juliacall.VectorValue\nAbstractDict juliacall.DictValue\nAbstractSet juliacall.SetValue\nIO juliacall.BufferedIOValue\nModule juliacall.ModuleValue\nType juliacall.TypeValue\nAnything else juliacall.AnyValue","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"See here for an explanation of the juliacall.*Value wrapper types.","category":"page"},{"location":"conversion-to-python/#jl2py-conversion-custom","page":"Julia to Python","title":"Custom rules","text":"","category":"section"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"You may define a new conversion rule for your new type T by overloading Py(::T).","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"If T is a wrapper type (such as PyList) where Py(x) simply returns the stored Python object, then also define ispy(::T) = true.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"PythonCall.ispy","category":"page"},{"location":"conversion-to-python/#PythonCall.Core.ispy","page":"Julia to Python","title":"PythonCall.Core.ispy","text":"ispy(x)\n\nTrue if x is a Python object.\n\nThis includes Py and Python wrapper types such as PyList.\n\n\n\n\n\n","category":"function"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"Alternatively, if you define a wrapper type (a subtype of juliacall.AnyValue) then you may instead define pyjltype(::T) to be that type.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"PythonCall.pyjltype","category":"page"},{"location":"conversion-to-python/#PythonCall.JlWrap.pyjltype","page":"Julia to Python","title":"PythonCall.JlWrap.pyjltype","text":"pyjltype(x)\n\nThe subtype of juliacall.AnyValue which the Julia object x is wrapped as by pyjl(x).\n\nOverload pyjltype(::T) to define a custom conversion for your type T.\n\n\n\n\n\n","category":"function"},{"location":"pycall/#Coming-from-PyCall/PyJulia?","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Another similar interface to Python is provided by PyCall.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"On this page, we give some tips for migrating between the two modules and a comparison.","category":"page"},{"location":"pycall/#Tips","page":"Coming from PyCall/PyJulia?","title":"Tips","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"You can use both PyCall and PythonCall in the same Julia session. This is platform-dependent:\nOn Unix (Linux, Mac, etc.) the Python interpreter used by PythonCall and PyCall must be the same (see below).\nOn Windows, it appears to be possible for PythonCall and PyCall to use different interpreters.\nTo force PythonCall to use the same Python interpreter as PyCall, set the environment variable JULIA_PYTHONCALL_EXE to \"@PyCall\". Note that this will opt out of automatic dependency management using CondaPkg.\nAlternatively, to force PyCall to use the same interpreter as PythonCall, set the environment variable PYTHON to PythonCall.python_executable_path() and then Pkg.build(\"PyCall\"). You will need to do this each time you change project, because PythonCall by default uses a different Python for each project.","category":"page"},{"location":"pycall/#Comparison","page":"Coming from PyCall/PyJulia?","title":"Comparison","text":"","category":"section"},{"location":"pycall/#Flexibility-of-conversion","page":"Coming from PyCall/PyJulia?","title":"Flexibility of conversion","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In PyCall you do convert(T, x) to convert the Python object x to a Julia T. In PythonCall you similarly do pyconvert(T, x).","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PythonCall supports far more combinations of types of T and x. For example convert(Vector, x) in PyCall requires x to be a sequence, whereas in PythonCall pyconvert(Vector, x) works if x is an iterable, an object supporting the buffer protocol (such as bytes) or an object supporting the numpy array interface (such as numpy.ndarray).","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Furthermore, pyconvert can be extended to support more types, whereas convert(Vector, x) cannot support more Python types.","category":"page"},{"location":"pycall/#Lossiness-of-conversion","page":"Coming from PyCall/PyJulia?","title":"Lossiness of conversion","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Both packages allow conversion of Julia values to Python: PyObject(x) in PyCall, Py(x) in PythonCall.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Whereas both packages convert numbers, booleans, tuples and strings to their Python counterparts, they differ in handling other types. For example PyCall converts AbstractVector to list whereas PythonCall converts AbstractVector to juliacall.VectorValue which is a sequence type directly wrapping the Julia value - this has the advantage that mutating the Python object also mutates the original Julia object.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Hence with PyCall the following does not mutate the original array x:","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"x = [\"foo\", \"bar\"]\nPyObject(x).append(\"baz\")\n@show x # --> [\"foo\", \"bar\"]","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"whereas with PythonCall the following does mutate x:","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"x = [\"foo\", \"bar\"]\nPy(x).append(\"baz\")\n@show x # --> [\"foo\", \"bar\", \"baz\"]","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In fact, PythonCall has the policy that any mutable object will by default be wrapped in this way, which not only preserves mutability but makes conversion faster for large containers since it does not require taking a copy of all the data.","category":"page"},{"location":"pycall/#Automatic-conversion","page":"Coming from PyCall/PyJulia?","title":"Automatic conversion","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In PyCall, most function calls, attribute accesses, indexing, etc. of Python object by default automatically convert their result to a Julia object. This means that the following","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"pyimport(\"sys\").modules[\"KEY\"] = \"VALUE\"","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"does not actually modify the modules dict because it was copied to a new Julia Dict. This was probably not intended, plus it wasted time copying the whole dictionary. Instead you must do","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"set!(pyimport(os).\"environ\", \"KEY\", \"VALUE\")","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In PythonCall, we don't do any such automatic conversion: we always return Py. This means that the first piece of code above does what you think.","category":"page"},{"location":"pycall/#Which-Python","page":"Coming from PyCall/PyJulia?","title":"Which Python","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PyCall uses some global installation of Python - typically the version of Python installed on the system or used by Conda.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PythonCall uses a separate Conda environment for each Julia environment/project/package and installs Python (and other Python packages) into that. This means that different Julia projects can maintain an isolated set of Python dependencies (including the Python version itself).","category":"page"},{"location":"pycall/#Corresponding-Python-packages","page":"Coming from PyCall/PyJulia?","title":"Corresponding Python packages","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PyCall has the corresponding Python package PyJulia for calling Julia from Python, and PythonCall similarly has JuliaCall.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"One difference is between them is their code size: PyJulia is a large package, whereas JuliaCall is very small, with most of the implementation being in PythonCall itself. The practical up-shot is that PythonCall/JuliaCall have very symmetric interfaces; for example they use identical conversion policies and have the same set of wrapper types available.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Note also that JuliaCall will use a separate Julia project for each virtual/conda environment. This means that different Python environments can maintain an isolated set of Julia dependencies, including the versions of Julia and PythonCall themselves.","category":"page"},{"location":"pycall/#Compatibility","page":"Coming from PyCall/PyJulia?","title":"Compatibility","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PyCall supports Julia 0.7+ and Python 2.7+, whereas PythonCall supports Julia 1.6.1+ and Python 3.8+. PyCall requires numpy to be installed, PythonCall doesn't (it provides the same fast array access through the buffer protocol and array interface).","category":"page"},{"location":"releasenotes/#Release-Notes","page":"Release Notes","title":"Release Notes","text":"","category":"section"},{"location":"releasenotes/#0.9.21-(2024-07-20)","page":"Release Notes","title":"0.9.21 (2024-07-20)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Serialization.serialize can use dill instead of pickle by setting the env var JULIA_PYTHONCALL_PICKLE=dill.\nnumpy.bool_ can now be converted to Bool and other number types.\ndatetime.timedelta can now be converted to Dates.Nanosecond, Microsecond, Millisecond and Second. This behaviour was already documented.\nIn JuliaCall, the Julia runtime is now properly terminated when Python exits. This means all finalizers should always run.\nNULL Python objects (such as from pynew()) can be safely displayed in multimedia contexts (VSCode/Pluto/etc.)","category":"page"},{"location":"releasenotes/#0.9.20-(2024-05-01)","page":"Release Notes","title":"0.9.20 (2024-05-01)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"The IPython extension is now automatically loaded upon import if IPython is detected.\nJuliaCall now compatible with Julia 1.10.3.\nMinimum supported Python version is now 3.8.","category":"page"},{"location":"releasenotes/#0.9.19-(2024-03-19)","page":"Release Notes","title":"0.9.19 (2024-03-19)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.18-(2024-03-18)","page":"Release Notes","title":"0.9.18 (2024-03-18)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.17-(2024-03-16)","page":"Release Notes","title":"0.9.17 (2024-03-16)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.16-(2024-03-14)","page":"Release Notes","title":"0.9.16 (2024-03-14)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Big internal refactor.\nNew unexported functions: python_executable_path, python_library_path, python_library_handle and python_version.\nPy is now treated as a scalar when broadcasting.\nPyArray is now serializable.\nRemoved compatibility with Julia 1.10.1 and 1.10.2 (to be fixed in 1.10.3 and 1.11.0) due to an upstream bug.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.15-(2023-10-25)","page":"Release Notes","title":"0.9.15 (2023-10-25)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"JuliaCall now supports -X juliacall-startup-file=no to disable running startup.jl.\nIf you are using CondaPkg then Python can optionally now be installed from the anaconda channel (instead of only conda-forge).\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.14-(2023-07-26)","page":"Release Notes","title":"0.9.14 (2023-07-26)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Wrapped Julia values support truthiness (__bool__) better: all values are true, except for zero numbers and empty arrays, dicts and sets.\nJuliaCall now supports the Julia --handle-signals option. Setting this to yes allows allocating multithreaded Julia code to be called from JuliaCall without segfaulting. The default is no while compatibility concerns are investigated, and may be changed to yes in a future release.","category":"page"},{"location":"releasenotes/#0.9.13-(2023-05-14)","page":"Release Notes","title":"0.9.13 (2023-05-14)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Conversion to wrapper types PyList, PySet, PyDict or PyIterable now default to having element type Any instead of Py.\nThe __repr__ method of wrapped Julia objects now uses the 3-arg show method for nicer (richer and truncated) display at the Python REPL.\nThe IPython extension can now be loaded as just %load_ext juliacall.\nThe %%julia IPython magic can now synchronise variables between Python and Julia.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.12-(2023-02-28)","page":"Release Notes","title":"0.9.12 (2023-02-28)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.11-(2023-02-15)","page":"Release Notes","title":"0.9.11 (2023-02-15)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"In PyArray{T}(x), the eltype T no longer needs to exactly match the stored data type. If x has numeric elements, then any number type T is allowed. If x has string elements, then any string type T is allowed.\nStaticString (the inline string type used by PyArray) supports the AbstractString interface better.","category":"page"},{"location":"releasenotes/#0.9.10-(2022-12-02)","page":"Release Notes","title":"0.9.10 (2022-12-02)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.9-(2022-10-20)","page":"Release Notes","title":"0.9.9 (2022-10-20)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.8-(2022-10-18)","page":"Release Notes","title":"0.9.8 (2022-10-18)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Adds line_buffering option to PyIO.\nImprovements to stdout when using juliacall.ipython including line-buffering.","category":"page"},{"location":"releasenotes/#0.9.7-(2022-10-11)","page":"Release Notes","title":"0.9.7 (2022-10-11)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"If CondaPkg is using the Null backend, PythonCall will now use python from the PATH.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.6-(2022-09-09)","page":"Release Notes","title":"0.9.6 (2022-09-09)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"When using JuliaCall from an interactive Python session, Julia is put into interactive mode: isinteractive() is true, InteractiveUtils is loaded, and a nicer display is used.\nWrapped Julia values now truncate their output when displayed via _repr_mimebundle_.\nNumpy arrays with structured dtypes can now be converted to PyArray, provided the fields are aligned.\nPython named tuples can be converted to Julia named tuples.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.5-(2022-08-19)","page":"Release Notes","title":"0.9.5 (2022-08-19)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Adds PythonCall.GC.disable() and PythonCall.GC.enable().\nExperimental new function juliacall.interactive() allows the Julia async event loop to run in the background of the Python REPL.\nExperimental new IPython extension juliacall.ipython providing the %julia and %%julia magics for executing Julia code.\nExperimental new module juliacall.importer allowing you to write Python modules in Julia.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.4-(2022-07-26)","page":"Release Notes","title":"0.9.4 (2022-07-26)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.3-(2022-07-02)","page":"Release Notes","title":"0.9.3 (2022-07-02)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.2-(2022-07-02)","page":"Release Notes","title":"0.9.2 (2022-07-02)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Many Julia CLI options (such sysimage or number of threads) can be set from JuliaCall.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.1-(2022-06-18)","page":"Release Notes","title":"0.9.1 (2022-06-18)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"PyArray can be constructed using the __array_struct__ part of the Numpy array interface. Constructing PyArray(x) is now about 50x faster, or 175x faster if you fully specify the type.\nJuliaCall can now be imported on Apple M1.","category":"page"},{"location":"releasenotes/#0.9.0-(2022-05-27)","page":"Release Notes","title":"0.9.0 (2022-05-27)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking. Removes getpy: you may now overload Py directly, which now need not always return a new object (e.g. for singletons or wrappers).\nBreaking. Conversion rules no longer take a new object every time.\nBreaking. Improved Tables-interface support for PyPandasDataFrame: better inferred column types; better handling of non-string column names; columns are usually wrappers (PyArray or PyList). Constructor arguments have changed. Dict methods have been removed (basically only the Tables interface is supported).\nBreaking. A Py which is convertible to PyTable is no longer considered to be a table itself; you must convert explicitly.\nAdds pyhasitem and 3-arg pygetitem.\nExtends Base.get, Base.get!, Base.haskey and 2-arg Base.hash for Py.\nPyArray can now have any element type when the underlying array is of Python objects.\nAdds ArrayValue.to_numpy().\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.8.0-(2022-03-17)","page":"Release Notes","title":"v0.8.0 (2022-03-17)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking: Removes pymethod and pyclass. In the future, pyclass may become sugar for types.new_class (namely you can specify a metaclass).\nAdds pyfunc, pyclassmethod, pystaticmethod and pyproperty.\npyconvert_add_rule is now documented. Its semantics have changed, including the separator of the first argument from / to :.\nA pandas value is now converted to missing.\nA NaN in a PyPandasDataFrame is converted to missing.\nBreaking: Removes using and As from JuliaCall.\nAdds convert to JuliaCall (replacing As).\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.6.1-(2022-02-21)","page":"Release Notes","title":"v0.6.1 (2022-02-21)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Conversions from simple ctypes types, e.g. ctypes.c_float to Cfloat.\nConversions from simple numpy types, e.g. numpy.float32 to Float32.\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.6.0-(2022-02-17)","page":"Release Notes","title":"v0.6.0 (2022-02-17)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking: JuliaCall now uses JuliaPkg to manage Julia dependencies.\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.5.1-(2022-01-24)","page":"Release Notes","title":"v0.5.1 (2022-01-24)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#v0.5.0-(2021-12-11)","page":"Release Notes","title":"v0.5.0 (2021-12-11)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking: PythonCall now uses CondaPkg to manage Python dependencies.\nPython objects can be shared with PyCall provided it uses the same interpreter, using methods PythonCall.Py(::PyCall.PyObject) and PyCall.PyObject(::PythonCall.Py).\nAdds PythonDisplay which displays objects by printing to Python's sys.stdout. Used automatically in IPython in addition to IPythonDisplay.\nRemoves the GLOBAL mode from @pyexec. Use global in the code instead.\nBug fixes.","category":"page"},{"location":"conversion-to-julia/#py2jl","page":"Python to Julia","title":"Conversion to Julia","text":"","category":"section"},{"location":"conversion-to-julia/#py2jl-conversion","page":"Python to Julia","title":"Conversion Rules","text":"","category":"section"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"The following table specifies the conversion rules used whenever converting a Python object to a Julia object. 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.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"From Julia, one can convert Python objects to a desired type using pyconvert(T, x) for example.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"From Python, the arguments to a Julia function will be converted according to these rules with T=Any.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"From To\nTop priority (wrapped values). \njuliacall.AnyValue Any\nVery high priority (arrays). \nObjects satisfying the buffer or array interface (inc. bytes, bytearray, array.array, numpy.ndarray) PyArray\nHigh priority (canonical conversions). \nNone Nothing\nbool Bool\nnumbers.Integral (inc. int) Integer (prefers Int, or BigInt on overflow)\nfloat Float64\ncomplex Complex{Float64}\nrange StepRange\nstr String\ntuple Tuple\ncollections.abc.Mapping (inc. dict) PyDict\ncollections.abc.Sequence (inc. list) PyList\ncollections.abc.Set (inc. set, frozenset) PySet\nio.IOBase (includes open files) PyIO\nBaseException PyException\ndatetime.date/datetime.time/datetime.datetime Date/Time/DateTime\ndatetime.timedelta Microsecond (or Millisecond or Second on overflow)\nnumpy.intXX/numpy.uintXX/numpy.floatXX IntXX/UIntXX/FloatXX\nStandard priority (other reasonable conversions). \nNone Missing\nbytes Vector{UInt8}, Vector{Int8}, String\nstr String, Symbol, Char, Vector{UInt8}, Vector{Int8}\nrange UnitRange\ncollections.abc.Mapping Dict\ncollections.abc.Iterable Vector, Set, Tuple, NamedTuple, Pair\ndatetime.timedelta Dates.CompoundPeriod\nnumbers.Integral Integer, Rational, Real, Number\nnumbers.Real AbstractFloat, Number, Missing/Nothing (if NaN)\nnumbers.Complex Complex, Number\nctypes.c_int and other integers Integer, Rational, Real, Number\nctypes.c_float/ctypes.c_double Cfloat/Cdouble, AbstractFloat, Real, Number\nctypes.c_voidp Ptr{Cvoid}, Ptr\nctypes.c_char_p Cstring, Ptr{Cchar}, Ptr\nctypes.c_wchar_p Cwstring, Ptr{Cwchar}, Ptr\nnumpy.bool_/numpy.intXX/numpy.uintXX/numpy.floatXX Bool, Integer, Rational, Real, Number\nObjects satisfying the buffer or array interface Array, AbstractArray\nLow priority (fallback to Py). \nAnything Py\nBottom priority (must be explicitly specified by excluding Py). \nObjects satisfying the buffer interface PyBuffer\nAnything PyRef","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"See here for an explanation of the Py* wrapper types (PyList, PyIO, etc).","category":"page"},{"location":"conversion-to-julia/#py2jl-conversion-custom","page":"Python to Julia","title":"Custom rules","text":"","category":"section"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"To add a custom conversion rule, you must define a function to do the conversion and call pyconvert_add_rule to register it.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"You must not do this while precompiling, so these calls will normally be in the __init__ function of your module.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"PythonCall.pyconvert_add_rule","category":"page"},{"location":"conversion-to-julia/#PythonCall.Convert.pyconvert_add_rule","page":"Python to Julia","title":"PythonCall.Convert.pyconvert_add_rule","text":"pyconvert_add_rule(tname::String, T::Type, func::Function, priority::PyConvertPriority=PYCONVERT_PRIORITY_NORMAL)\n\nAdd a new conversion rule for pyconvert.\n\nArguments\n\ntname is a string of the form \"__module__:__qualname__\" identifying a Python type t, such as \"builtins:dict\" or \"sympy.core.symbol:Symbol\". This rule only applies to Python objects of this type.\nT is a Julia type, such that this rule only applies when the target type intersects with T.\nfunc is the function implementing the rule.\npriority determines whether to prioritise this rule above others.\n\nWhen pyconvert(R, x) is called, all rules such that typeintersect(T, R) != Union{} and pyisinstance(x, t) are considered. These rules are sorted first by priority, then by the specificity of t (e.g. bool is more specific than int is more specific than object) then by the order they were added. The rules are tried in turn until one succeeds.\n\nImplementing func\n\nfunc is called as func(S, x::Py) for some S <: T.\n\nIt must return one of:\n\npyconvert_return(ans) where ans is the result of the conversion (and must be an S).\npyconvert_unconverted() if the conversion was not possible (e.g. converting a list to Vector{Int} might fail if some of the list items are not integers).\n\nThe target type S is never a union or the empty type, i.e. it is always a data type or union-all.\n\nPriority\n\nMost rules should have priority PYCONVERT_PRIORITY_NORMAL (the default) which is for any reasonable conversion rule.\n\nUse priority PYCONVERT_PRIORITY_CANONICAL for canonical conversion rules. Immutable objects may be canonically converted to their corresponding Julia type, such as int to Integer. Mutable objects must be converted to a wrapper type, such that the original Python object can be retrieved. For example a list is canonically converted to PyList and not to a Vector. There should not be more than one canonical conversion rule for a given Python type.\n\nOther priorities are reserved for internal use.\n\n\n\n\n\n","category":"function"},{"location":"faq/#FAQ-and-Troubleshooting","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"","category":"section"},{"location":"faq/#Is-PythonCall/JuliaCall-thread-safe?","page":"FAQ & Troubleshooting","title":"Is PythonCall/JuliaCall thread safe?","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"No.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Some rules if you are writing multithreaded code:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Only call Python functions from the first thread.\nYou probably also need to call PythonCall.GC.disable() on the main thread before any threaded block of code. Remember to call PythonCall.GC.enable() again afterwards. (This is because Julia finalizers can be called from any thread.)\nJulia intentionally causes segmentation faults as part of the GC safepoint mechanism. If unhandled, these segfaults will result in termination of the process. To enable signal handling, set PYTHON_JULIACALL_HANDLE_SIGNALS=yes before any calls to import juliacall. This is equivalent to starting julia with julia --handle-signals=yes, the default behavior in Julia. See discussion here for more information.\nYou may still encounter problems.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #201, #202","category":"page"},{"location":"faq/#Issues-when-Numpy-arrays-are-expected","page":"FAQ & Troubleshooting","title":"Issues when Numpy arrays are expected","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"When a Julia array is passed to Python, it is wrapped as a ArrayValue. This type satisfies the Numpy array interface and the buffer protocol, so can be used in most places where a numpy array is valid.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"However, some Python packages have functions which assume the input is an actual Numpy array. You may see errors such as:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"AttributeError: Julia: type Array has no field dtype","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"To fix this you can convert the array x to a Numpy array as follows","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Py(x).to_numpy()","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"If the array is being mutated, you will need to pass the argument copy=false.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #280","category":"page"},{"location":"faq/#Heap-corruption-when-using-PyTorch","page":"FAQ & Troubleshooting","title":"Heap corruption when using PyTorch","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"On some systems, you may see an error like the following when using torch and juliacall:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Python(65251,0x104cf8580) malloc: Heap corruption detected, free list is damaged at 0x600001c17280\n*** Incorrect guard value: 1903002876\nPython(65251,0x104cf8580) malloc: *** set a breakpoint in malloc_error_break to debug\n[1] 65251 abort ipython","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"A solution is to ensure that juliacall is imported before torch.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #215","category":"page"},{"location":"faq/#ccall-requires-the-compiler-error-when-importing-some-Python-libraries","page":"FAQ & Troubleshooting","title":"ccall requires the compiler error when importing some Python libraries","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"On some systems, you may see an error like the following when import e.g. matplotlib before juliacall:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"ERROR: `ccall` requires the compilerTraceback (most recent call last):\n File \"/home/dingraha/projects/pythoncall_import_error/run.py\", line 2, in \n from foo import Foo\n File \"/home/dingraha/projects/pythoncall_import_error/foo.py\", line 4, in \n import juliacall; jl = juliacall.newmodule(\"FooModule\")\n File \"/home/dingraha/projects/pythoncall_import_error/venv/lib/python3.9/site-packages/juliacall/__init__.py\", line 218, in \n init()\n File \"/home/dingraha/projects/pythoncall_import_error/venv/lib/python3.9/site-packages/juliacall/__init__.py\", line 214, in init\n raise Exception('PythonCall.jl did not start properly')\nException: PythonCall.jl did not start properly","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"The likely problem is that the \"other\" Python library (matplotlib, whatever) is loading the system libstdc++.so, which isn't compatible with the libstdc++.so that Julia ships with. Linux distributions with older libstdc++ versions seem more likely to suffer from this issue. The solution is to either:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"use a Linux distribution with a more recent libstdc++\nimport juliacall before the other Python library, so that Julia's libstdc++ is loaded\nuse a Python from a conda environment, which will have a newer libstdc++ that is compatible with Julia's","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #255","category":"page"},{"location":"faq/#Can-I-use-JuliaCall-to-run-Julia-inside-applications-with-embedded-Python?","page":"FAQ & Troubleshooting","title":"Can I use JuliaCall to run Julia inside applications with embedded Python?","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Yes, it may be possible. A good example of that is having Julia running inside the Python that is running inside Blender, as presented in this Discourse post. From the point that one has JuliaCall running inside Python, if it has access to the terminal, one can even launch a Julia REPL there, and if needed connect with VSCode Julia extension to it. The full Python script to install, launch JuliaCall, and launch a Julia REPL in Blender is here.","category":"page"},{"location":"pythoncall-reference/#py-reference","page":"Reference","title":"PythonCall API Reference","text":"","category":"section"},{"location":"pythoncall-reference/#Py-objects","page":"Reference","title":"Py objects","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Py\npybuiltins","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.Py","page":"Reference","title":"PythonCall.Core.Py","text":"Py(x)\n\nConvert x to a Python object, of type Py.\n\nConversion happens according to these rules.\n\nSuch an object supports attribute access (obj.attr), indexing (obj[idx]), calling (obj(arg1, arg2)), iteration (for x in obj), arithmetic (obj + obj2) and comparison (obj > obj2), among other things. These operations convert all their arguments to Py and return Py.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Core.pybuiltins","page":"Reference","title":"PythonCall.Core.pybuiltins","text":"pybuiltins\n\nAn object whose fields are the Python builtins, of type Py.\n\nFor example pybuiltins.None, pybuiltins.int, pybuiltins.ValueError.\n\n\n\n\n\n","category":"module"},{"location":"pythoncall-reference/#Constructors","page":"Reference","title":"Constructors","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions construct Python objects of builtin types from Julia values.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pybool\npycollist\npybytes\npycomplex\npydict\npyfloat\npyfrozenset\npyint\npylist\npyrange\npyrowlist\npyset\npyslice\npystr\npytuple","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pybool","page":"Reference","title":"PythonCall.Core.pybool","text":"pybool(x)\n\nConvert x to a Python bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycollist","page":"Reference","title":"PythonCall.Core.pycollist","text":"pycollist(x::AbstractArray)\n\nCreate a nested Python list-of-lists from the elements of x. For matrices, this is a list of columns.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pybytes","page":"Reference","title":"PythonCall.Core.pybytes","text":"pybytes(x)\n\nConvert x to a Python bytes.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycomplex","page":"Reference","title":"PythonCall.Core.pycomplex","text":"pycomplex(x=0.0)\npycomplex(re, im)\n\nConvert x to a Python complex, or create one from given real and imaginary parts.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydict","page":"Reference","title":"PythonCall.Core.pydict","text":"pydict(x)\npydict(; x...)\n\nConvert x to a Python dict. In the second form, the keys are strings.\n\nIf x is a Python object, this is equivalent to dict(x) in Python. Otherwise x must iterate over key-value pairs.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyfloat","page":"Reference","title":"PythonCall.Core.pyfloat","text":"pyfloat(x=0.0)\n\nConvert x to a Python float.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyfrozenset","page":"Reference","title":"PythonCall.Core.pyfrozenset","text":"pyfrozenset(x=())\n\nConvert x to a Python frozenset.\n\nIf x is a Python object, this is equivalent to frozenset(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyint","page":"Reference","title":"PythonCall.Core.pyint","text":"pyint(x=0)\n\nConvert x to a Python int.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylist","page":"Reference","title":"PythonCall.Core.pylist","text":"pylist(x=())\n\nConvert x to a Python list.\n\nIf x is a Python object, this is equivalent to list(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrange","page":"Reference","title":"PythonCall.Core.pyrange","text":"pyrange([[start], [stop]], [step])\n\nConstruct a Python range. Unspecified arguments default to None.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrowlist","page":"Reference","title":"PythonCall.Core.pyrowlist","text":"pyrowlist(x::AbstractArray)\n\nCreate a nested Python list-of-lists from the elements of x. For matrices, this is a list of rows.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyset","page":"Reference","title":"PythonCall.Core.pyset","text":"pyset(x=())\n\nConvert x to a Python set.\n\nIf x is a Python object, this is equivalent to set(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyslice","page":"Reference","title":"PythonCall.Core.pyslice","text":"pyslice([start], stop, [step])\n\nConstruct a Python slice. Unspecified arguments default to None.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pystr","page":"Reference","title":"PythonCall.Core.pystr","text":"pystr(x)\n\nConvert x to a Python str.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pytuple","page":"Reference","title":"PythonCall.Core.pytuple","text":"pytuple(x=())\n\nConvert x to a Python tuple.\n\nIf x is a Python object, this is equivalent to tuple(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Builtins","page":"Reference","title":"Builtins","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions mimic the Python builtin functions or keywords of the same name.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyall\npyany\npyascii\npycall\npycallable\npycompile\npycontains\npydelattr\npydelitem\npydir\npyeval\n@pyeval\npyexec\n@pyexec\npygetattr\npygetitem\npyhasattr\npyhasitem\npyhash\npyhelp\npyimport\npyin\npyis\npyisinstance\npyissubclass\npyiter\npylen\npynext\npyprint\npyrepr\npysetattr\npysetitem\npytype(::Any)\npywith","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pyall","page":"Reference","title":"PythonCall.Core.pyall","text":"pyall(x)\n\nEquivalent to all(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyany","page":"Reference","title":"PythonCall.Core.pyany","text":"pyany(x)\n\nEquivalent to any(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyascii","page":"Reference","title":"PythonCall.Core.pyascii","text":"pyascii(x)\n\nEquivalent to ascii(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycall","page":"Reference","title":"PythonCall.Core.pycall","text":"pycall(f, args...; kwargs...)\n\nCall the Python object f with the given arguments.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycallable","page":"Reference","title":"PythonCall.Core.pycallable","text":"pycallable(x)\n\nEquivalent to callable(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycompile","page":"Reference","title":"PythonCall.Core.pycompile","text":"pycompile(...)\n\nEquivalent to compile(...) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycontains","page":"Reference","title":"PythonCall.Core.pycontains","text":"pycontains(x, v)\n\nEquivalent to v in x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydelattr","page":"Reference","title":"PythonCall.Core.pydelattr","text":"pydelattr(x, k)\n\nEquivalent to delattr(x, k) or del x.k in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydelitem","page":"Reference","title":"PythonCall.Core.pydelitem","text":"pydelitem(x, k)\n\nEquivalent to delitem(x, k) or del x[k] in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydir","page":"Reference","title":"PythonCall.Core.pydir","text":"pydir(x)\n\nEquivalent to dir(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyeval","page":"Reference","title":"PythonCall.Core.pyeval","text":"pyeval([T=Py], code, globals, locals=nothing)\n\nEvaluate the given Python code, returning the result as a T.\n\nIf globals is a Module, then a persistent dict unique to that module is used.\n\nBy default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.\n\nSee also @pyeval.\n\nExamples\n\nThe following computes 1.1+2.2 in the Main module as a Float64:\n\npyeval(Float64, \"x+y\", Main, (x=1.1, y=2.2)) # returns 3.3\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.@pyeval","page":"Reference","title":"PythonCall.Core.@pyeval","text":"@pyeval [inputs =>] code [=> T]\n\nEvaluate the given code in a new local scope and return the answer as a T.\n\nThe global scope is persistent and unique to the current module.\n\nThe code must be a literal string or command.\n\nThe inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.\n\nExamples\n\nThe following computes 1.1+2.2 and returns a Float64:\n\n@pyeval (x=1.1, y=2.2) => `x+y` => Float64 # returns 3.3\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#PythonCall.Core.pyexec","page":"Reference","title":"PythonCall.Core.pyexec","text":"pyexec([T=Nothing], code, globals, locals=nothing)\n\nExecute the given Python code.\n\nIf globals is a Module, then a persistent dict unique to that module is used.\n\nBy default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.\n\nIf T==Nothing then returns nothing. Otherwise T must be a concrete NamedTuple type and the corresponding items from locals are extracted and returned.\n\nSee also @pyexec.\n\nExamples\n\nThe following computes 1.1+2.2 in the Main module as a Float64:\n\npyexec(@NamedTuple{ans::Float64}, \"ans=x+y\", Main, (x=1.1, y=2.2)) # returns (ans = 3.3,)\n\nMarking variables as global saves them into the module scope, so that they are available in subsequent invocations:\n\npyexec(\"global x; x=12\", Main)\npyeval(Int, \"x\", Main) # returns 12\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.@pyexec","page":"Reference","title":"PythonCall.Core.@pyexec","text":"@pyexec [inputs =>] code [=> outputs]\n\nExecute the given code in a new local scope.\n\nThe global scope is persistent and unique to the current module.\n\nThe code must be a literal string or command.\n\nThe inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.\n\nThe outputs is a tuple of outputs of the form x::T=v, meaning that v is extracted from locals, converted to T and assigned to x. Only x is required: T defaults to Py and v defaults to x.\n\nExamples\n\nThe following computes 1.1+2.2 and assigns its value to ans as a Float64:\n\n@pyexec (x=1.1, y=2.2) => `ans=x+y` => ans::Float64 # returns 3.3\n\nMarking variables as global saves them into the module scope, so that they are available in subsequent invocations:\n\n@pyexec `global x; x=12`\n@pyeval `x` => Int # returns 12\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#PythonCall.Core.pygetattr","page":"Reference","title":"PythonCall.Core.pygetattr","text":"pygetattr(x, k, [d])\n\nEquivalent to getattr(x, k) or x.k in Python.\n\nIf d is specified, it is returned if the attribute does not exist.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pygetitem","page":"Reference","title":"PythonCall.Core.pygetitem","text":"pygetitem(x, k, [d])\n\nEquivalent x[k] in Python.\n\nIf d is specified, it is returned if the item does not exist (i.e. if x[k] raises a KeyError or IndexError).\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhasattr","page":"Reference","title":"PythonCall.Core.pyhasattr","text":"pyhasattr(x, k)\n\nEquivalent to hasattr(x, k) in Python.\n\nTests if getattr(x, k) raises an AttributeError.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhasitem","page":"Reference","title":"PythonCall.Core.pyhasitem","text":"pyhasitem(x, k)\n\nTest if pygetitem(x, k) raises a KeyError or AttributeError.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhash","page":"Reference","title":"PythonCall.Core.pyhash","text":"pyhash(x)\n\nEquivalent to hash(x) in Python, converted to an Integer.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhelp","page":"Reference","title":"PythonCall.Core.pyhelp","text":"pyhelp([x])\n\nEquivalent to help(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimport","page":"Reference","title":"PythonCall.Core.pyimport","text":"pyimport(m)\npyimport(m => k)\npyimport(m => (k1, k2, ...))\npyimport(m1, m2, ...)\n\nImport a module m, or an attribute k, or a tuple of attributes.\n\nIf several arguments are given, return the results of importing each one in a tuple.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyin","page":"Reference","title":"PythonCall.Core.pyin","text":"pyin(v, x)\n\nEquivalent to v in x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyis","page":"Reference","title":"PythonCall.Core.pyis","text":"pyis(x, y)\n\nTrue if x and y are the same Python object. Equivalent to x is y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyisinstance","page":"Reference","title":"PythonCall.Core.pyisinstance","text":"pyisinstance(x, t)\n\nTest if x is of type t. Equivalent to isinstance(x, t) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyissubclass","page":"Reference","title":"PythonCall.Core.pyissubclass","text":"pyissubclass(s, t)\n\nTest if s is a subclass of t. Equivalent to issubclass(s, t) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyiter","page":"Reference","title":"PythonCall.Core.pyiter","text":"pyiter(x)\n\nEquivalent to iter(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylen","page":"Reference","title":"PythonCall.Core.pylen","text":"pylen(x)\n\nThe length of x. Equivalent to len(x) in Python, converted to an Integer.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pynext","page":"Reference","title":"PythonCall.Core.pynext","text":"pynext(x)\n\nEquivalent to next(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyprint","page":"Reference","title":"PythonCall.Core.pyprint","text":"pyprint(...)\n\nEquivalent to print(...) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrepr","page":"Reference","title":"PythonCall.Core.pyrepr","text":"pyrepr(x)\n\nEquivalent to repr(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pysetattr","page":"Reference","title":"PythonCall.Core.pysetattr","text":"pysetattr(x, k, v)\n\nEquivalent to setattr(x, k, v) or x.k = v in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pysetitem","page":"Reference","title":"PythonCall.Core.pysetitem","text":"pysetitem(x, k, v)\n\nEquivalent to setitem(x, k, v) or x[k] = v in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pytype-Tuple{Any}","page":"Reference","title":"PythonCall.Core.pytype","text":"pytype(x)\n\nThe Python type of x.\n\n\n\n\n\n","category":"method"},{"location":"pythoncall-reference/#PythonCall.Core.pywith","page":"Reference","title":"PythonCall.Core.pywith","text":"pywith(f, o, d=nothing)\n\nEquivalent to with o as x: f(x) in Python, where x is a Py.\n\nOn success, the value of f(x) is returned.\n\nIf an exception occurs but is suppressed then d is returned.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Conversion-to-Julia","page":"Reference","title":"Conversion to Julia","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions convert Python values to Julia values, using the rules documented here.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyconvert\n@pyconvert","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pyconvert","page":"Reference","title":"PythonCall.Core.pyconvert","text":"pyconvert(T, x, [d])\n\nConvert the Python object x to a T.\n\nIf d is specified, it is returned on failure instead of throwing an error.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Convert.@pyconvert","page":"Reference","title":"PythonCall.Convert.@pyconvert","text":"@pyconvert(T, x, [onfail])\n\nConvert the Python object x to a T.\n\nOn failure, evaluates to onfail, which defaults to return pyconvert_unconverted() (mainly useful for writing conversion rules).\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#Wrap-Julia-values","page":"Reference","title":"Wrap Julia values","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions explicitly wrap Julia values into Python objects, documented here.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"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.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyjl\npyjlraw\npyisjl\npyjlvalue\npybinaryio\npytextio","category":"page"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyjl","page":"Reference","title":"PythonCall.JlWrap.pyjl","text":"pyjl([t=pyjltype(x)], x)\n\nCreate a Python object wrapping the Julia object x.\n\nIf x is mutable, then mutating the returned object also mutates x, and vice versa.\n\nIts Python type is normally inferred from the type of x, but can be specified with t.\n\nFor 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.\n\nTo define a custom conversion for your type T, overload pyjltype(::T).\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyjlraw","page":"Reference","title":"PythonCall.JlWrap.pyjlraw","text":"pyjlraw(v)\n\nCreate a Python object wrapping the Julia object x.\n\nIt 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.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyisjl","page":"Reference","title":"PythonCall.JlWrap.pyisjl","text":"pyisjl(x)\n\nTest whether x is a wrapped Julia value, namely an instance of juliacall.ValueBase.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyjlvalue","page":"Reference","title":"PythonCall.JlWrap.pyjlvalue","text":"pyjlvalue(x)\n\nExtract the value from the wrapped Julia value x.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pybinaryio","page":"Reference","title":"PythonCall.JlWrap.pybinaryio","text":"pybinaryio(io::IO)\n\nWrap io as a Python binary IO object.\n\nThis is the default behaviour of Py(io).\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pytextio","page":"Reference","title":"PythonCall.JlWrap.pytextio","text":"pytextio(io::IO)\n\nWrap io as a Python text IO object.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Arithmetic","page":"Reference","title":"Arithmetic","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions are equivalent to the corresponding Python arithmetic operators.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"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.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyneg\npypos\npyabs\npyinv\npyindex\npyadd\npysub\npymul\npymatmul\npypow\npyfloordiv\npytruediv\npymod\npydivmod\npylshift\npyrshift\npyand\npyxor\npyor\npyiadd\npyisub\npyimul\npyimatmul\npyipow\npyifloordiv\npyitruediv\npyimod\npyilshift\npyirshift\npyiand\npyixor\npyior","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pyneg","page":"Reference","title":"PythonCall.Core.pyneg","text":"pyneg(x)\n\nEquivalent to -x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pypos","page":"Reference","title":"PythonCall.Core.pypos","text":"pypos(x)\n\nEquivalent to +x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyabs","page":"Reference","title":"PythonCall.Core.pyabs","text":"pyabs(x)\n\nEquivalent to abs(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyinv","page":"Reference","title":"PythonCall.Core.pyinv","text":"pyinv(x)\n\nEquivalent to ~x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyindex","page":"Reference","title":"PythonCall.Core.pyindex","text":"pyindex(x)\n\nConvert x losslessly to an int.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyadd","page":"Reference","title":"PythonCall.Core.pyadd","text":"pyadd(x, y)\n\nEquivalent to x + y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pysub","page":"Reference","title":"PythonCall.Core.pysub","text":"pysub(x, y)\n\nEquivalent to x - y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pymul","page":"Reference","title":"PythonCall.Core.pymul","text":"pymul(x, y)\n\nEquivalent to x * y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pymatmul","page":"Reference","title":"PythonCall.Core.pymatmul","text":"pymatmul(x, y)\n\nEquivalent to x @ y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pypow","page":"Reference","title":"PythonCall.Core.pypow","text":"pypow(x, y, z=None)\n\nEquivalent to x ** y or pow(x, y, z) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyfloordiv","page":"Reference","title":"PythonCall.Core.pyfloordiv","text":"pyfloordiv(x, y)\n\nEquivalent to x // y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pytruediv","page":"Reference","title":"PythonCall.Core.pytruediv","text":"pytruediv(x, y)\n\nEquivalent to x / y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pymod","page":"Reference","title":"PythonCall.Core.pymod","text":"pymod(x, y)\n\nEquivalent to x % y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydivmod","page":"Reference","title":"PythonCall.Core.pydivmod","text":"pydivmod(x, y)\n\nEquivalent to divmod(x, y) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylshift","page":"Reference","title":"PythonCall.Core.pylshift","text":"pylshift(x, y)\n\nEquivalent to x << y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrshift","page":"Reference","title":"PythonCall.Core.pyrshift","text":"pyrshift(x, y)\n\nEquivalent to x >> y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyand","page":"Reference","title":"PythonCall.Core.pyand","text":"pyand(x, y)\n\nEquivalent to x & y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyxor","page":"Reference","title":"PythonCall.Core.pyxor","text":"pyxor(x, y)\n\nEquivalent to x ^ y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyor","page":"Reference","title":"PythonCall.Core.pyor","text":"pyor(x, y)\n\nEquivalent to x | y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyiadd","page":"Reference","title":"PythonCall.Core.pyiadd","text":"pyiadd(x, y)\n\nIn-place add. x = pyiadd(x, y) is equivalent to x += y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyisub","page":"Reference","title":"PythonCall.Core.pyisub","text":"pyisub(x, y)\n\nIn-place subtract. x = pyisub(x, y) is equivalent to x -= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimul","page":"Reference","title":"PythonCall.Core.pyimul","text":"pyimul(x, y)\n\nIn-place multiply. x = pyimul(x, y) is equivalent to x *= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimatmul","page":"Reference","title":"PythonCall.Core.pyimatmul","text":"pyimatmul(x, y)\n\nIn-place matrix multiply. x = pyimatmul(x, y) is equivalent to x @= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyipow","page":"Reference","title":"PythonCall.Core.pyipow","text":"pyipow(x, y, z=None)\n\nIn-place power. x = pyipow(x, y) is equivalent to x **= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyifloordiv","page":"Reference","title":"PythonCall.Core.pyifloordiv","text":"pyifloordiv(x, y)\n\nIn-place floor divide. x = pyifloordiv(x, y) is equivalent to x //= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyitruediv","page":"Reference","title":"PythonCall.Core.pyitruediv","text":"pyitruediv(x, y)\n\nIn-place true division. x = pyitruediv(x, y) is equivalent to x /= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimod","page":"Reference","title":"PythonCall.Core.pyimod","text":"pyimod(x, y)\n\nIn-place subtraction. x = pyimod(x, y) is equivalent to x %= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyilshift","page":"Reference","title":"PythonCall.Core.pyilshift","text":"pyilshift(x, y)\n\nIn-place left shift. x = pyilshift(x, y) is equivalent to x <<= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyirshift","page":"Reference","title":"PythonCall.Core.pyirshift","text":"pyirshift(x, y)\n\nIn-place right shift. x = pyirshift(x, y) is equivalent to x >>= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyiand","page":"Reference","title":"PythonCall.Core.pyiand","text":"pyiand(x, y)\n\nIn-place and. x = pyiand(x, y) is equivalent to x &= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyixor","page":"Reference","title":"PythonCall.Core.pyixor","text":"pyixor(x, y)\n\nIn-place xor. x = pyixor(x, y) is equivalent to x ^= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyior","page":"Reference","title":"PythonCall.Core.pyior","text":"pyior(x, y)\n\nIn-place or. x = pyior(x, y) is equivalent to x |= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Logic","page":"Reference","title":"Logic","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions are equivalent to the corresponding Python logical operators.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"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.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Note that the binary operators by default return Py (not Bool) since comparisons in Python do not necessarily return bool.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pytruth\npynot\npyeq\npyne\npyle\npylt\npyge\npygt","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pytruth","page":"Reference","title":"PythonCall.Core.pytruth","text":"pytruth(x)\n\nThe truthyness of x. Equivalent to bool(x) in Python, converted to a Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pynot","page":"Reference","title":"PythonCall.Core.pynot","text":"pynot(x)\n\nThe falsyness of x. Equivalent to not x in Python, converted to a Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyeq","page":"Reference","title":"PythonCall.Core.pyeq","text":"pyeq(x, y)\npyeq(Bool, x, y)\n\nEquivalent to x == y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyne","page":"Reference","title":"PythonCall.Core.pyne","text":"pyne(x, y)\npyne(Bool, x, y)\n\nEquivalent to x != y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyle","page":"Reference","title":"PythonCall.Core.pyle","text":"pyle(x, y)\npyle(Bool, x, y)\n\nEquivalent to x <= y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylt","page":"Reference","title":"PythonCall.Core.pylt","text":"pylt(x, y)\npylt(Bool, x, y)\n\nEquivalent to x < y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyge","page":"Reference","title":"PythonCall.Core.pyge","text":"pyge(x, y)\npyge(Bool, x, y)\n\nEquivalent to x >= y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pygt","page":"Reference","title":"PythonCall.Core.pygt","text":"pygt(x, y)\npygt(Bool, x, y)\n\nEquivalent to x > y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Create-classes","page":"Reference","title":"Create classes","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions can be used to create new Python classes where the functions are implemented in Julia. You can instead use @pyeval etc. to create pure-Python classes.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pytype(::Any, ::Any, ::Any)\npyfunc\npyclassmethod\npystaticmethod\npyproperty","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pytype-Tuple{Any, Any, Any}","page":"Reference","title":"PythonCall.Core.pytype","text":"pytype(name, bases, dict)\n\nCreate a new type. Equivalent to type(name, bases, dict) in Python.\n\nIf bases is not a Python object, it is converted to one using pytuple.\n\nThe dict may either by a Python object or a Julia iterable. In the latter case, each item may either be a name => value pair or a Python object with a __name__ attribute.\n\nIn order to use a Julia Function as an instance method, it must be wrapped into a Python function with pyfunc. Similarly, see also pyclassmethod, pystaticmethod or pyproperty. In all these cases, the arguments passed to the function always have type Py. See the example below.\n\nExample\n\nFoo = pytype(\"Foo\", (), [\n \"__module__\" => \"__main__\",\n\n pyfunc(\n name = \"__init__\",\n doc = \"\"\"\n Specify x and y to store in the Foo.\n\n If omitted, y defaults to None.\n \"\"\",\n function (self, x, y = nothing)\n self.x = x\n self.y = y\n return\n end,\n ),\n\n pyfunc(\n name = \"__repr__\",\n self -> \"Foo($(self.x), $(self.y))\",\n ),\n\n pyclassmethod(\n name = \"frompair\",\n doc = \"Construct a Foo from a tuple of length two.\",\n (cls, xy) -> cls(xy...),\n ),\n\n pystaticmethod(\n name = \"hello\",\n doc = \"Prints a friendly greeting.\",\n (name) -> println(\"Hello, $name\"),\n ),\n\n \"xy\" => pyproperty(\n doc = \"A tuple of x and y.\",\n get = (self) -> (self.x, self.y),\n set = function (self, xy)\n (x, y) = xy\n self.x = x\n self.y = y\n nothing\n end,\n ),\n])\n\n\n\n\n\n","category":"method"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyfunc","page":"Reference","title":"PythonCall.JlWrap.pyfunc","text":"pyfunc(f; [name], [qualname], [doc], [signature])\n\nWrap the callable f as an ordinary Python function.\n\nThe name, qualname, docstring or signature can optionally be set with name, qualname, doc or signature.\n\nUnlike Py(f) (or pyjl(f)), the arguments passed to f are always of type Py, i.e. they are never converted.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyclassmethod","page":"Reference","title":"PythonCall.JlWrap.pyclassmethod","text":"pyclassmethod(f; ...)\n\nConvert callable f to a Python class method.\n\nIf f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Keyword arguments are passed to pyfunc.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pystaticmethod","page":"Reference","title":"PythonCall.JlWrap.pystaticmethod","text":"pystaticmethod(f; ...)\n\nConvert callable f to a Python static method.\n\nIf f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Any keyword arguments are passed to pyfunc.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyproperty","page":"Reference","title":"PythonCall.JlWrap.pyproperty","text":"pyproperty(; get=nothing, set=nothing, del=nothing, doc=nothing)\npyproperty(get)\n\nCreate a Python property with the given getter, setter and deleter.\n\nIf get, set or del is not a Python object (e.g. if it is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to it are always of type Py.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#python-wrappers","page":"Reference","title":"Wrapper types","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"The following types wrap a Python object, giving it the semantics of a Julia object. For example PyList(x) interprets the Python sequence x as a Julia abstract vector.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Apart from a few fundamental immutable types, conversion from Python to Julia Any will return a wrapper type such as one of these, or simply Py if no wrapper type is suitable.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"PyList\nPySet\nPyDict\nPyIterable\nPyArray\nPyIO\nPyTable\nPyPandasDataFrame\nPyObjectArray\nPyException","category":"page"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyList","page":"Reference","title":"PythonCall.Wrap.PyList","text":"PyList{T=Py}([x])\n\nWraps the Python list x (or anything satisfying the sequence interface) as an AbstractVector{T}.\n\nIf x is not a Python object, it is converted to one using pylist.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PySet","page":"Reference","title":"PythonCall.Wrap.PySet","text":"PySet{T=Py}([x])\n\nWraps the Python set x (or anything satisfying the set interface) as an AbstractSet{T}.\n\nIf x is not a Python object, it is converted to one using pyset.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyDict","page":"Reference","title":"PythonCall.Wrap.PyDict","text":"PyDict{K=Py,V=Py}([x])\n\nWraps the Python dict x (or anything satisfying the mapping interface) as an AbstractDict{K,V}.\n\nIf x is not a Python object, it is converted to one using pydict.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyIterable","page":"Reference","title":"PythonCall.Wrap.PyIterable","text":"PyIterable{T=Py}(x)\n\nThis object iterates over iterable Python object x, yielding values of type T.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyArray","page":"Reference","title":"PythonCall.Wrap.PyArray","text":"PyArray{T,N,M,L,R}(x; copy=true, array=true, buffer=true)\n\nWrap the Python array x as a Julia AbstractArray{T,N}.\n\nThe input x can be bytes, bytearray, array.array, numpy.ndarray or anything satisfying the buffer protocol (if buffer=true) or the numpy array interface (if array=true).\n\nIf copy=false then the resulting array is guaranteed to directly wrap the data in x. If copy=true then a copy is taken if necessary to produce an array.\n\nThe type parameters are all optional, and are:\n\nT: The element type.\nN: The number of dimensions.\nM: True if the array is mutable.\nL: True if the array supports fast linear indexing.\nR: The element type of the underlying buffer. Often equal to T.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyIO","page":"Reference","title":"PythonCall.Wrap.PyIO","text":"PyIO(x; own=false, text=missing, line_buffering=false, buflen=4096)\n\nWrap the Python IO stream x as a Julia IO stream.\n\nWhen this goes out of scope and is finalized, it is automatically flushed. If own=true then it is also closed.\n\nIf text=false then x must be a binary stream and arbitrary binary I/O is possible. If text=true then x must be a text stream and only UTF-8 must be written (i.e. use print not write). If text is not specified then it is chosen automatically. If x is a text stream and you really need a binary stream, then often PyIO(x.buffer) will work.\n\nIf line_buffering=true then output is flushed at each line.\n\nFor efficiency, reads and writes are buffered before being sent to x. The size of the buffers is buflen. The buffers are cleared using flush.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyTable","page":"Reference","title":"PythonCall.Wrap.PyTable","text":"PyTable(x)\n\nWrap x as a Tables.jl-compatible table.\n\nPyTable is an abstract type. See PyPandasDataFrame for a concrete example.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyPandasDataFrame","page":"Reference","title":"PythonCall.Wrap.PyPandasDataFrame","text":"PyPandasDataFrame(x; [indexname::Union{Nothing,Symbol}], [columnnames::Function], [columntypes::Function])\n\nWraps the pandas DataFrame x as a Tables.jl-compatible table.\n\nindexname: The name of the column including the index. The default is nothing, meaning to exclude the index.\ncolumnnames: A function mapping the Python column name (a Py) to the Julia one (a Symbol). The default is x -> Symbol(x).\ncolumntypes: A function taking the column name (a Symbol) and returning either the desired element type of the column, or nothing to indicate automatic inference.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.JlWrap.PyObjectArray","page":"Reference","title":"PythonCall.JlWrap.PyObjectArray","text":"PyObjectArray(undef, dims...)\nPyObjectArray(array)\n\nAn array of Pys which supports the Python buffer protocol.\n\nInternally, the objects are stored as an array of pointers.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Core.PyException","page":"Reference","title":"PythonCall.Core.PyException","text":"PyException(x)\n\nWraps the Python exception x as a Julia Exception.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#python-wrappers-custom","page":"Reference","title":"Custom wrappers","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Here is a minimal example of defining a wrapper type. You may add methods, fields and a supertype to the type to specialise its behaviour. See any of the above wrapper types for examples.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"# The new type with a field for the Python object being wrapped.\nstruct MyType\n py::Py\nend\n\n# Says that the object is a wrapper.\nispy(x::MyType) = true\n\n# Says how to access the underlying Python object.\nPy(x::MyType) = x.py","category":"page"},{"location":"pythoncall-reference/#@py-and-@pyconst","page":"Reference","title":"@py and @pyconst","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"@py\n@pyconst","category":"page"},{"location":"pythoncall-reference/#PythonCall.PyMacro.@py","page":"Reference","title":"PythonCall.PyMacro.@py","text":"@py expr\n\nEvaluate the given expression using Pythonic semantics.\n\nFor example:\n\nf(x, y) is translated to pycall(f, x, y)\nx + y is translated to pyadd(x, y)\nx === y is translated to pyis(x, y) (x is y in Python)\nx.foo is translated to pygetattr(x, \"foo\")\nimport x: f as g is translated to g = pyimport(\"x\" => \"f\") (from x import f as g in Python)\n\nCompound statements such as begin, if, while and for are supported.\n\nSee the online documentation for more details.\n\nwarning: Warning\nThis macro is experimental. It may be modified or removed in a future release.\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#PythonCall.Core.@pyconst","page":"Reference","title":"PythonCall.Core.@pyconst","text":"@pyconst ex\n\nEquivalent to Py(ex) but always returns the exact same Julia object.\n\nThat is, if foo() = @pyconst ex then foo() === foo().\n\nThe expression ex is evaluated the first time the code is run.\n\nIf ex is a string literal, the string is interned.\n\nDo not use this macro at the top level of a module. Instead, use pynew() and pycopy!().\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#The-Python-interpreter","page":"Reference","title":"The Python interpreter","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions are not exported. They give information about which Python interpreter is being used.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"PythonCall.python_version\nPythonCall.python_executable_path\nPythonCall.python_library_path\nPythonCall.python_library_handle","category":"page"},{"location":"pythoncall-reference/#PythonCall.C.python_version","page":"Reference","title":"PythonCall.C.python_version","text":"python_version()\n\nThe version of Python, or missing if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.C.python_executable_path","page":"Reference","title":"PythonCall.C.python_executable_path","text":"python_executable_path()\n\nPath to the Python interpreter, or missing if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.C.python_library_path","page":"Reference","title":"PythonCall.C.python_library_path","text":"python_library_path()\n\nPath to libpython, or missing if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.C.python_library_handle","page":"Reference","title":"PythonCall.C.python_library_handle","text":"python_library_handle()\n\nHandle to the open libpython, or C_NULL if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Low-level-API","page":"Reference","title":"Low-level API","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"The functions here are not exported. They are mostly unsafe in the sense that you can crash Julia by using them incorrectly.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"PythonCall.pynew\nPythonCall.pyisnull\nPythonCall.pycopy!\nPythonCall.getptr\nPythonCall.pydel!\nPythonCall.unsafe_pynext","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pynew","page":"Reference","title":"PythonCall.Core.pynew","text":"pynew([ptr])\n\nA new Py representing the Python object at ptr (NULL by default).\n\nIf ptr is given and non-NULL, this function steals a reference to the Python object it points at, i.e. the new Py object owns a reference.\n\nNote that NULL Python objects are not safe in the sense that most API functions will probably crash your Julia session if you pass a NULL argument.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyisnull","page":"Reference","title":"PythonCall.Core.pyisnull","text":"pyisnull(x)\n\nTrue if the Python object x is NULL.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycopy!","page":"Reference","title":"PythonCall.Core.pycopy!","text":"pycopy!(dst::Py, src)\n\nCopy the Python object src into dst, so that they both represent the same object.\n\nThis function exists to support module-level constant Python objects. It is illegal to call most PythonCall API functions at the top level of a module (i.e. before __init__() has run) so you cannot do const x = pything() at the top level. Instead do const x = pynew() at the top level then pycopy!(x, pything()) inside __init__().\n\nAssumes dst is NULL, otherwise a memory leak will occur.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.getptr","page":"Reference","title":"PythonCall.Core.getptr","text":"getptr(x)\n\nGet the underlying pointer from the Python object x.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydel!","page":"Reference","title":"PythonCall.Core.pydel!","text":"pydel!(x::Py)\n\nDelete the Python object x.\n\nDANGER! Use this function ONLY IF the Julia object x could have been garbage-collected anyway, i.e. was about to become unreachable. This means you MUST KNOW that no other part of the program has the Julia object x.\n\nThis decrements the reference count, sets the pointer to NULL and appends x to a cache of unused objects (PYNULL_CACHE).\n\nThis is an optimization to avoid excessive allocation and deallocation in Julia, which can be a significant source of slow-down in code which uses a lot of Python objects. It allows pynew() to pop an item from PYNULL_CACHE instead of allocating one, and avoids calling the relatively slow finalizer on x.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.unsafe_pynext","page":"Reference","title":"PythonCall.Core.unsafe_pynext","text":"unsafe_pynext(x)\n\nReturn the next item in the iterator x. When there are no more items, return NULL.\n\n\n\n\n\n","category":"function"},{"location":"juliacall/#The-Python-module-JuliaCall","page":"Guide","title":"The Python module JuliaCall","text":"","category":"section"},{"location":"juliacall/#Installation","page":"Guide","title":"Installation","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"It's as simple as","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"pip install juliacall","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Developers may wish to clone the repo (https://github.com/JuliaPy/PythonCall.jl) directly and pip install the module in editable mode. You should add \"dev\":true, \"path\":\"../..\" to pysrc/juliacall/juliapkg.json to ensure you use the development version of PythonCall in conjunction with JuliaCall.","category":"page"},{"location":"juliacall/#Getting-started","page":"Guide","title":"Getting started","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"For interactive or scripting use, the simplest way to get started is:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"from juliacall import Main as jl","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"This loads a single variable jl which represents the Main module in Julia, from which all of Julia's functionality is available:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"jl.println(\"Hello from Julia!\")\n# Hello from Julia!\nx = jl.rand(range(10), 3, 5)\nx._jl_display()\n# 3×5 Matrix{Int64}:\n# 8 1 7 0 6\n# 9 2 1 4 0\n# 1 8 5 4 0\nimport numpy\nnumpy.sum(x, axis=0)\n# array([18, 11, 13, 8, 6], dtype=int64)","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"In this example:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"We called the jl.println function to print a message.\nWe called the jl.rand function to generate an array of random integers. Note that the first argument is range(10) which is converted to 0:9 in Julia.\nWe called its special _jl_display() to show it using Julia's display mechanism.\nWe called the numpy.sum function to sum each column of x. This automatically converted x to a NumPy array. (We could have done jl.sum(x, dims=1) too.)","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"If you are writing a package which uses Julia, then to avoid polluting the global Main namespace you instead should start with:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"import juliacall\njl = juliacall.newmodule(\"SomeName\")","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Julia modules have a special method seval which will evaluate a given piece of code given as a string in the module. This is most frequently used to import modules:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"from array import array\njl.seval(\"using Statistics\")\nx = array('i', [1, 2, 3])\njl.mean(x)\n# 2.0\ny = array('i', [2,4,8])\njl.cor(x, y)\n# 0.9819805060619657","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"What to read next:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"The main functionality of this package is in AnyValue objects, which represent Julia objects, documented here.\nIf you need to install Julia packages, read here.\nWhen you call a Julia function, such as jl.rand(...) in the above example, its arguments are converted to Julia according to this table and its return value is converted to Python according to this table.","category":"page"},{"location":"juliacall/#julia-deps","page":"Guide","title":"Managing Julia dependencies","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"JuliaCall manages its Julia dependencies using JuliaPkg.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"It will automatically download a suitable version of Julia if required.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"A Julia environment is also created, activated and populated with any required packages. If you are in a virtual or Conda environment, the environment is put there. Otherwise a global environment is used at ~/.julia/environments/pyjuliapkg.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"If your project requires any Julia packages, or a particular version of Julia itself, then create a file called juliapkg.json in your package. For example: Here is an example:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"{\n \"julia\": \"1.5\",\n \"packages\": {\n \"Example\": {\n \"uuid\": \"7876af07-990d-54b4-ab0e-23690620f79a\",\n \"version\": \"0.5, 0.6\"\n }\n }\n}","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Alternatively you can use add, rm, etc. from JuliaPkg to edit this file.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"See JuliaPkg for more details.","category":"page"},{"location":"juliacall/#julia-config","page":"Guide","title":"Configuration","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Some features of the Julia process, such as the optimization level or number of threads, may be configured in two ways:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"As an -X argument to Python, such as -X juliacall-optlevel=3; or\nAs an environment variable, such as PYTHON_JULIACALL_OPTLEVEL=3.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"-X option Environment Variable Description\n-X juliacall-home= PYTHON_JULIACALL_BINDIR= The directory containing the julia executable.\n-X juliacall-check-bounds= PYTHON_JULIACALL_CHECK_BOUNDS= Enable or disable bounds checking.\n-X juliacall-compile= PYTHON_JULIACALL_COMPILE= Enable or disable JIT compilation.\n-X juliacall-compiled-modules= PYTHON_JULIACALL_COMPILED_MODULES= Enable or disable incrementally compiling modules.\n-X juliacall-depwarn= PYTHON_JULIACALL_DEPWARN= Enable or disable deprecation warnings.\n-X juliacall-handle-signals= PYTHON_JULIACALL_HANDLE_SIGNALS= Enable or disable Julia signal handling.\n-X juliacall-inline= PYTHON_JULIACALL_INLINE= Enable or disable inlining.\n-X juliacall-min-optlevel=<0|1|2|3> PYTHON_JULIACALL_MIN_OPTLEVEL=<0|1|2|3> Optimization level.\n-X juliacall-optimize=<0|1|2|3> PYTHON_JULIACALL_OPTIMIZE=<0|1|2|3> Minimum optimization level.\n-X juliacall-procs= PYTHON_JULIACALL_PROCS= Launch N local worker process.\n-X juliacall-startup-file= PYTHON_JULIACALL_STARTUP_FILE= Enable or disable your startup.jl file.\n-X juliacall-sysimage= PYTHON_JULIACALL_SYSIMAGE= Use the given system image.\n-X juliacall-threads= PYTHON_JULIACALL_THREADS= Launch N threads.\n-X juliacall-warn-overwrite= PYTHON_JULIACALL_WARN_OVERWRITE= Enable or disable method overwrite warnings.\n-X juliacall-autoload-ipython-extension= PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION= Enable or disable IPython extension autoloading.","category":"page"},{"location":"compat/#Compatibility-Tools","page":"Compatibility Tools","title":"Compatibility Tools","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Some packages require a little extra help to work nicely with PythonCall.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Some of these are \"fixes\" that are silently applied for you, and some are just extra functions to bridge a gap. We aim to keep these as minimal as possible.","category":"page"},{"location":"compat/#Python-standard-library","page":"Compatibility Tools","title":"Python standard library","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Whenever a Python exception is displayed by Julia, sys.last_traceback and friends are set. This allows the post-mortem debugger pdb.pm() to work. Disable by setting PythonCall.CONFIG.auto_sys_last_traceback = false.","category":"page"},{"location":"compat/#Julia-standard-library","page":"Compatibility Tools","title":"Julia standard library","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Python objects can be serialised with the Serialization stdlib. This uses pickle library under the hood. You can opt into using dill instead by setting the environment variable JULIA_PYTHONCALL_PICKLE=\"dill\".","category":"page"},{"location":"compat/#Tabular-data-/-Pandas","page":"Compatibility Tools","title":"Tabular data / Pandas","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The abstract type PyTable is for wrapper types around Python tables, providing the Tables.jl interface. PyTable(x) is shorthand for pyconvert(PyTable, x).","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The subtype PyPandasDataFrame wraps a pandas.DataFrame.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"For example, if x is a pandas.DataFrame then PyTable(x) is a PyPandasDataFrame and DataFrame(PyTable(x)) is a DataFrame.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"In the other direction, the following functions can be used to convert any Tables.jl-compatible table to a Python table.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"pytable","category":"page"},{"location":"compat/#PythonCall.Compat.pytable","page":"Compatibility Tools","title":"PythonCall.Compat.pytable","text":"pytable(src, format=:pandas; ...)\n\nConstruct a Python table from the Tables.jl-compatible table src.\n\nThe format controls the type of the resulting table, and is one of:\n\n:pandas: A pandas.DataFrame. Keyword arguments are passed to the DataFrame constructor.\n:columns: A dict mapping column names to columns.\n:rows: A list of rows, which are namedtuples.\n:rowdicts: A list of rows, which are dicts.\n\n\n\n\n\n","category":"function"},{"location":"compat/#MatPlotLib-/-PyPlot-/-Seaborn","page":"Compatibility Tools","title":"MatPlotLib / PyPlot / Seaborn","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"MatPlotLib figures can be shown with Julia's display mechanism, like display(fig) or display(mime, fig).","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"This means that if you return a figure from a Jupyter or Pluto notebook cell, it will be shown. You can call display(plt.gcf()) to display the current figure.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"We also provide a simple MatPlotLib backend: mpl.use(\"module://juliacall.matplotlib\"). Now you can call plt.show() to display the figure with Julia's display mechanism. You can specify the format like plt.show(format=\"png\").","category":"page"},{"location":"compat/#Python-GUIs-(including-MatPlotLib)","page":"Compatibility Tools","title":"Python GUIs (including MatPlotLib)","text":"","category":"section"},{"location":"compat/#Event-loops","page":"Compatibility Tools","title":"Event loops","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"If for example you wish to use PyPlot in interactive mode (matplotlib.pyplot.ion()) then activating the correct event loop will allow it to work.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"PythonCall.event_loop_on\nPythonCall.event_loop_off","category":"page"},{"location":"compat/#PythonCall.Compat.event_loop_on","page":"Compatibility Tools","title":"PythonCall.Compat.event_loop_on","text":"event_loop_on(g::Symbol; interval=0.04, fix=false)\n\nActivate an event loop for the GUI framework g, so that the framework can run in the background of a Julia session.\n\nThe event loop runs every interval seconds. If fix is true and g is a Qt framework, then fix_qt_plugin_path is called.\n\nSupported values of g (and the Python module they relate to) are: :pyqt4 (PyQt4), :pyqt5 (PyQt5), :pyside (PySide), :pyside2 (PySide2), :gtk (gtk), :gtk3 (gi), :wx (wx), :tkinter (tkinter).\n\n\n\n\n\n","category":"function"},{"location":"compat/#PythonCall.Compat.event_loop_off","page":"Compatibility Tools","title":"PythonCall.Compat.event_loop_off","text":"event_loop_off(g::Symbol)\n\nTerminate the event loop g if it is running.\n\n\n\n\n\n","category":"function"},{"location":"compat/#Qt-path-fix","page":"Compatibility Tools","title":"Qt path fix","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"PythonCall.fix_qt_plugin_path","category":"page"},{"location":"compat/#PythonCall.Compat.fix_qt_plugin_path","page":"Compatibility Tools","title":"PythonCall.Compat.fix_qt_plugin_path","text":"fix_qt_plugin_path()\n\nTry to set the QT_PLUGIN_PATH environment variable in Python, if not already set.\n\nThis fixes the problem that Qt does not know where to find its qt.conf file, because it always looks relative to sys.executable, which can be the Julia executable not the Python one when using this package.\n\nIf CONFIG.auto_fix_qt_plugin_path is true, then this is run automatically before PyQt4, PyQt5, PySide or PySide2 are imported.\n\n\n\n\n\n","category":"function"},{"location":"compat/#IPython","page":"Compatibility Tools","title":"IPython","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The juliacall IPython extension adds these features to your IPython session:","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The line magic %julia code executes the given Julia code in-line.\nThe cell magic %%julia executes a cell of Julia code.\nJulia's stdout and stderr are redirected to IPython.\nCalling display(x) from Julia will display x in IPython.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The extension is experimental and unstable - the API can change at any time.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"You can explicitly enable the extension with %load_ext juliacall, but it will automatically be loaded if juliacall is imported and IPython is detected. You can disable this behavior with an environment variable.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The %%julia cell magic can synchronise variables between Julia and Python by listing them on the first line:","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"In [1]: %load_ext juliacall\n\nIn [2]: x = 2\n\nIn [3]: y = 8\n\nIn [4]: %%julia x y z\n ...: z = \"$x^$y = $(x^y)\";\n ...:\n ...:\n\nIn [5]: z\nOut[5]: '2^8 = 256'","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Also see the IPython docs for more information on extensions.","category":"page"},{"location":"compat/#Asynchronous-Julia-code-(including-Makie)","page":"Compatibility Tools","title":"Asynchronous Julia code (including Makie)","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Asynchronous Julia code will not normally run while Python is executing, unless it is in a separate thread.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"This can be fixed by calling jl.yield() periodically from Python code, allowing the Julia scheduler to run.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"When working at the Python REPL, you may call juliacall.interactive() which will allow Julia async code to run while the prompt is showing. This will allow interactive plots such as Makie to work.","category":"page"},{"location":"#PythonCall-and-JuliaCall","page":"Home","title":"PythonCall & JuliaCall","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Bringing Python® and Julia together in seamless harmony:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Call Python code from Julia and Julia code from Python via a symmetric interface.\nSimple syntax, so the Python code looks like Python and the Julia code looks like Julia.\nIntuitive and flexible conversions between Julia and Python: anything can be converted, you are in control.\nFast non-copying conversion of numeric arrays in either direction: modify Python arrays (e.g. bytes, array.array, numpy.ndarray) from Julia or Julia arrays from Python.\nHelpful wrappers: interpret Python sequences, dictionaries, arrays, dataframes and IO streams as their Julia counterparts, and vice versa.\nBeautiful stack-traces.\nWorks anywhere: tested on Windows, MacOS and Linux, 32- and 64-bit, Julia Julia 1.6.1 upwards and Python 3.8 upwards.","category":"page"}] +[{"location":"pythoncall/#The-Julia-module-PythonCall","page":"Guide","title":"The Julia module PythonCall","text":"","category":"section"},{"location":"pythoncall/#Installation","page":"Guide","title":"Installation","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"This package is in the general registry, so to install just type ] in the Julia REPL and run:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"pkg> add PythonCall","category":"page"},{"location":"pythoncall/#Getting-started","page":"Guide","title":"Getting started","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Import the module with:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> using PythonCall","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"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. See here to configure which Python to use.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Now you can interact with Python as follows:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> re = pyimport(\"re\")\nPython: \n\njulia> words = re.findall(\"[a-zA-Z]+\", \"PythonCall.jl is very useful!\")\nPython: ['PythonCall', 'jl', 'is', 'very', 'useful']\n\njulia> sentence = Py(\" \").join(words)\nPython: 'PythonCall jl is very useful'\n\njulia> pyconvert(String, sentence)\n\"PythonCall jl is very useful\"","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"In this example:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"We used pyimport to import the re module.\nWe called its findall function on a pair of strings, which were automatically converted to Python strings (see Conversion to Python).\nWe 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.\nWe called pyconvert to convert the Python string sentence to a Julia string (see Conversion to Julia).","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The values re, words and sentence in the example are all Python objects, which have type Py in Julia. As we have seen, these objects support attribute access (e.g. re.findall) and function calls (e.g. join(words)). They also support indexing, comparison and arithmetic:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pylist([3, 4, 5])\nPython: [3, 4, 5]\n\njulia> x[2] == 5\nPython: True\n\njulia> x[pyslice(0,2)] + pylist([1,2])\nPython: [3, 4, 1, 2]","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"We have just seen the functions pylist (for constructing a Python list) and pyslice (for constructing a Python slice). There are many such functions, mirroring most of the Python builtin functions and types. The API Reference documents them all.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Most of these functions 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.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Notable exceptions are:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"pyconvert to convert a Python object to a Julia object.\npyimport to import a Python module.\npyjl to directly wrap a Julia object as a Python object.\npywith to emulate the Python with statement.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"To access the Python builtins directly, you can access the fields of pybuiltins:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> pybuiltins.None\nPython: None\n\njulia> pybuiltins.True\nPython: True\n\njulia> pybuiltins.ValueError(\"some error\")\nPython: ValueError('some error')","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"With the functions introduced so far, you have access to the vast majority of Python's functionality.","category":"page"},{"location":"pythoncall/#Conversion-between-Julia-and-Python","page":"Guide","title":"Conversion between Julia and Python","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"A Julia object can be converted to a Python one either explicitly (such as Py(x)) or implicitly (such as the arguments when calling a Python function). Either way, it follows the default conversion rules here.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Most operations involving Python objects will return a Py and are not automatically converted to another Julia type. Instead, you can explicitly convert using pyconvert:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pylist([3.4, 5.6])\nPython: [3.4, 5.6]\n\njulia> pyconvert(Vector, x)\n2-element Vector{Float64}:\n 3.4\n 5.6\n\njulia> pyconvert(Vector{Float32}, x)\n2-element Vector{Float32}:\n 3.4\n 5.6\n\njulia> pyconvert(Any, x)\n2-element PyList{Any}:\n 3.4\n 5.6","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"In the above example, we converted a Python list to a Julia vector in three ways.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"pyconvert(Vector, x) returned a Vector{Float64} since all the list items are floats.\npyconvert(Vector{Float32}, x) specified the element type, so the floats were converted to Float32.\npyconvert(Any, x) returned a PyList{Py} which is a no-copy wrapper around the original list x, viewing it as a AbstractVector{Py}. Since it is a wrapper, mutating it mutates x and vice-versa.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See here for the rules regarding how pyconvert(T, x) works. If x is an immutable scalar type (such as an int or str) then pyconvert(Any, x) may return the corresponding Julia object (such as an Integer or String). Otherwise it will typically return either a wrapper type (such as PyList{Py} in the above example) or will fall back to returning a Py.","category":"page"},{"location":"pythoncall/#py-wrappers","page":"Guide","title":"Wrapper types","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"A wrapper is a type which wraps a Python object but provides it with the semantics of some other Julia type.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Since it is merely wrapping a Python object, if you mutate the wrapper you also mutate the wrapped object, and vice versa.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See here for details of all the wrapper types provided by PythonCall.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"We have already seen PyList. It wraps any Python sequence (such as a list) as a Julia vector:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pylist([3,4,5])\nPython: [3, 4, 5]\n\njulia> y = PyList{Union{Int,Nothing}}(x)\n3-element PyList{Union{Nothing, Int64}}:\n 3\n 4\n 5\n\njulia> push!(y, nothing)\n4-element PyList{Union{Nothing, Int64}}:\n 3\n 4\n 5\n nothing\n\njulia> append!(y, 1:2)\n6-element PyList{Union{Nothing, Int64}}:\n 3\n 4\n 5\n nothing\n 1\n 2\n\njulia> x\nPython: [3, 4, 5, None, 1, 2]","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"There are wrappers for other container types, such as PyDict and PySet.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The wrapper PyArray provides a Julia array view of any Python array, i.e. anything satisfying either the buffer protocol or the numpy array interface. This includes things like bytes, bytearray, array.array and numpy.ndarray:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pyimport(\"array\").array(\"i\", [3, 4, 5])\nPython: array('i', [3, 4, 5])\n\njulia> y = PyArray(x)\n3-element PyArray{Int32, 1, true, true, Int32}:\n 3\n 4\n 5\n\njulia> sum(y)\n12\n\njulia> y[1] = 0\n0\n\njulia> x\nPython: array('i', [0, 4, 5])","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"It directly wraps the underlying data buffer, so array operations such as indexing are about as fast as for an ordinary Array.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The PyIO wrapper type views a Python file object as a Julia IO object:","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> x = pyimport(\"io\").StringIO()\nPython: <_io.StringIO object at 0x000000006579BC70>\n\njulia> y = PyIO(x)\nPyIO(, false, true, false, 4096, UInt8[], 4096, UInt8[])\n\njulia> println(y, \"Hello, world!\")\n\njulia> flush(y)\n\njulia> x.seek(0)\nPython: 0\n\njulia> x.read()\nPython: 'Hello, world!\\n'","category":"page"},{"location":"pythoncall/#pythoncall-config","page":"Guide","title":"Configuration","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"By default, PythonCall uses CondaPkg.jl to manage its dependencies. This will install Conda and use it to create a Conda environment specific to your current Julia project containing Python and any required Python packages.","category":"page"},{"location":"pythoncall/#If-you-already-have-Python-and-required-Python-packages-installed","page":"Guide","title":"If you already have Python and required Python packages installed","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"ENV[\"JULIA_CONDAPKG_BACKEND\"] = \"Null\"\nENV[\"JULIA_PYTHONCALL_EXE\"] = \"/path/to/python\" # optional\nENV[\"JULIA_PYTHONCALL_EXE\"] = \"@PyCall\" # optional","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"By setting the CondaPkg backend to Null, it will never install any Conda packages. In this case, PythonCall will use whichever Python is currently installed and in your PATH. You must have already installed any Python packages that you need.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If python is not in your PATH, you will also need to set JULIA_PYTHONCALL_EXE to its path.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If you also use PyCall, you can set JULIA_PYTHONCALL_EXE=@PyCall to use the same Python interpreter.","category":"page"},{"location":"pythoncall/#If-you-already-have-a-Conda-environment","page":"Guide","title":"If you already have a Conda environment","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"ENV[\"JULIA_CONDAPKG_BACKEND\"] = \"Current\"\nENV[\"JULIA_CONDAPKG_EXE\"] = \"/path/to/conda\" # optional","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The Current backend to CondaPkg will use the currently activated Conda environment instead of creating a new one.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Note that this will still install any required Conda packages into your Conda environment. If you already have your dependencies installed and do not want the environment to be modified, then see the previous section.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If conda, mamba or micromamba is not in your PATH you will also need to set JULIA_CONDAPKG_EXE to its path.","category":"page"},{"location":"pythoncall/#If-you-already-have-Conda,-Mamba-or-MicroMamba","page":"Guide","title":"If you already have Conda, Mamba or MicroMamba","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"ENV[\"JULIA_CONDAPKG_BACKEND\"] = \"System\"\nENV[\"JULIA_CONDAPKG_EXE\"] = \"/path/to/conda\" # optional","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"The System backend to CondaPkg will use your preinstalled Conda implementation instead of downloading one.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Note that this will still create a new Conda environment and install any required packages into it. If you want to use a pre-existing Conda environment, see the previous section.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If conda, mamba or micromamba is not in your PATH you will also need to set JULIA_CONDAPKG_EXE to its path.","category":"page"},{"location":"pythoncall/#python-deps","page":"Guide","title":"Installing Python packages","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"Assuming you haven't opted out, PythonCall uses CondaPkg.jl to automatically install any required Python packages.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"This is as simple as","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"julia> using CondaPkg\n\njulia> # press ] to enter the Pkg REPL\n\npkg> conda add some_package","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"This creates a CondaPkg.toml file in the active project specifying the dependencies, just like a Project.toml specifies Julia dependencies. Commit this file along with the rest of the project so that dependencies are automatically installed for everyone using it.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"To add dependencies to a Julia package, just ensure the package project is activated first.","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See the CondaPkg.jl documentation.","category":"page"},{"location":"pythoncall/#Writing-packages-which-depend-on-PythonCall","page":"Guide","title":"Writing packages which depend on PythonCall","text":"","category":"section"},{"location":"pythoncall/#Example","page":"Guide","title":"Example","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"See https://github.com/cjdoris/Faiss.jl for an example package which wraps the Python FAISS package.","category":"page"},{"location":"pythoncall/#Precompilation","page":"Guide","title":"Precompilation","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"You must not interact with Python during module precompilation. Therefore, instead of","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n const foo = pyimport(\"foo\")\n bar() = foo.bar() # will crash when called\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"you can do the import when the module is loaded, saving the result in a Ref","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n const foo = Ref{Py}()\n function __init__()\n foo[] = pyimport(\"foo\")\n end\n bar() = foo[].bar()\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"or you can perform any imports dynamically","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n bar() = pyimport(\"foo\").bar()\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"or if that is too slow, you can cache the import","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n bar() = @pyconst(pyimport(\"foo\")).bar()\nend","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"or even cache the imported function","category":"page"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"module MyModule\n using PythonCall\n bar() = @pyconst(pyimport(\"foo\").bar)()\nend","category":"page"},{"location":"pythoncall/#Dependencies","page":"Guide","title":"Dependencies","text":"","category":"section"},{"location":"pythoncall/","page":"Guide","title":"Guide","text":"If your package depends on some Python packages, you must generate a CondaPkg.toml file. See Installing Python packages.","category":"page"},{"location":"juliacall-reference/#JuliaCall-API-Reference","page":"Reference","title":"JuliaCall API Reference","text":"","category":"section"},{"location":"juliacall-reference/#Constants","page":"Reference","title":"Constants","text":"","category":"section"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.Main - Constant\n\nThe Julia `Main` module, as a [`ModuleValue`](#juliacall.ModuleValue).\n\nIn interactive scripts, you can use this as the main entry-point to JuliaCall:\n```python\nfrom juliacall import Main as jl\njl.println(\"Hello, world!\")\n```\n\nIn packages, use [`newmodule`](#juliacall.newmodule) instead.","category":"page"},{"location":"juliacall-reference/#juliacall.Main","page":"Reference","title":"juliacall.Main","text":"The Julia Main module, as a ModuleValue.\n\nIn interactive scripts, you can use this as the main entry-point to JuliaCall:\n\nfrom juliacall import Main as jl\njl.println(\"Hello, world!\")\n\nIn packages, use newmodule instead.\n\n\n\n\n\n","category":"constant"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"The modules Base, Core and PythonCall are also available.","category":"page"},{"location":"juliacall-reference/#Utilities","page":"Reference","title":"Utilities","text":"","category":"section"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.convert - Function\n\n```python\nconvert(T, x)\n```\n\nConvert `x` to a Julia object of type `T`.\n\nYou can use this to pass an argument to a Julia function of a specific type.","category":"page"},{"location":"juliacall-reference/#juliacall.convert","page":"Reference","title":"juliacall.convert","text":"convert(T, x)\n\nConvert x to a Julia object of type T.\n\nYou can use this to pass an argument to a Julia function of a specific type.\n\n\n\n\n\n","category":"function"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.newmodule - Function\n\n```python\nnewmodule(name)\n```\n\nA new module with the given name.","category":"page"},{"location":"juliacall-reference/#juliacall.newmodule","page":"Reference","title":"juliacall.newmodule","text":"newmodule(name)\n\nA new module with the given name.\n\n\n\n\n\n","category":"function"},{"location":"juliacall-reference/#julia-wrappers","page":"Reference","title":"Wrapper types","text":"","category":"section"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"Apart from a few fundamental immutable types, all Julia values are by default converted into Python to some AnyValue object, which wraps the original value, but giving it a Pythonic interface.","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"Subclasses of AnyValue provide additional Python semantics. For example a Julia vector is converted to a VectorValue which satisfies the Python sequence interface and behaves very similar to a list.","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"There is also a RawValue object, which gives a stricter \"Julia-only\" interface, documented below. These types all inherit from ValueBase:","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"ValueBase\nRawValue\nAnyValue\nNumberValue\nComplexValue\nRealValue\nRationalValue\nIntegerValue\nArrayValue\nVectorValue\nDictValue\nSetValue\nIOValue\nBinaryIOValue\nTextIOValue\nModuleValue\nTypeValue","category":"page"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.AnyValue - Class\n\nWraps any Julia object, giving it some basic Python semantics. Subtypes provide extra\nsemantics.\n\nSupports `repr(x)`, `str(x)`, attributes (`x.attr`), calling (`x(a,b)`), iteration,\ncomparisons, `len(x)`, `a in x`, `dir(x)`.\n\nCalling, indexing, attribute access, etc. will convert the result to a Python object\naccording to [this table](@ref jl2py). This is typically a builtin Python type (for\nimmutables) or a subtype of `AnyValue`.\n\nAttribute access can be used to access Julia properties as well as normal class members. In\nthe case of a name clash, the class member will take precedence. For convenience with Julia\nnaming conventions, `_b` at the end of an attribute is replaced with `!` and `_bb` is\nreplaced with `!!`.\n\n###### Members\n- `_jl_raw()`: Convert to a [`RawValue`](#juliacall.RawValue). (See also [`pyjlraw`](@ref).)\n- `_jl_display()`: Display the object using Julia's display mechanism.\n- `_jl_help()`: Display help for the object.","category":"page"},{"location":"juliacall-reference/#juliacall.AnyValue","page":"Reference","title":"juliacall.AnyValue","text":"Wraps any Julia object, giving it some basic Python semantics. Subtypes provide extra semantics.\n\nSupports repr(x), str(x), attributes (x.attr), calling (x(a,b)), iteration, comparisons, len(x), a in x, dir(x).\n\nCalling, indexing, attribute access, etc. will convert the result to a Python object according to this table. This is typically a builtin Python type (for immutables) or a subtype of AnyValue.\n\nAttribute access can be used to access Julia properties as well as normal class members. In the case of a name clash, the class member will take precedence. For convenience with Julia naming conventions, _b at the end of an attribute is replaced with ! and _bb is replaced with !!.\n\nMembers\n\n_jl_raw(): Convert to a RawValue. (See also pyjlraw.)\n_jl_display(): Display the object using Julia's display mechanism.\n_jl_help(): Display help for the object.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.NumberValue - Class\n\nThis wraps any Julia `Number` value. It is a subclass of `numbers.Number` and behaves\nsimilar to other Python numbers.\n\nThere are also subtypes `ComplexValue`, `RealValue`, `RationalValue`, `IntegerValue` which\nwrap values of the corresponding Julia types, and are subclasses of the corresponding\n`numbers` ABC.","category":"page"},{"location":"juliacall-reference/#juliacall.NumberValue","page":"Reference","title":"juliacall.NumberValue","text":"This wraps any Julia Number value. It is a subclass of numbers.Number and behaves similar to other Python numbers.\n\nThere are also subtypes ComplexValue, RealValue, RationalValue, IntegerValue which wrap values of the corresponding Julia types, and are subclasses of the corresponding numbers ABC.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.ArrayValue - Class\n\nThis wraps any Julia `AbstractArray` value. It is a subclass of\n`collections.abc.Collection`.\n\nIt supports zero-up indexing, and can be indexed with integers or slices. Slicing returns a\nview of the original array.\n\nIf the array is strided and its eltype is supported (i.e. `Bool`, `IntXX`, `UIntXX`,\n`FloatXX`, `Complex{FloatXX}`, `Ptr{Cvoid}` or `Tuple` or `NamedTuple` of these) then it\nsupports the buffer protocol and the numpy array interface. This means that\n`numpy.asarray(this)` will yield a view of the original array, so mutations are visible on\nthe original.\n\nOtherwise, the numpy `__array__` method is supported, and this returns an array of Python\nobjects converted from the contents of the array. In this case, `numpy.asarray(this)` is a\ncopy of the original array.\n\n###### Members\n- `ndim`: The number of dimensions.\n- `shape`: Tuple of lengths in each dimension.\n- `copy()`: A copy of the array.\n- `reshape(shape)`: A reshaped view of the array.\n- `to_numpy(dtype=None, copy=True, order=\"K\")`: Convert to a numpy array.","category":"page"},{"location":"juliacall-reference/#juliacall.ArrayValue","page":"Reference","title":"juliacall.ArrayValue","text":"This wraps any Julia AbstractArray value. It is a subclass of collections.abc.Collection.\n\nIt supports zero-up indexing, and can be indexed with integers or slices. Slicing returns a view of the original array.\n\nIf the array is strided and its eltype is supported (i.e. Bool, IntXX, UIntXX, FloatXX, Complex{FloatXX}, Ptr{Cvoid} or Tuple or NamedTuple of these) then it supports the buffer protocol and the numpy array interface. This means that numpy.asarray(this) will yield a view of the original array, so mutations are visible on the original.\n\nOtherwise, the numpy __array__ method is supported, and this returns an array of Python objects converted from the contents of the array. In this case, numpy.asarray(this) is a copy of the original array.\n\nMembers\n\nndim: The number of dimensions.\nshape: Tuple of lengths in each dimension.\ncopy(): A copy of the array.\nreshape(shape): A reshaped view of the array.\nto_numpy(dtype=None, copy=True, order=\"K\"): Convert to a numpy array.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.VectorValue - Class\n\nThis wraps any Julia `AbstractVector` value. It is a subclass of `juliacall.ArrayValue` and\n`collections.abc.MutableSequence` and behaves similar to a Python `list`.\n\n###### Members\n- `resize(size)`: Change the length of the vector.\n- `sort(reverse=False, key=None)`: Sort the vector in-place.\n- `reverse()`: Reverse the vector.\n- `clear()`: Empty the vector.\n- `insert(index, value)`: Insert the value at the given index.\n- `append(value)`: Append the value to the end of the vector.\n- `extend(values)`: Append the values to the end of the vector.\n- `pop(index=-1)`: Remove and return the item at the given index.\n- `remove(value)`: Remove the first item equal to the value.\n- `index(value)`: The index of the first item equal to the value.\n- `count(value)`: The number of items equal to the value.","category":"page"},{"location":"juliacall-reference/#juliacall.VectorValue","page":"Reference","title":"juliacall.VectorValue","text":"This wraps any Julia AbstractVector value. It is a subclass of juliacall.ArrayValue and collections.abc.MutableSequence and behaves similar to a Python list.\n\nMembers\n\nresize(size): Change the length of the vector.\nsort(reverse=False, key=None): Sort the vector in-place.\nreverse(): Reverse the vector.\nclear(): Empty the vector.\ninsert(index, value): Insert the value at the given index.\nappend(value): Append the value to the end of the vector.\nextend(values): Append the values to the end of the vector.\npop(index=-1): Remove and return the item at the given index.\nremove(value): Remove the first item equal to the value.\nindex(value): The index of the first item equal to the value.\ncount(value): The number of items equal to the value.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.DictValue - Class\nThis wraps any Julia `AbstractDict` value. It is a subclass of `collections.abc.Mapping` and\nbehaves similar to a Python `dict`.","category":"page"},{"location":"juliacall-reference/#juliacall.DictValue","page":"Reference","title":"juliacall.DictValue","text":"This wraps any Julia AbstractDict value. It is a subclass of collections.abc.Mapping and behaves similar to a Python dict.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.SetValue - Class\nThis wraps any Julia `AbstractSet` value. It is a subclass of `collections.abc.Set` and\nbehaves similar to a Python `set`.","category":"page"},{"location":"juliacall-reference/#juliacall.SetValue","page":"Reference","title":"juliacall.SetValue","text":"This wraps any Julia AbstractSet value. It is a subclass of collections.abc.Set and behaves similar to a Python set.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.IOValue - Class\n\nThis wraps any Julia `IO` value. It is a subclass of `io.IOBase` and behaves like Python\nfiles.\n\nThere are also subtypes `BinaryIOValue` and `TextIOValue`, which are subclasses of\n`io.BufferedIOBase` (buffered bytes) and `io.TextIOBase` (text).","category":"page"},{"location":"juliacall-reference/#juliacall.IOValue","page":"Reference","title":"juliacall.IOValue","text":"This wraps any Julia IO value. It is a subclass of io.IOBase and behaves like Python files.\n\nThere are also subtypes BinaryIOValue and TextIOValue, which are subclasses of io.BufferedIOBase (buffered bytes) and io.TextIOBase (text).\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.ModuleValue - Class\nThis wraps any Julia `Module` value.\n\nIt is the same as [`AnyValue`](#juliacall.AnyValue) except for one additional convenience\nmethod:\n- `seval([module=self], code)`: Evaluates the given code (a string) in the given module.","category":"page"},{"location":"juliacall-reference/#juliacall.ModuleValue","page":"Reference","title":"juliacall.ModuleValue","text":"This wraps any Julia Module value.\n\nIt is the same as AnyValue except for one additional convenience method:\n\nseval([module=self], code): Evaluates the given code (a string) in the given module.\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.TypeValue - Class\n\nThis wraps any Julia `Type` value.\n\nIt is the same as [`AnyValue`](#juliacall.AnyValue) except that indexing is used to access\nJulia's \"curly\" syntax for specifying parametric types:\n\n```python\nfrom juliacall import Main as jl\n# equivalent to Vector{Int}() in Julia\njl.Vector[jl.Int]()\n```","category":"page"},{"location":"juliacall-reference/#juliacall.TypeValue","page":"Reference","title":"juliacall.TypeValue","text":"This wraps any Julia Type value.\n\nIt is the same as AnyValue except that indexing is used to access Julia's \"curly\" syntax for specifying parametric types:\n\nfrom juliacall import Main as jl\n# equivalent to Vector{Int}() in Julia\njl.Vector[jl.Int]()\n\n\n\n\n\n","category":"class"},{"location":"juliacall-reference/","page":"Reference","title":"Reference","text":"juliacall.RawValue - Class\n\nWraps any Julia value with a rigid interface suitable for generic programming.\n\nSupports `repr(x)`, `str(x)`, attributes (`x.attr`), calling (`x(a,b)`), `len(x)`, `dir(x)`.\n\nThis is very similar to [`AnyValue`](#juliacall.AnyValue) except that indexing, calling,\netc. will always return a `RawValue`.\n\nIndexing with a tuple corresponds to indexing in Julia with multiple values. To index with a\nsingle tuple, it will need to be wrapped in another tuple.\n\n###### Members\n- `_jl_any()`: Convert to a [`AnyValue`](#juliacall.AnyValue) (or subclass). (See also\n [`pyjl`](@ref).)","category":"page"},{"location":"juliacall-reference/#juliacall.RawValue","page":"Reference","title":"juliacall.RawValue","text":"Wraps any Julia value with a rigid interface suitable for generic programming.\n\nSupports repr(x), str(x), attributes (x.attr), calling (x(a,b)), len(x), dir(x).\n\nThis is very similar to AnyValue except that indexing, calling, etc. will always return a RawValue.\n\nIndexing with a tuple corresponds to indexing in Julia with multiple values. To index with a single tuple, it will need to be wrapped in another tuple.\n\nMembers\n\n_jl_any(): Convert to a AnyValue (or subclass). (See also pyjl.)\n\n\n\n\n\n","category":"class"},{"location":"conversion-to-python/#jl2py","page":"Julia to Python","title":"Conversion to Python","text":"","category":"section"},{"location":"conversion-to-python/#jl2py-conversion","page":"Julia to Python","title":"Conversion Rules","text":"","category":"section"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"The following table specifies the conversion rules used whenever converting a Julia object to a Python object.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"From Julia, this occurs explicitly with Py(x) or implicitly when passing Julia objects as the argument to a Python function. To avoid this automatic conversion, the user can convert objects explicitly, such as by calling pylist or pydict.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"From Python, this occurs when converting the return value of a Julia function.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"From To\nAny Python object type (Py, PyList, etc.) itself\nNothing, Missing None\nBool bool\nStandard integer (IntXX, UIntXX, BigInt) int\nStandard rational (Rational{T}, T a standard integer) fractions.Fraction\nStandard float (FloatXX) float\nStandard complex (Complex{T}, T a standard float) complex\nStandard string/char (String and SubString{String}, Char) str\nTuple tuple\nStandard integer range (AbstractRange{T}, T a standard integer) range\nDate, Time, DateTime (from Dates) date, time, datetime (from datetime)\nSecond, Millisecond, Microsecond, Nanosecond (from Dates) timedelta (from datetime)\nNumber juliacall.NumberValue, juliacall.ComplexValue, etc.\nAbstractArray juliacall.ArrayValue, juliacall.VectorValue\nAbstractDict juliacall.DictValue\nAbstractSet juliacall.SetValue\nIO juliacall.BufferedIOValue\nModule juliacall.ModuleValue\nType juliacall.TypeValue\nAnything else juliacall.AnyValue","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"See here for an explanation of the juliacall.*Value wrapper types.","category":"page"},{"location":"conversion-to-python/#jl2py-conversion-custom","page":"Julia to Python","title":"Custom rules","text":"","category":"section"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"You may define a new conversion rule for your new type T by overloading Py(::T).","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"If T is a wrapper type (such as PyList) where Py(x) simply returns the stored Python object, then also define ispy(::T) = true.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"PythonCall.ispy","category":"page"},{"location":"conversion-to-python/#PythonCall.Core.ispy","page":"Julia to Python","title":"PythonCall.Core.ispy","text":"ispy(x)\n\nTrue if x is a Python object.\n\nThis includes Py and Python wrapper types such as PyList.\n\n\n\n\n\n","category":"function"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"Alternatively, if you define a wrapper type (a subtype of juliacall.AnyValue) then you may instead define pyjltype(::T) to be that type.","category":"page"},{"location":"conversion-to-python/","page":"Julia to Python","title":"Julia to Python","text":"PythonCall.pyjltype","category":"page"},{"location":"conversion-to-python/#PythonCall.JlWrap.pyjltype","page":"Julia to Python","title":"PythonCall.JlWrap.pyjltype","text":"pyjltype(x)\n\nThe subtype of juliacall.AnyValue which the Julia object x is wrapped as by pyjl(x).\n\nOverload pyjltype(::T) to define a custom conversion for your type T.\n\n\n\n\n\n","category":"function"},{"location":"pycall/#Coming-from-PyCall/PyJulia?","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Another similar interface to Python is provided by PyCall.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"On this page, we give some tips for migrating between the two modules and a comparison.","category":"page"},{"location":"pycall/#Tips","page":"Coming from PyCall/PyJulia?","title":"Tips","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"You can use both PyCall and PythonCall in the same Julia session. This is platform-dependent:\nOn Unix (Linux, Mac, etc.) the Python interpreter used by PythonCall and PyCall must be the same (see below).\nOn Windows, it appears to be possible for PythonCall and PyCall to use different interpreters.\nTo force PythonCall to use the same Python interpreter as PyCall, set the environment variable JULIA_PYTHONCALL_EXE to \"@PyCall\". Note that this will opt out of automatic dependency management using CondaPkg.\nAlternatively, to force PyCall to use the same interpreter as PythonCall, set the environment variable PYTHON to PythonCall.python_executable_path() and then Pkg.build(\"PyCall\"). You will need to do this each time you change project, because PythonCall by default uses a different Python for each project.","category":"page"},{"location":"pycall/#Comparison","page":"Coming from PyCall/PyJulia?","title":"Comparison","text":"","category":"section"},{"location":"pycall/#Flexibility-of-conversion","page":"Coming from PyCall/PyJulia?","title":"Flexibility of conversion","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In PyCall you do convert(T, x) to convert the Python object x to a Julia T. In PythonCall you similarly do pyconvert(T, x).","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PythonCall supports far more combinations of types of T and x. For example convert(Vector, x) in PyCall requires x to be a sequence, whereas in PythonCall pyconvert(Vector, x) works if x is an iterable, an object supporting the buffer protocol (such as bytes) or an object supporting the numpy array interface (such as numpy.ndarray).","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Furthermore, pyconvert can be extended to support more types, whereas convert(Vector, x) cannot support more Python types.","category":"page"},{"location":"pycall/#Lossiness-of-conversion","page":"Coming from PyCall/PyJulia?","title":"Lossiness of conversion","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Both packages allow conversion of Julia values to Python: PyObject(x) in PyCall, Py(x) in PythonCall.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Whereas both packages convert numbers, booleans, tuples and strings to their Python counterparts, they differ in handling other types. For example PyCall converts AbstractVector to list whereas PythonCall converts AbstractVector to juliacall.VectorValue which is a sequence type directly wrapping the Julia value - this has the advantage that mutating the Python object also mutates the original Julia object.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Hence with PyCall the following does not mutate the original array x:","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"x = [\"foo\", \"bar\"]\nPyObject(x).append(\"baz\")\n@show x # --> [\"foo\", \"bar\"]","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"whereas with PythonCall the following does mutate x:","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"x = [\"foo\", \"bar\"]\nPy(x).append(\"baz\")\n@show x # --> [\"foo\", \"bar\", \"baz\"]","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In fact, PythonCall has the policy that any mutable object will by default be wrapped in this way, which not only preserves mutability but makes conversion faster for large containers since it does not require taking a copy of all the data.","category":"page"},{"location":"pycall/#Automatic-conversion","page":"Coming from PyCall/PyJulia?","title":"Automatic conversion","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In PyCall, most function calls, attribute accesses, indexing, etc. of Python object by default automatically convert their result to a Julia object. This means that the following","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"pyimport(\"sys\").modules[\"KEY\"] = \"VALUE\"","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"does not actually modify the modules dict because it was copied to a new Julia Dict. This was probably not intended, plus it wasted time copying the whole dictionary. Instead you must do","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"set!(pyimport(os).\"environ\", \"KEY\", \"VALUE\")","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"In PythonCall, we don't do any such automatic conversion: we always return Py. This means that the first piece of code above does what you think.","category":"page"},{"location":"pycall/#Which-Python","page":"Coming from PyCall/PyJulia?","title":"Which Python","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PyCall uses some global installation of Python - typically the version of Python installed on the system or used by Conda.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PythonCall uses a separate Conda environment for each Julia environment/project/package and installs Python (and other Python packages) into that. This means that different Julia projects can maintain an isolated set of Python dependencies (including the Python version itself).","category":"page"},{"location":"pycall/#Corresponding-Python-packages","page":"Coming from PyCall/PyJulia?","title":"Corresponding Python packages","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PyCall has the corresponding Python package PyJulia for calling Julia from Python, and PythonCall similarly has JuliaCall.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"One difference is between them is their code size: PyJulia is a large package, whereas JuliaCall is very small, with most of the implementation being in PythonCall itself. The practical up-shot is that PythonCall/JuliaCall have very symmetric interfaces; for example they use identical conversion policies and have the same set of wrapper types available.","category":"page"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"Note also that JuliaCall will use a separate Julia project for each virtual/conda environment. This means that different Python environments can maintain an isolated set of Julia dependencies, including the versions of Julia and PythonCall themselves.","category":"page"},{"location":"pycall/#Compatibility","page":"Coming from PyCall/PyJulia?","title":"Compatibility","text":"","category":"section"},{"location":"pycall/","page":"Coming from PyCall/PyJulia?","title":"Coming from PyCall/PyJulia?","text":"PyCall supports Julia 0.7+ and Python 2.7+, whereas PythonCall supports Julia 1.6.1+ and Python 3.8+. PyCall requires numpy to be installed, PythonCall doesn't (it provides the same fast array access through the buffer protocol and array interface).","category":"page"},{"location":"releasenotes/#Release-Notes","page":"Release Notes","title":"Release Notes","text":"","category":"section"},{"location":"releasenotes/#Unreleased","page":"Release Notes","title":"Unreleased","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Finalizers are now thread-safe, meaning PythonCall now works in the presence of multi-threaded Julia code. Previously, tricks such as disabling the garbage collector were required. Python code must still be called on the main thread.\nGC.disable() and GC.enable() are now a no-op and deprecated since they are no longer required for thread-safety. These will be removed in v1.\nAdds GC.gc().","category":"page"},{"location":"releasenotes/#0.9.21-(2024-07-20)","page":"Release Notes","title":"0.9.21 (2024-07-20)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Serialization.serialize can use dill instead of pickle by setting the env var JULIA_PYTHONCALL_PICKLE=dill.\nnumpy.bool_ can now be converted to Bool and other number types.\ndatetime.timedelta can now be converted to Dates.Nanosecond, Microsecond, Millisecond and Second. This behaviour was already documented.\nIn JuliaCall, the Julia runtime is now properly terminated when Python exits. This means all finalizers should always run.\nNULL Python objects (such as from pynew()) can be safely displayed in multimedia contexts (VSCode/Pluto/etc.)","category":"page"},{"location":"releasenotes/#0.9.20-(2024-05-01)","page":"Release Notes","title":"0.9.20 (2024-05-01)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"The IPython extension is now automatically loaded upon import if IPython is detected.\nJuliaCall now compatible with Julia 1.10.3.\nMinimum supported Python version is now 3.8.","category":"page"},{"location":"releasenotes/#0.9.19-(2024-03-19)","page":"Release Notes","title":"0.9.19 (2024-03-19)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.18-(2024-03-18)","page":"Release Notes","title":"0.9.18 (2024-03-18)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.17-(2024-03-16)","page":"Release Notes","title":"0.9.17 (2024-03-16)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.16-(2024-03-14)","page":"Release Notes","title":"0.9.16 (2024-03-14)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Big internal refactor.\nNew unexported functions: python_executable_path, python_library_path, python_library_handle and python_version.\nPy is now treated as a scalar when broadcasting.\nPyArray is now serializable.\nRemoved compatibility with Julia 1.10.1 and 1.10.2 (to be fixed in 1.10.3 and 1.11.0) due to an upstream bug.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.15-(2023-10-25)","page":"Release Notes","title":"0.9.15 (2023-10-25)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"JuliaCall now supports -X juliacall-startup-file=no to disable running startup.jl.\nIf you are using CondaPkg then Python can optionally now be installed from the anaconda channel (instead of only conda-forge).\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.14-(2023-07-26)","page":"Release Notes","title":"0.9.14 (2023-07-26)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Wrapped Julia values support truthiness (__bool__) better: all values are true, except for zero numbers and empty arrays, dicts and sets.\nJuliaCall now supports the Julia --handle-signals option. Setting this to yes allows allocating multithreaded Julia code to be called from JuliaCall without segfaulting. The default is no while compatibility concerns are investigated, and may be changed to yes in a future release.","category":"page"},{"location":"releasenotes/#0.9.13-(2023-05-14)","page":"Release Notes","title":"0.9.13 (2023-05-14)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Conversion to wrapper types PyList, PySet, PyDict or PyIterable now default to having element type Any instead of Py.\nThe __repr__ method of wrapped Julia objects now uses the 3-arg show method for nicer (richer and truncated) display at the Python REPL.\nThe IPython extension can now be loaded as just %load_ext juliacall.\nThe %%julia IPython magic can now synchronise variables between Python and Julia.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.12-(2023-02-28)","page":"Release Notes","title":"0.9.12 (2023-02-28)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.11-(2023-02-15)","page":"Release Notes","title":"0.9.11 (2023-02-15)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"In PyArray{T}(x), the eltype T no longer needs to exactly match the stored data type. If x has numeric elements, then any number type T is allowed. If x has string elements, then any string type T is allowed.\nStaticString (the inline string type used by PyArray) supports the AbstractString interface better.","category":"page"},{"location":"releasenotes/#0.9.10-(2022-12-02)","page":"Release Notes","title":"0.9.10 (2022-12-02)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.9-(2022-10-20)","page":"Release Notes","title":"0.9.9 (2022-10-20)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.8-(2022-10-18)","page":"Release Notes","title":"0.9.8 (2022-10-18)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Adds line_buffering option to PyIO.\nImprovements to stdout when using juliacall.ipython including line-buffering.","category":"page"},{"location":"releasenotes/#0.9.7-(2022-10-11)","page":"Release Notes","title":"0.9.7 (2022-10-11)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"If CondaPkg is using the Null backend, PythonCall will now use python from the PATH.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.6-(2022-09-09)","page":"Release Notes","title":"0.9.6 (2022-09-09)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"When using JuliaCall from an interactive Python session, Julia is put into interactive mode: isinteractive() is true, InteractiveUtils is loaded, and a nicer display is used.\nWrapped Julia values now truncate their output when displayed via _repr_mimebundle_.\nNumpy arrays with structured dtypes can now be converted to PyArray, provided the fields are aligned.\nPython named tuples can be converted to Julia named tuples.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.5-(2022-08-19)","page":"Release Notes","title":"0.9.5 (2022-08-19)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Adds PythonCall.GC.disable() and PythonCall.GC.enable().\nExperimental new function juliacall.interactive() allows the Julia async event loop to run in the background of the Python REPL.\nExperimental new IPython extension juliacall.ipython providing the %julia and %%julia magics for executing Julia code.\nExperimental new module juliacall.importer allowing you to write Python modules in Julia.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.4-(2022-07-26)","page":"Release Notes","title":"0.9.4 (2022-07-26)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.3-(2022-07-02)","page":"Release Notes","title":"0.9.3 (2022-07-02)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#0.9.2-(2022-07-02)","page":"Release Notes","title":"0.9.2 (2022-07-02)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Many Julia CLI options (such sysimage or number of threads) can be set from JuliaCall.\nBug fixes.","category":"page"},{"location":"releasenotes/#0.9.1-(2022-06-18)","page":"Release Notes","title":"0.9.1 (2022-06-18)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"PyArray can be constructed using the __array_struct__ part of the Numpy array interface. Constructing PyArray(x) is now about 50x faster, or 175x faster if you fully specify the type.\nJuliaCall can now be imported on Apple M1.","category":"page"},{"location":"releasenotes/#0.9.0-(2022-05-27)","page":"Release Notes","title":"0.9.0 (2022-05-27)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking. Removes getpy: you may now overload Py directly, which now need not always return a new object (e.g. for singletons or wrappers).\nBreaking. Conversion rules no longer take a new object every time.\nBreaking. Improved Tables-interface support for PyPandasDataFrame: better inferred column types; better handling of non-string column names; columns are usually wrappers (PyArray or PyList). Constructor arguments have changed. Dict methods have been removed (basically only the Tables interface is supported).\nBreaking. A Py which is convertible to PyTable is no longer considered to be a table itself; you must convert explicitly.\nAdds pyhasitem and 3-arg pygetitem.\nExtends Base.get, Base.get!, Base.haskey and 2-arg Base.hash for Py.\nPyArray can now have any element type when the underlying array is of Python objects.\nAdds ArrayValue.to_numpy().\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.8.0-(2022-03-17)","page":"Release Notes","title":"v0.8.0 (2022-03-17)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking: Removes pymethod and pyclass. In the future, pyclass may become sugar for types.new_class (namely you can specify a metaclass).\nAdds pyfunc, pyclassmethod, pystaticmethod and pyproperty.\npyconvert_add_rule is now documented. Its semantics have changed, including the separator of the first argument from / to :.\nA pandas value is now converted to missing.\nA NaN in a PyPandasDataFrame is converted to missing.\nBreaking: Removes using and As from JuliaCall.\nAdds convert to JuliaCall (replacing As).\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.6.1-(2022-02-21)","page":"Release Notes","title":"v0.6.1 (2022-02-21)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Conversions from simple ctypes types, e.g. ctypes.c_float to Cfloat.\nConversions from simple numpy types, e.g. numpy.float32 to Float32.\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.6.0-(2022-02-17)","page":"Release Notes","title":"v0.6.0 (2022-02-17)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking: JuliaCall now uses JuliaPkg to manage Julia dependencies.\nBug fixes.","category":"page"},{"location":"releasenotes/#v0.5.1-(2022-01-24)","page":"Release Notes","title":"v0.5.1 (2022-01-24)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Bug fixes.","category":"page"},{"location":"releasenotes/#v0.5.0-(2021-12-11)","page":"Release Notes","title":"v0.5.0 (2021-12-11)","text":"","category":"section"},{"location":"releasenotes/","page":"Release Notes","title":"Release Notes","text":"Breaking: PythonCall now uses CondaPkg to manage Python dependencies.\nPython objects can be shared with PyCall provided it uses the same interpreter, using methods PythonCall.Py(::PyCall.PyObject) and PyCall.PyObject(::PythonCall.Py).\nAdds PythonDisplay which displays objects by printing to Python's sys.stdout. Used automatically in IPython in addition to IPythonDisplay.\nRemoves the GLOBAL mode from @pyexec. Use global in the code instead.\nBug fixes.","category":"page"},{"location":"conversion-to-julia/#py2jl","page":"Python to Julia","title":"Conversion to Julia","text":"","category":"section"},{"location":"conversion-to-julia/#py2jl-conversion","page":"Python to Julia","title":"Conversion Rules","text":"","category":"section"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"The following table specifies the conversion rules used whenever converting a Python object to a Julia object. 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.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"From Julia, one can convert Python objects to a desired type using pyconvert(T, x) for example.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"From Python, the arguments to a Julia function will be converted according to these rules with T=Any.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"From To\nTop priority (wrapped values). \njuliacall.AnyValue Any\nVery high priority (arrays). \nObjects satisfying the buffer or array interface (inc. bytes, bytearray, array.array, numpy.ndarray) PyArray\nHigh priority (canonical conversions). \nNone Nothing\nbool Bool\nnumbers.Integral (inc. int) Integer (prefers Int, or BigInt on overflow)\nfloat Float64\ncomplex Complex{Float64}\nrange StepRange\nstr String\ntuple Tuple\ncollections.abc.Mapping (inc. dict) PyDict\ncollections.abc.Sequence (inc. list) PyList\ncollections.abc.Set (inc. set, frozenset) PySet\nio.IOBase (includes open files) PyIO\nBaseException PyException\ndatetime.date/datetime.time/datetime.datetime Date/Time/DateTime\ndatetime.timedelta Microsecond (or Millisecond or Second on overflow)\nnumpy.intXX/numpy.uintXX/numpy.floatXX IntXX/UIntXX/FloatXX\nStandard priority (other reasonable conversions). \nNone Missing\nbytes Vector{UInt8}, Vector{Int8}, String\nstr String, Symbol, Char, Vector{UInt8}, Vector{Int8}\nrange UnitRange\ncollections.abc.Mapping Dict\ncollections.abc.Iterable Vector, Set, Tuple, NamedTuple, Pair\ndatetime.timedelta Dates.CompoundPeriod\nnumbers.Integral Integer, Rational, Real, Number\nnumbers.Real AbstractFloat, Number, Missing/Nothing (if NaN)\nnumbers.Complex Complex, Number\nctypes.c_int and other integers Integer, Rational, Real, Number\nctypes.c_float/ctypes.c_double Cfloat/Cdouble, AbstractFloat, Real, Number\nctypes.c_voidp Ptr{Cvoid}, Ptr\nctypes.c_char_p Cstring, Ptr{Cchar}, Ptr\nctypes.c_wchar_p Cwstring, Ptr{Cwchar}, Ptr\nnumpy.bool_/numpy.intXX/numpy.uintXX/numpy.floatXX Bool, Integer, Rational, Real, Number\nObjects satisfying the buffer or array interface Array, AbstractArray\nLow priority (fallback to Py). \nAnything Py\nBottom priority (must be explicitly specified by excluding Py). \nObjects satisfying the buffer interface PyBuffer\nAnything PyRef","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"See here for an explanation of the Py* wrapper types (PyList, PyIO, etc).","category":"page"},{"location":"conversion-to-julia/#py2jl-conversion-custom","page":"Python to Julia","title":"Custom rules","text":"","category":"section"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"To add a custom conversion rule, you must define a function to do the conversion and call pyconvert_add_rule to register it.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"You must not do this while precompiling, so these calls will normally be in the __init__ function of your module.","category":"page"},{"location":"conversion-to-julia/","page":"Python to Julia","title":"Python to Julia","text":"PythonCall.pyconvert_add_rule","category":"page"},{"location":"conversion-to-julia/#PythonCall.Convert.pyconvert_add_rule","page":"Python to Julia","title":"PythonCall.Convert.pyconvert_add_rule","text":"pyconvert_add_rule(tname::String, T::Type, func::Function, priority::PyConvertPriority=PYCONVERT_PRIORITY_NORMAL)\n\nAdd a new conversion rule for pyconvert.\n\nArguments\n\ntname is a string of the form \"__module__:__qualname__\" identifying a Python type t, such as \"builtins:dict\" or \"sympy.core.symbol:Symbol\". This rule only applies to Python objects of this type.\nT is a Julia type, such that this rule only applies when the target type intersects with T.\nfunc is the function implementing the rule.\npriority determines whether to prioritise this rule above others.\n\nWhen pyconvert(R, x) is called, all rules such that typeintersect(T, R) != Union{} and pyisinstance(x, t) are considered. These rules are sorted first by priority, then by the specificity of t (e.g. bool is more specific than int is more specific than object) then by the order they were added. The rules are tried in turn until one succeeds.\n\nImplementing func\n\nfunc is called as func(S, x::Py) for some S <: T.\n\nIt must return one of:\n\npyconvert_return(ans) where ans is the result of the conversion (and must be an S).\npyconvert_unconverted() if the conversion was not possible (e.g. converting a list to Vector{Int} might fail if some of the list items are not integers).\n\nThe target type S is never a union or the empty type, i.e. it is always a data type or union-all.\n\nPriority\n\nMost rules should have priority PYCONVERT_PRIORITY_NORMAL (the default) which is for any reasonable conversion rule.\n\nUse priority PYCONVERT_PRIORITY_CANONICAL for canonical conversion rules. Immutable objects may be canonically converted to their corresponding Julia type, such as int to Integer. Mutable objects must be converted to a wrapper type, such that the original Python object can be retrieved. For example a list is canonically converted to PyList and not to a Vector. There should not be more than one canonical conversion rule for a given Python type.\n\nOther priorities are reserved for internal use.\n\n\n\n\n\n","category":"function"},{"location":"faq/#FAQ-and-Troubleshooting","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"","category":"section"},{"location":"faq/#Is-PythonCall/JuliaCall-thread-safe?","page":"FAQ & Troubleshooting","title":"Is PythonCall/JuliaCall thread safe?","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"No.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"However it is safe to use PythonCall with Julia with multiple threads, provided you only call Python code from the first thread. (Before v0.9.22, tricks such as disabling the garbage collector were required.)","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"From Python, to use JuliaCall with multiple threads you probably need to set PYTHON_JULIACALL_HANDLE_SIGNALS=yes before importing JuliaCall. This is because Julia intentionally causes segmentation faults as part of the GC safepoint mechanism. If unhandled, these segfaults will result in termination of the process. This is equivalent to starting julia with julia --handle-signals=yes, the default behavior in Julia. See discussion here for more information.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #201, #202, #529","category":"page"},{"location":"faq/#Issues-when-Numpy-arrays-are-expected","page":"FAQ & Troubleshooting","title":"Issues when Numpy arrays are expected","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"When a Julia array is passed to Python, it is wrapped as a ArrayValue. This type satisfies the Numpy array interface and the buffer protocol, so can be used in most places where a numpy array is valid.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"However, some Python packages have functions which assume the input is an actual Numpy array. You may see errors such as:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"AttributeError: Julia: type Array has no field dtype","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"To fix this you can convert the array x to a Numpy array as follows","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Py(x).to_numpy()","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"If the array is being mutated, you will need to pass the argument copy=false.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #280","category":"page"},{"location":"faq/#Heap-corruption-when-using-PyTorch","page":"FAQ & Troubleshooting","title":"Heap corruption when using PyTorch","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"On some systems, you may see an error like the following when using torch and juliacall:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Python(65251,0x104cf8580) malloc: Heap corruption detected, free list is damaged at 0x600001c17280\n*** Incorrect guard value: 1903002876\nPython(65251,0x104cf8580) malloc: *** set a breakpoint in malloc_error_break to debug\n[1] 65251 abort ipython","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"A solution is to ensure that juliacall is imported before torch.","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #215","category":"page"},{"location":"faq/#ccall-requires-the-compiler-error-when-importing-some-Python-libraries","page":"FAQ & Troubleshooting","title":"ccall requires the compiler error when importing some Python libraries","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"On some systems, you may see an error like the following when import e.g. matplotlib before juliacall:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"ERROR: `ccall` requires the compilerTraceback (most recent call last):\n File \"/home/dingraha/projects/pythoncall_import_error/run.py\", line 2, in \n from foo import Foo\n File \"/home/dingraha/projects/pythoncall_import_error/foo.py\", line 4, in \n import juliacall; jl = juliacall.newmodule(\"FooModule\")\n File \"/home/dingraha/projects/pythoncall_import_error/venv/lib/python3.9/site-packages/juliacall/__init__.py\", line 218, in \n init()\n File \"/home/dingraha/projects/pythoncall_import_error/venv/lib/python3.9/site-packages/juliacall/__init__.py\", line 214, in init\n raise Exception('PythonCall.jl did not start properly')\nException: PythonCall.jl did not start properly","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"The likely problem is that the \"other\" Python library (matplotlib, whatever) is loading the system libstdc++.so, which isn't compatible with the libstdc++.so that Julia ships with. Linux distributions with older libstdc++ versions seem more likely to suffer from this issue. The solution is to either:","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"use a Linux distribution with a more recent libstdc++\nimport juliacall before the other Python library, so that Julia's libstdc++ is loaded\nuse a Python from a conda environment, which will have a newer libstdc++ that is compatible with Julia's","category":"page"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Related issues: #255","category":"page"},{"location":"faq/#Can-I-use-JuliaCall-to-run-Julia-inside-applications-with-embedded-Python?","page":"FAQ & Troubleshooting","title":"Can I use JuliaCall to run Julia inside applications with embedded Python?","text":"","category":"section"},{"location":"faq/","page":"FAQ & Troubleshooting","title":"FAQ & Troubleshooting","text":"Yes, it may be possible. A good example of that is having Julia running inside the Python that is running inside Blender, as presented in this Discourse post. From the point that one has JuliaCall running inside Python, if it has access to the terminal, one can even launch a Julia REPL there, and if needed connect with VSCode Julia extension to it. The full Python script to install, launch JuliaCall, and launch a Julia REPL in Blender is here.","category":"page"},{"location":"pythoncall-reference/#py-reference","page":"Reference","title":"PythonCall API Reference","text":"","category":"section"},{"location":"pythoncall-reference/#Py-objects","page":"Reference","title":"Py objects","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Py\npybuiltins","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.Py","page":"Reference","title":"PythonCall.Core.Py","text":"Py(x)\n\nConvert x to a Python object, of type Py.\n\nConversion happens according to these rules.\n\nSuch an object supports attribute access (obj.attr), indexing (obj[idx]), calling (obj(arg1, arg2)), iteration (for x in obj), arithmetic (obj + obj2) and comparison (obj > obj2), among other things. These operations convert all their arguments to Py and return Py.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Core.pybuiltins","page":"Reference","title":"PythonCall.Core.pybuiltins","text":"pybuiltins\n\nAn object whose fields are the Python builtins, of type Py.\n\nFor example pybuiltins.None, pybuiltins.int, pybuiltins.ValueError.\n\n\n\n\n\n","category":"module"},{"location":"pythoncall-reference/#Constructors","page":"Reference","title":"Constructors","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions construct Python objects of builtin types from Julia values.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pybool\npycollist\npybytes\npycomplex\npydict\npyfloat\npyfrozenset\npyint\npylist\npyrange\npyrowlist\npyset\npyslice\npystr\npytuple","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pybool","page":"Reference","title":"PythonCall.Core.pybool","text":"pybool(x)\n\nConvert x to a Python bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycollist","page":"Reference","title":"PythonCall.Core.pycollist","text":"pycollist(x::AbstractArray)\n\nCreate a nested Python list-of-lists from the elements of x. For matrices, this is a list of columns.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pybytes","page":"Reference","title":"PythonCall.Core.pybytes","text":"pybytes(x)\n\nConvert x to a Python bytes.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycomplex","page":"Reference","title":"PythonCall.Core.pycomplex","text":"pycomplex(x=0.0)\npycomplex(re, im)\n\nConvert x to a Python complex, or create one from given real and imaginary parts.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydict","page":"Reference","title":"PythonCall.Core.pydict","text":"pydict(x)\npydict(; x...)\n\nConvert x to a Python dict. In the second form, the keys are strings.\n\nIf x is a Python object, this is equivalent to dict(x) in Python. Otherwise x must iterate over key-value pairs.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyfloat","page":"Reference","title":"PythonCall.Core.pyfloat","text":"pyfloat(x=0.0)\n\nConvert x to a Python float.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyfrozenset","page":"Reference","title":"PythonCall.Core.pyfrozenset","text":"pyfrozenset(x=())\n\nConvert x to a Python frozenset.\n\nIf x is a Python object, this is equivalent to frozenset(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyint","page":"Reference","title":"PythonCall.Core.pyint","text":"pyint(x=0)\n\nConvert x to a Python int.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylist","page":"Reference","title":"PythonCall.Core.pylist","text":"pylist(x=())\n\nConvert x to a Python list.\n\nIf x is a Python object, this is equivalent to list(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrange","page":"Reference","title":"PythonCall.Core.pyrange","text":"pyrange([[start], [stop]], [step])\n\nConstruct a Python range. Unspecified arguments default to None.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrowlist","page":"Reference","title":"PythonCall.Core.pyrowlist","text":"pyrowlist(x::AbstractArray)\n\nCreate a nested Python list-of-lists from the elements of x. For matrices, this is a list of rows.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyset","page":"Reference","title":"PythonCall.Core.pyset","text":"pyset(x=())\n\nConvert x to a Python set.\n\nIf x is a Python object, this is equivalent to set(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyslice","page":"Reference","title":"PythonCall.Core.pyslice","text":"pyslice([start], stop, [step])\n\nConstruct a Python slice. Unspecified arguments default to None.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pystr","page":"Reference","title":"PythonCall.Core.pystr","text":"pystr(x)\n\nConvert x to a Python str.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pytuple","page":"Reference","title":"PythonCall.Core.pytuple","text":"pytuple(x=())\n\nConvert x to a Python tuple.\n\nIf x is a Python object, this is equivalent to tuple(x) in Python. Otherwise x must be iterable.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Builtins","page":"Reference","title":"Builtins","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions mimic the Python builtin functions or keywords of the same name.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyall\npyany\npyascii\npycall\npycallable\npycompile\npycontains\npydelattr\npydelitem\npydir\npyeval\n@pyeval\npyexec\n@pyexec\npygetattr\npygetitem\npyhasattr\npyhasitem\npyhash\npyhelp\npyimport\npyin\npyis\npyisinstance\npyissubclass\npyiter\npylen\npynext\npyprint\npyrepr\npysetattr\npysetitem\npytype(::Any)\npywith","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pyall","page":"Reference","title":"PythonCall.Core.pyall","text":"pyall(x)\n\nEquivalent to all(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyany","page":"Reference","title":"PythonCall.Core.pyany","text":"pyany(x)\n\nEquivalent to any(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyascii","page":"Reference","title":"PythonCall.Core.pyascii","text":"pyascii(x)\n\nEquivalent to ascii(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycall","page":"Reference","title":"PythonCall.Core.pycall","text":"pycall(f, args...; kwargs...)\n\nCall the Python object f with the given arguments.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycallable","page":"Reference","title":"PythonCall.Core.pycallable","text":"pycallable(x)\n\nEquivalent to callable(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycompile","page":"Reference","title":"PythonCall.Core.pycompile","text":"pycompile(...)\n\nEquivalent to compile(...) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycontains","page":"Reference","title":"PythonCall.Core.pycontains","text":"pycontains(x, v)\n\nEquivalent to v in x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydelattr","page":"Reference","title":"PythonCall.Core.pydelattr","text":"pydelattr(x, k)\n\nEquivalent to delattr(x, k) or del x.k in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydelitem","page":"Reference","title":"PythonCall.Core.pydelitem","text":"pydelitem(x, k)\n\nEquivalent to delitem(x, k) or del x[k] in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydir","page":"Reference","title":"PythonCall.Core.pydir","text":"pydir(x)\n\nEquivalent to dir(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyeval","page":"Reference","title":"PythonCall.Core.pyeval","text":"pyeval([T=Py], code, globals, locals=nothing)\n\nEvaluate the given Python code, returning the result as a T.\n\nIf globals is a Module, then a persistent dict unique to that module is used.\n\nBy default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.\n\nSee also @pyeval.\n\nExamples\n\nThe following computes 1.1+2.2 in the Main module as a Float64:\n\npyeval(Float64, \"x+y\", Main, (x=1.1, y=2.2)) # returns 3.3\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.@pyeval","page":"Reference","title":"PythonCall.Core.@pyeval","text":"@pyeval [inputs =>] code [=> T]\n\nEvaluate the given code in a new local scope and return the answer as a T.\n\nThe global scope is persistent and unique to the current module.\n\nThe code must be a literal string or command.\n\nThe inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.\n\nExamples\n\nThe following computes 1.1+2.2 and returns a Float64:\n\n@pyeval (x=1.1, y=2.2) => `x+y` => Float64 # returns 3.3\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#PythonCall.Core.pyexec","page":"Reference","title":"PythonCall.Core.pyexec","text":"pyexec([T=Nothing], code, globals, locals=nothing)\n\nExecute the given Python code.\n\nIf globals is a Module, then a persistent dict unique to that module is used.\n\nBy default the code runs in global scope (i.e. locals===globals). To use a temporary local scope, set locals to (), or to a NamedTuple of variables to include in the scope.\n\nIf T==Nothing then returns nothing. Otherwise T must be a concrete NamedTuple type and the corresponding items from locals are extracted and returned.\n\nSee also @pyexec.\n\nExamples\n\nThe following computes 1.1+2.2 in the Main module as a Float64:\n\npyexec(@NamedTuple{ans::Float64}, \"ans=x+y\", Main, (x=1.1, y=2.2)) # returns (ans = 3.3,)\n\nMarking variables as global saves them into the module scope, so that they are available in subsequent invocations:\n\npyexec(\"global x; x=12\", Main)\npyeval(Int, \"x\", Main) # returns 12\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.@pyexec","page":"Reference","title":"PythonCall.Core.@pyexec","text":"@pyexec [inputs =>] code [=> outputs]\n\nExecute the given code in a new local scope.\n\nThe global scope is persistent and unique to the current module.\n\nThe code must be a literal string or command.\n\nThe inputs is a tuple of inputs of the form v=expr to be included in the local scope. Only v is required, expr defaults to v.\n\nThe outputs is a tuple of outputs of the form x::T=v, meaning that v is extracted from locals, converted to T and assigned to x. Only x is required: T defaults to Py and v defaults to x.\n\nExamples\n\nThe following computes 1.1+2.2 and assigns its value to ans as a Float64:\n\n@pyexec (x=1.1, y=2.2) => `ans=x+y` => ans::Float64 # returns 3.3\n\nMarking variables as global saves them into the module scope, so that they are available in subsequent invocations:\n\n@pyexec `global x; x=12`\n@pyeval `x` => Int # returns 12\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#PythonCall.Core.pygetattr","page":"Reference","title":"PythonCall.Core.pygetattr","text":"pygetattr(x, k, [d])\n\nEquivalent to getattr(x, k) or x.k in Python.\n\nIf d is specified, it is returned if the attribute does not exist.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pygetitem","page":"Reference","title":"PythonCall.Core.pygetitem","text":"pygetitem(x, k, [d])\n\nEquivalent x[k] in Python.\n\nIf d is specified, it is returned if the item does not exist (i.e. if x[k] raises a KeyError or IndexError).\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhasattr","page":"Reference","title":"PythonCall.Core.pyhasattr","text":"pyhasattr(x, k)\n\nEquivalent to hasattr(x, k) in Python.\n\nTests if getattr(x, k) raises an AttributeError.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhasitem","page":"Reference","title":"PythonCall.Core.pyhasitem","text":"pyhasitem(x, k)\n\nTest if pygetitem(x, k) raises a KeyError or AttributeError.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhash","page":"Reference","title":"PythonCall.Core.pyhash","text":"pyhash(x)\n\nEquivalent to hash(x) in Python, converted to an Integer.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyhelp","page":"Reference","title":"PythonCall.Core.pyhelp","text":"pyhelp([x])\n\nEquivalent to help(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimport","page":"Reference","title":"PythonCall.Core.pyimport","text":"pyimport(m)\npyimport(m => k)\npyimport(m => (k1, k2, ...))\npyimport(m1, m2, ...)\n\nImport a module m, or an attribute k, or a tuple of attributes.\n\nIf several arguments are given, return the results of importing each one in a tuple.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyin","page":"Reference","title":"PythonCall.Core.pyin","text":"pyin(v, x)\n\nEquivalent to v in x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyis","page":"Reference","title":"PythonCall.Core.pyis","text":"pyis(x, y)\n\nTrue if x and y are the same Python object. Equivalent to x is y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyisinstance","page":"Reference","title":"PythonCall.Core.pyisinstance","text":"pyisinstance(x, t)\n\nTest if x is of type t. Equivalent to isinstance(x, t) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyissubclass","page":"Reference","title":"PythonCall.Core.pyissubclass","text":"pyissubclass(s, t)\n\nTest if s is a subclass of t. Equivalent to issubclass(s, t) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyiter","page":"Reference","title":"PythonCall.Core.pyiter","text":"pyiter(x)\n\nEquivalent to iter(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylen","page":"Reference","title":"PythonCall.Core.pylen","text":"pylen(x)\n\nThe length of x. Equivalent to len(x) in Python, converted to an Integer.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pynext","page":"Reference","title":"PythonCall.Core.pynext","text":"pynext(x)\n\nEquivalent to next(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyprint","page":"Reference","title":"PythonCall.Core.pyprint","text":"pyprint(...)\n\nEquivalent to print(...) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrepr","page":"Reference","title":"PythonCall.Core.pyrepr","text":"pyrepr(x)\n\nEquivalent to repr(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pysetattr","page":"Reference","title":"PythonCall.Core.pysetattr","text":"pysetattr(x, k, v)\n\nEquivalent to setattr(x, k, v) or x.k = v in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pysetitem","page":"Reference","title":"PythonCall.Core.pysetitem","text":"pysetitem(x, k, v)\n\nEquivalent to setitem(x, k, v) or x[k] = v in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pytype-Tuple{Any}","page":"Reference","title":"PythonCall.Core.pytype","text":"pytype(x)\n\nThe Python type of x.\n\n\n\n\n\n","category":"method"},{"location":"pythoncall-reference/#PythonCall.Core.pywith","page":"Reference","title":"PythonCall.Core.pywith","text":"pywith(f, o, d=nothing)\n\nEquivalent to with o as x: f(x) in Python, where x is a Py.\n\nOn success, the value of f(x) is returned.\n\nIf an exception occurs but is suppressed then d is returned.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Conversion-to-Julia","page":"Reference","title":"Conversion to Julia","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions convert Python values to Julia values, using the rules documented here.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyconvert\n@pyconvert","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pyconvert","page":"Reference","title":"PythonCall.Core.pyconvert","text":"pyconvert(T, x, [d])\n\nConvert the Python object x to a T.\n\nIf d is specified, it is returned on failure instead of throwing an error.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Convert.@pyconvert","page":"Reference","title":"PythonCall.Convert.@pyconvert","text":"@pyconvert(T, x, [onfail])\n\nConvert the Python object x to a T.\n\nOn failure, evaluates to onfail, which defaults to return pyconvert_unconverted() (mainly useful for writing conversion rules).\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#Wrap-Julia-values","page":"Reference","title":"Wrap Julia values","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions explicitly wrap Julia values into Python objects, documented here.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"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.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyjl\npyjlraw\npyisjl\npyjlvalue\npybinaryio\npytextio","category":"page"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyjl","page":"Reference","title":"PythonCall.JlWrap.pyjl","text":"pyjl([t=pyjltype(x)], x)\n\nCreate a Python object wrapping the Julia object x.\n\nIf x is mutable, then mutating the returned object also mutates x, and vice versa.\n\nIts Python type is normally inferred from the type of x, but can be specified with t.\n\nFor 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.\n\nTo define a custom conversion for your type T, overload pyjltype(::T).\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyjlraw","page":"Reference","title":"PythonCall.JlWrap.pyjlraw","text":"pyjlraw(v)\n\nCreate a Python object wrapping the Julia object x.\n\nIt 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.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyisjl","page":"Reference","title":"PythonCall.JlWrap.pyisjl","text":"pyisjl(x)\n\nTest whether x is a wrapped Julia value, namely an instance of juliacall.ValueBase.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyjlvalue","page":"Reference","title":"PythonCall.JlWrap.pyjlvalue","text":"pyjlvalue(x)\n\nExtract the value from the wrapped Julia value x.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pybinaryio","page":"Reference","title":"PythonCall.JlWrap.pybinaryio","text":"pybinaryio(io::IO)\n\nWrap io as a Python binary IO object.\n\nThis is the default behaviour of Py(io).\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pytextio","page":"Reference","title":"PythonCall.JlWrap.pytextio","text":"pytextio(io::IO)\n\nWrap io as a Python text IO object.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Arithmetic","page":"Reference","title":"Arithmetic","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions are equivalent to the corresponding Python arithmetic operators.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"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.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pyneg\npypos\npyabs\npyinv\npyindex\npyadd\npysub\npymul\npymatmul\npypow\npyfloordiv\npytruediv\npymod\npydivmod\npylshift\npyrshift\npyand\npyxor\npyor\npyiadd\npyisub\npyimul\npyimatmul\npyipow\npyifloordiv\npyitruediv\npyimod\npyilshift\npyirshift\npyiand\npyixor\npyior","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pyneg","page":"Reference","title":"PythonCall.Core.pyneg","text":"pyneg(x)\n\nEquivalent to -x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pypos","page":"Reference","title":"PythonCall.Core.pypos","text":"pypos(x)\n\nEquivalent to +x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyabs","page":"Reference","title":"PythonCall.Core.pyabs","text":"pyabs(x)\n\nEquivalent to abs(x) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyinv","page":"Reference","title":"PythonCall.Core.pyinv","text":"pyinv(x)\n\nEquivalent to ~x in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyindex","page":"Reference","title":"PythonCall.Core.pyindex","text":"pyindex(x)\n\nConvert x losslessly to an int.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyadd","page":"Reference","title":"PythonCall.Core.pyadd","text":"pyadd(x, y)\n\nEquivalent to x + y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pysub","page":"Reference","title":"PythonCall.Core.pysub","text":"pysub(x, y)\n\nEquivalent to x - y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pymul","page":"Reference","title":"PythonCall.Core.pymul","text":"pymul(x, y)\n\nEquivalent to x * y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pymatmul","page":"Reference","title":"PythonCall.Core.pymatmul","text":"pymatmul(x, y)\n\nEquivalent to x @ y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pypow","page":"Reference","title":"PythonCall.Core.pypow","text":"pypow(x, y, z=None)\n\nEquivalent to x ** y or pow(x, y, z) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyfloordiv","page":"Reference","title":"PythonCall.Core.pyfloordiv","text":"pyfloordiv(x, y)\n\nEquivalent to x // y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pytruediv","page":"Reference","title":"PythonCall.Core.pytruediv","text":"pytruediv(x, y)\n\nEquivalent to x / y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pymod","page":"Reference","title":"PythonCall.Core.pymod","text":"pymod(x, y)\n\nEquivalent to x % y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydivmod","page":"Reference","title":"PythonCall.Core.pydivmod","text":"pydivmod(x, y)\n\nEquivalent to divmod(x, y) in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylshift","page":"Reference","title":"PythonCall.Core.pylshift","text":"pylshift(x, y)\n\nEquivalent to x << y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyrshift","page":"Reference","title":"PythonCall.Core.pyrshift","text":"pyrshift(x, y)\n\nEquivalent to x >> y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyand","page":"Reference","title":"PythonCall.Core.pyand","text":"pyand(x, y)\n\nEquivalent to x & y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyxor","page":"Reference","title":"PythonCall.Core.pyxor","text":"pyxor(x, y)\n\nEquivalent to x ^ y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyor","page":"Reference","title":"PythonCall.Core.pyor","text":"pyor(x, y)\n\nEquivalent to x | y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyiadd","page":"Reference","title":"PythonCall.Core.pyiadd","text":"pyiadd(x, y)\n\nIn-place add. x = pyiadd(x, y) is equivalent to x += y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyisub","page":"Reference","title":"PythonCall.Core.pyisub","text":"pyisub(x, y)\n\nIn-place subtract. x = pyisub(x, y) is equivalent to x -= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimul","page":"Reference","title":"PythonCall.Core.pyimul","text":"pyimul(x, y)\n\nIn-place multiply. x = pyimul(x, y) is equivalent to x *= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimatmul","page":"Reference","title":"PythonCall.Core.pyimatmul","text":"pyimatmul(x, y)\n\nIn-place matrix multiply. x = pyimatmul(x, y) is equivalent to x @= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyipow","page":"Reference","title":"PythonCall.Core.pyipow","text":"pyipow(x, y, z=None)\n\nIn-place power. x = pyipow(x, y) is equivalent to x **= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyifloordiv","page":"Reference","title":"PythonCall.Core.pyifloordiv","text":"pyifloordiv(x, y)\n\nIn-place floor divide. x = pyifloordiv(x, y) is equivalent to x //= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyitruediv","page":"Reference","title":"PythonCall.Core.pyitruediv","text":"pyitruediv(x, y)\n\nIn-place true division. x = pyitruediv(x, y) is equivalent to x /= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyimod","page":"Reference","title":"PythonCall.Core.pyimod","text":"pyimod(x, y)\n\nIn-place subtraction. x = pyimod(x, y) is equivalent to x %= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyilshift","page":"Reference","title":"PythonCall.Core.pyilshift","text":"pyilshift(x, y)\n\nIn-place left shift. x = pyilshift(x, y) is equivalent to x <<= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyirshift","page":"Reference","title":"PythonCall.Core.pyirshift","text":"pyirshift(x, y)\n\nIn-place right shift. x = pyirshift(x, y) is equivalent to x >>= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyiand","page":"Reference","title":"PythonCall.Core.pyiand","text":"pyiand(x, y)\n\nIn-place and. x = pyiand(x, y) is equivalent to x &= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyixor","page":"Reference","title":"PythonCall.Core.pyixor","text":"pyixor(x, y)\n\nIn-place xor. x = pyixor(x, y) is equivalent to x ^= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyior","page":"Reference","title":"PythonCall.Core.pyior","text":"pyior(x, y)\n\nIn-place or. x = pyior(x, y) is equivalent to x |= y in Python.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Logic","page":"Reference","title":"Logic","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions are equivalent to the corresponding Python logical operators.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"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.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Note that the binary operators by default return Py (not Bool) since comparisons in Python do not necessarily return bool.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pytruth\npynot\npyeq\npyne\npyle\npylt\npyge\npygt","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pytruth","page":"Reference","title":"PythonCall.Core.pytruth","text":"pytruth(x)\n\nThe truthyness of x. Equivalent to bool(x) in Python, converted to a Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pynot","page":"Reference","title":"PythonCall.Core.pynot","text":"pynot(x)\n\nThe falsyness of x. Equivalent to not x in Python, converted to a Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyeq","page":"Reference","title":"PythonCall.Core.pyeq","text":"pyeq(x, y)\npyeq(Bool, x, y)\n\nEquivalent to x == y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyne","page":"Reference","title":"PythonCall.Core.pyne","text":"pyne(x, y)\npyne(Bool, x, y)\n\nEquivalent to x != y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyle","page":"Reference","title":"PythonCall.Core.pyle","text":"pyle(x, y)\npyle(Bool, x, y)\n\nEquivalent to x <= y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pylt","page":"Reference","title":"PythonCall.Core.pylt","text":"pylt(x, y)\npylt(Bool, x, y)\n\nEquivalent to x < y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyge","page":"Reference","title":"PythonCall.Core.pyge","text":"pyge(x, y)\npyge(Bool, x, y)\n\nEquivalent to x >= y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pygt","page":"Reference","title":"PythonCall.Core.pygt","text":"pygt(x, y)\npygt(Bool, x, y)\n\nEquivalent to x > y in Python. The second form converts to Bool.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Create-classes","page":"Reference","title":"Create classes","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions can be used to create new Python classes where the functions are implemented in Julia. You can instead use @pyeval etc. to create pure-Python classes.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"pytype(::Any, ::Any, ::Any)\npyfunc\npyclassmethod\npystaticmethod\npyproperty","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pytype-Tuple{Any, Any, Any}","page":"Reference","title":"PythonCall.Core.pytype","text":"pytype(name, bases, dict)\n\nCreate a new type. Equivalent to type(name, bases, dict) in Python.\n\nIf bases is not a Python object, it is converted to one using pytuple.\n\nThe dict may either by a Python object or a Julia iterable. In the latter case, each item may either be a name => value pair or a Python object with a __name__ attribute.\n\nIn order to use a Julia Function as an instance method, it must be wrapped into a Python function with pyfunc. Similarly, see also pyclassmethod, pystaticmethod or pyproperty. In all these cases, the arguments passed to the function always have type Py. See the example below.\n\nExample\n\nFoo = pytype(\"Foo\", (), [\n \"__module__\" => \"__main__\",\n\n pyfunc(\n name = \"__init__\",\n doc = \"\"\"\n Specify x and y to store in the Foo.\n\n If omitted, y defaults to None.\n \"\"\",\n function (self, x, y = nothing)\n self.x = x\n self.y = y\n return\n end,\n ),\n\n pyfunc(\n name = \"__repr__\",\n self -> \"Foo($(self.x), $(self.y))\",\n ),\n\n pyclassmethod(\n name = \"frompair\",\n doc = \"Construct a Foo from a tuple of length two.\",\n (cls, xy) -> cls(xy...),\n ),\n\n pystaticmethod(\n name = \"hello\",\n doc = \"Prints a friendly greeting.\",\n (name) -> println(\"Hello, $name\"),\n ),\n\n \"xy\" => pyproperty(\n doc = \"A tuple of x and y.\",\n get = (self) -> (self.x, self.y),\n set = function (self, xy)\n (x, y) = xy\n self.x = x\n self.y = y\n nothing\n end,\n ),\n])\n\n\n\n\n\n","category":"method"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyfunc","page":"Reference","title":"PythonCall.JlWrap.pyfunc","text":"pyfunc(f; [name], [qualname], [doc], [signature])\n\nWrap the callable f as an ordinary Python function.\n\nThe name, qualname, docstring or signature can optionally be set with name, qualname, doc or signature.\n\nUnlike Py(f) (or pyjl(f)), the arguments passed to f are always of type Py, i.e. they are never converted.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyclassmethod","page":"Reference","title":"PythonCall.JlWrap.pyclassmethod","text":"pyclassmethod(f; ...)\n\nConvert callable f to a Python class method.\n\nIf f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Keyword arguments are passed to pyfunc.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pystaticmethod","page":"Reference","title":"PythonCall.JlWrap.pystaticmethod","text":"pystaticmethod(f; ...)\n\nConvert callable f to a Python static method.\n\nIf f is not a Python object (e.g. if f is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to f are always of type Py. Any keyword arguments are passed to pyfunc.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.JlWrap.pyproperty","page":"Reference","title":"PythonCall.JlWrap.pyproperty","text":"pyproperty(; get=nothing, set=nothing, del=nothing, doc=nothing)\npyproperty(get)\n\nCreate a Python property with the given getter, setter and deleter.\n\nIf get, set or del is not a Python object (e.g. if it is a Function) then it is converted to one with pyfunc. In particular this means the arguments passed to it are always of type Py.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#python-wrappers","page":"Reference","title":"Wrapper types","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"The following types wrap a Python object, giving it the semantics of a Julia object. For example PyList(x) interprets the Python sequence x as a Julia abstract vector.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Apart from a few fundamental immutable types, conversion from Python to Julia Any will return a wrapper type such as one of these, or simply Py if no wrapper type is suitable.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"PyList\nPySet\nPyDict\nPyIterable\nPyArray\nPyIO\nPyTable\nPyPandasDataFrame\nPyObjectArray\nPyException","category":"page"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyList","page":"Reference","title":"PythonCall.Wrap.PyList","text":"PyList{T=Py}([x])\n\nWraps the Python list x (or anything satisfying the sequence interface) as an AbstractVector{T}.\n\nIf x is not a Python object, it is converted to one using pylist.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PySet","page":"Reference","title":"PythonCall.Wrap.PySet","text":"PySet{T=Py}([x])\n\nWraps the Python set x (or anything satisfying the set interface) as an AbstractSet{T}.\n\nIf x is not a Python object, it is converted to one using pyset.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyDict","page":"Reference","title":"PythonCall.Wrap.PyDict","text":"PyDict{K=Py,V=Py}([x])\n\nWraps the Python dict x (or anything satisfying the mapping interface) as an AbstractDict{K,V}.\n\nIf x is not a Python object, it is converted to one using pydict.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyIterable","page":"Reference","title":"PythonCall.Wrap.PyIterable","text":"PyIterable{T=Py}(x)\n\nThis object iterates over iterable Python object x, yielding values of type T.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyArray","page":"Reference","title":"PythonCall.Wrap.PyArray","text":"PyArray{T,N,M,L,R}(x; copy=true, array=true, buffer=true)\n\nWrap the Python array x as a Julia AbstractArray{T,N}.\n\nThe input x can be bytes, bytearray, array.array, numpy.ndarray or anything satisfying the buffer protocol (if buffer=true) or the numpy array interface (if array=true).\n\nIf copy=false then the resulting array is guaranteed to directly wrap the data in x. If copy=true then a copy is taken if necessary to produce an array.\n\nThe type parameters are all optional, and are:\n\nT: The element type.\nN: The number of dimensions.\nM: True if the array is mutable.\nL: True if the array supports fast linear indexing.\nR: The element type of the underlying buffer. Often equal to T.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyIO","page":"Reference","title":"PythonCall.Wrap.PyIO","text":"PyIO(x; own=false, text=missing, line_buffering=false, buflen=4096)\n\nWrap the Python IO stream x as a Julia IO stream.\n\nWhen this goes out of scope and is finalized, it is automatically flushed. If own=true then it is also closed.\n\nIf text=false then x must be a binary stream and arbitrary binary I/O is possible. If text=true then x must be a text stream and only UTF-8 must be written (i.e. use print not write). If text is not specified then it is chosen automatically. If x is a text stream and you really need a binary stream, then often PyIO(x.buffer) will work.\n\nIf line_buffering=true then output is flushed at each line.\n\nFor efficiency, reads and writes are buffered before being sent to x. The size of the buffers is buflen. The buffers are cleared using flush.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyTable","page":"Reference","title":"PythonCall.Wrap.PyTable","text":"PyTable(x)\n\nWrap x as a Tables.jl-compatible table.\n\nPyTable is an abstract type. See PyPandasDataFrame for a concrete example.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Wrap.PyPandasDataFrame","page":"Reference","title":"PythonCall.Wrap.PyPandasDataFrame","text":"PyPandasDataFrame(x; [indexname::Union{Nothing,Symbol}], [columnnames::Function], [columntypes::Function])\n\nWraps the pandas DataFrame x as a Tables.jl-compatible table.\n\nindexname: The name of the column including the index. The default is nothing, meaning to exclude the index.\ncolumnnames: A function mapping the Python column name (a Py) to the Julia one (a Symbol). The default is x -> Symbol(x).\ncolumntypes: A function taking the column name (a Symbol) and returning either the desired element type of the column, or nothing to indicate automatic inference.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.JlWrap.PyObjectArray","page":"Reference","title":"PythonCall.JlWrap.PyObjectArray","text":"PyObjectArray(undef, dims...)\nPyObjectArray(array)\n\nAn array of Pys which supports the Python buffer protocol.\n\nInternally, the objects are stored as an array of pointers.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#PythonCall.Core.PyException","page":"Reference","title":"PythonCall.Core.PyException","text":"PyException(x)\n\nWraps the Python exception x as a Julia Exception.\n\n\n\n\n\n","category":"type"},{"location":"pythoncall-reference/#python-wrappers-custom","page":"Reference","title":"Custom wrappers","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"Here is a minimal example of defining a wrapper type. You may add methods, fields and a supertype to the type to specialise its behaviour. See any of the above wrapper types for examples.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"# The new type with a field for the Python object being wrapped.\nstruct MyType\n py::Py\nend\n\n# Says that the object is a wrapper.\nispy(x::MyType) = true\n\n# Says how to access the underlying Python object.\nPy(x::MyType) = x.py","category":"page"},{"location":"pythoncall-reference/#@py-and-@pyconst","page":"Reference","title":"@py and @pyconst","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"@py\n@pyconst","category":"page"},{"location":"pythoncall-reference/#PythonCall.PyMacro.@py","page":"Reference","title":"PythonCall.PyMacro.@py","text":"@py expr\n\nEvaluate the given expression using Pythonic semantics.\n\nFor example:\n\nf(x, y) is translated to pycall(f, x, y)\nx + y is translated to pyadd(x, y)\nx === y is translated to pyis(x, y) (x is y in Python)\nx.foo is translated to pygetattr(x, \"foo\")\nimport x: f as g is translated to g = pyimport(\"x\" => \"f\") (from x import f as g in Python)\n\nCompound statements such as begin, if, while and for are supported.\n\nSee the online documentation for more details.\n\nwarning: Warning\nThis macro is experimental. It may be modified or removed in a future release.\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#PythonCall.Core.@pyconst","page":"Reference","title":"PythonCall.Core.@pyconst","text":"@pyconst ex\n\nEquivalent to Py(ex) but always returns the exact same Julia object.\n\nThat is, if foo() = @pyconst ex then foo() === foo().\n\nThe expression ex is evaluated the first time the code is run.\n\nIf ex is a string literal, the string is interned.\n\nDo not use this macro at the top level of a module. Instead, use pynew() and pycopy!().\n\n\n\n\n\n","category":"macro"},{"location":"pythoncall-reference/#The-Python-interpreter","page":"Reference","title":"The Python interpreter","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"These functions are not exported. They give information about which Python interpreter is being used.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"PythonCall.python_version\nPythonCall.python_executable_path\nPythonCall.python_library_path\nPythonCall.python_library_handle","category":"page"},{"location":"pythoncall-reference/#PythonCall.C.python_version","page":"Reference","title":"PythonCall.C.python_version","text":"python_version()\n\nThe version of Python, or missing if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.C.python_executable_path","page":"Reference","title":"PythonCall.C.python_executable_path","text":"python_executable_path()\n\nPath to the Python interpreter, or missing if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.C.python_library_path","page":"Reference","title":"PythonCall.C.python_library_path","text":"python_library_path()\n\nPath to libpython, or missing if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.C.python_library_handle","page":"Reference","title":"PythonCall.C.python_library_handle","text":"python_library_handle()\n\nHandle to the open libpython, or C_NULL if not known.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#Low-level-API","page":"Reference","title":"Low-level API","text":"","category":"section"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"The functions here are not exported. They are mostly unsafe in the sense that you can crash Julia by using them incorrectly.","category":"page"},{"location":"pythoncall-reference/","page":"Reference","title":"Reference","text":"PythonCall.pynew\nPythonCall.pyisnull\nPythonCall.pycopy!\nPythonCall.getptr\nPythonCall.pydel!\nPythonCall.unsafe_pynext","category":"page"},{"location":"pythoncall-reference/#PythonCall.Core.pynew","page":"Reference","title":"PythonCall.Core.pynew","text":"pynew([ptr])\n\nA new Py representing the Python object at ptr (NULL by default).\n\nIf ptr is given and non-NULL, this function steals a reference to the Python object it points at, i.e. the new Py object owns a reference.\n\nNote that NULL Python objects are not safe in the sense that most API functions will probably crash your Julia session if you pass a NULL argument.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pyisnull","page":"Reference","title":"PythonCall.Core.pyisnull","text":"pyisnull(x)\n\nTrue if the Python object x is NULL.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pycopy!","page":"Reference","title":"PythonCall.Core.pycopy!","text":"pycopy!(dst::Py, src)\n\nCopy the Python object src into dst, so that they both represent the same object.\n\nThis function exists to support module-level constant Python objects. It is illegal to call most PythonCall API functions at the top level of a module (i.e. before __init__() has run) so you cannot do const x = pything() at the top level. Instead do const x = pynew() at the top level then pycopy!(x, pything()) inside __init__().\n\nAssumes dst is NULL, otherwise a memory leak will occur.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.getptr","page":"Reference","title":"PythonCall.Core.getptr","text":"getptr(x)\n\nGet the underlying pointer from the Python object x.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.pydel!","page":"Reference","title":"PythonCall.Core.pydel!","text":"pydel!(x::Py)\n\nDelete the Python object x.\n\nDANGER! Use this function ONLY IF the Julia object x could have been garbage-collected anyway, i.e. was about to become unreachable. This means you MUST KNOW that no other part of the program has the Julia object x.\n\nThis decrements the reference count, sets the pointer to NULL and appends x to a cache of unused objects (PYNULL_CACHE).\n\nThis is an optimization to avoid excessive allocation and deallocation in Julia, which can be a significant source of slow-down in code which uses a lot of Python objects. It allows pynew() to pop an item from PYNULL_CACHE instead of allocating one, and avoids calling the relatively slow finalizer on x.\n\n\n\n\n\n","category":"function"},{"location":"pythoncall-reference/#PythonCall.Core.unsafe_pynext","page":"Reference","title":"PythonCall.Core.unsafe_pynext","text":"unsafe_pynext(x)\n\nReturn the next item in the iterator x. When there are no more items, return NULL.\n\n\n\n\n\n","category":"function"},{"location":"juliacall/#The-Python-module-JuliaCall","page":"Guide","title":"The Python module JuliaCall","text":"","category":"section"},{"location":"juliacall/#Installation","page":"Guide","title":"Installation","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"It's as simple as","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"pip install juliacall","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Developers may wish to clone the repo (https://github.com/JuliaPy/PythonCall.jl) directly and pip install the module in editable mode. You should add \"dev\":true, \"path\":\"../..\" to pysrc/juliacall/juliapkg.json to ensure you use the development version of PythonCall in conjunction with JuliaCall.","category":"page"},{"location":"juliacall/#Getting-started","page":"Guide","title":"Getting started","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"For interactive or scripting use, the simplest way to get started is:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"from juliacall import Main as jl","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"This loads a single variable jl which represents the Main module in Julia, from which all of Julia's functionality is available:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"jl.println(\"Hello from Julia!\")\n# Hello from Julia!\nx = jl.rand(range(10), 3, 5)\nx._jl_display()\n# 3×5 Matrix{Int64}:\n# 8 1 7 0 6\n# 9 2 1 4 0\n# 1 8 5 4 0\nimport numpy\nnumpy.sum(x, axis=0)\n# array([18, 11, 13, 8, 6], dtype=int64)","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"In this example:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"We called the jl.println function to print a message.\nWe called the jl.rand function to generate an array of random integers. Note that the first argument is range(10) which is converted to 0:9 in Julia.\nWe called its special _jl_display() to show it using Julia's display mechanism.\nWe called the numpy.sum function to sum each column of x. This automatically converted x to a NumPy array. (We could have done jl.sum(x, dims=1) too.)","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"If you are writing a package which uses Julia, then to avoid polluting the global Main namespace you instead should start with:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"import juliacall\njl = juliacall.newmodule(\"SomeName\")","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Julia modules have a special method seval which will evaluate a given piece of code given as a string in the module. This is most frequently used to import modules:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"from array import array\njl.seval(\"using Statistics\")\nx = array('i', [1, 2, 3])\njl.mean(x)\n# 2.0\ny = array('i', [2,4,8])\njl.cor(x, y)\n# 0.9819805060619657","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"What to read next:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"The main functionality of this package is in AnyValue objects, which represent Julia objects, documented here.\nIf you need to install Julia packages, read here.\nWhen you call a Julia function, such as jl.rand(...) in the above example, its arguments are converted to Julia according to this table and its return value is converted to Python according to this table.","category":"page"},{"location":"juliacall/#julia-deps","page":"Guide","title":"Managing Julia dependencies","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"JuliaCall manages its Julia dependencies using JuliaPkg.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"It will automatically download a suitable version of Julia if required.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"A Julia environment is also created, activated and populated with any required packages. If you are in a virtual or Conda environment, the environment is put there. Otherwise a global environment is used at ~/.julia/environments/pyjuliapkg.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"If your project requires any Julia packages, or a particular version of Julia itself, then create a file called juliapkg.json in your package. For example: Here is an example:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"{\n \"julia\": \"1.5\",\n \"packages\": {\n \"Example\": {\n \"uuid\": \"7876af07-990d-54b4-ab0e-23690620f79a\",\n \"version\": \"0.5, 0.6\"\n }\n }\n}","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Alternatively you can use add, rm, etc. from JuliaPkg to edit this file.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"See JuliaPkg for more details.","category":"page"},{"location":"juliacall/#julia-config","page":"Guide","title":"Configuration","text":"","category":"section"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"Some features of the Julia process, such as the optimization level or number of threads, may be configured in two ways:","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"As an -X argument to Python, such as -X juliacall-optlevel=3; or\nAs an environment variable, such as PYTHON_JULIACALL_OPTLEVEL=3.","category":"page"},{"location":"juliacall/","page":"Guide","title":"Guide","text":"-X option Environment Variable Description\n-X juliacall-home= PYTHON_JULIACALL_BINDIR= The directory containing the julia executable.\n-X juliacall-check-bounds= PYTHON_JULIACALL_CHECK_BOUNDS= Enable or disable bounds checking.\n-X juliacall-compile= PYTHON_JULIACALL_COMPILE= Enable or disable JIT compilation.\n-X juliacall-compiled-modules= PYTHON_JULIACALL_COMPILED_MODULES= Enable or disable incrementally compiling modules.\n-X juliacall-depwarn= PYTHON_JULIACALL_DEPWARN= Enable or disable deprecation warnings.\n-X juliacall-handle-signals= PYTHON_JULIACALL_HANDLE_SIGNALS= Enable or disable Julia signal handling.\n-X juliacall-inline= PYTHON_JULIACALL_INLINE= Enable or disable inlining.\n-X juliacall-min-optlevel=<0|1|2|3> PYTHON_JULIACALL_MIN_OPTLEVEL=<0|1|2|3> Optimization level.\n-X juliacall-optimize=<0|1|2|3> PYTHON_JULIACALL_OPTIMIZE=<0|1|2|3> Minimum optimization level.\n-X juliacall-procs= PYTHON_JULIACALL_PROCS= Launch N local worker process.\n-X juliacall-startup-file= PYTHON_JULIACALL_STARTUP_FILE= Enable or disable your startup.jl file.\n-X juliacall-sysimage= PYTHON_JULIACALL_SYSIMAGE= Use the given system image.\n-X juliacall-threads= PYTHON_JULIACALL_THREADS= Launch N threads.\n-X juliacall-warn-overwrite= PYTHON_JULIACALL_WARN_OVERWRITE= Enable or disable method overwrite warnings.\n-X juliacall-autoload-ipython-extension= PYTHON_JULIACALL_AUTOLOAD_IPYTHON_EXTENSION= Enable or disable IPython extension autoloading.","category":"page"},{"location":"compat/#Compatibility-Tools","page":"Compatibility Tools","title":"Compatibility Tools","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Some packages require a little extra help to work nicely with PythonCall.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Some of these are \"fixes\" that are silently applied for you, and some are just extra functions to bridge a gap. We aim to keep these as minimal as possible.","category":"page"},{"location":"compat/#Python-standard-library","page":"Compatibility Tools","title":"Python standard library","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Whenever a Python exception is displayed by Julia, sys.last_traceback and friends are set. This allows the post-mortem debugger pdb.pm() to work. Disable by setting PythonCall.CONFIG.auto_sys_last_traceback = false.","category":"page"},{"location":"compat/#Julia-standard-library","page":"Compatibility Tools","title":"Julia standard library","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Python objects can be serialised with the Serialization stdlib. This uses pickle library under the hood. You can opt into using dill instead by setting the environment variable JULIA_PYTHONCALL_PICKLE=\"dill\".","category":"page"},{"location":"compat/#Tabular-data-/-Pandas","page":"Compatibility Tools","title":"Tabular data / Pandas","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The abstract type PyTable is for wrapper types around Python tables, providing the Tables.jl interface. PyTable(x) is shorthand for pyconvert(PyTable, x).","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The subtype PyPandasDataFrame wraps a pandas.DataFrame.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"For example, if x is a pandas.DataFrame then PyTable(x) is a PyPandasDataFrame and DataFrame(PyTable(x)) is a DataFrame.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"In the other direction, the following functions can be used to convert any Tables.jl-compatible table to a Python table.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"pytable","category":"page"},{"location":"compat/#PythonCall.Compat.pytable","page":"Compatibility Tools","title":"PythonCall.Compat.pytable","text":"pytable(src, format=:pandas; ...)\n\nConstruct a Python table from the Tables.jl-compatible table src.\n\nThe format controls the type of the resulting table, and is one of:\n\n:pandas: A pandas.DataFrame. Keyword arguments are passed to the DataFrame constructor.\n:columns: A dict mapping column names to columns.\n:rows: A list of rows, which are namedtuples.\n:rowdicts: A list of rows, which are dicts.\n\n\n\n\n\n","category":"function"},{"location":"compat/#MatPlotLib-/-PyPlot-/-Seaborn","page":"Compatibility Tools","title":"MatPlotLib / PyPlot / Seaborn","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"MatPlotLib figures can be shown with Julia's display mechanism, like display(fig) or display(mime, fig).","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"This means that if you return a figure from a Jupyter or Pluto notebook cell, it will be shown. You can call display(plt.gcf()) to display the current figure.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"We also provide a simple MatPlotLib backend: mpl.use(\"module://juliacall.matplotlib\"). Now you can call plt.show() to display the figure with Julia's display mechanism. You can specify the format like plt.show(format=\"png\").","category":"page"},{"location":"compat/#Python-GUIs-(including-MatPlotLib)","page":"Compatibility Tools","title":"Python GUIs (including MatPlotLib)","text":"","category":"section"},{"location":"compat/#Event-loops","page":"Compatibility Tools","title":"Event loops","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"If for example you wish to use PyPlot in interactive mode (matplotlib.pyplot.ion()) then activating the correct event loop will allow it to work.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"PythonCall.event_loop_on\nPythonCall.event_loop_off","category":"page"},{"location":"compat/#PythonCall.Compat.event_loop_on","page":"Compatibility Tools","title":"PythonCall.Compat.event_loop_on","text":"event_loop_on(g::Symbol; interval=0.04, fix=false)\n\nActivate an event loop for the GUI framework g, so that the framework can run in the background of a Julia session.\n\nThe event loop runs every interval seconds. If fix is true and g is a Qt framework, then fix_qt_plugin_path is called.\n\nSupported values of g (and the Python module they relate to) are: :pyqt4 (PyQt4), :pyqt5 (PyQt5), :pyside (PySide), :pyside2 (PySide2), :gtk (gtk), :gtk3 (gi), :wx (wx), :tkinter (tkinter).\n\n\n\n\n\n","category":"function"},{"location":"compat/#PythonCall.Compat.event_loop_off","page":"Compatibility Tools","title":"PythonCall.Compat.event_loop_off","text":"event_loop_off(g::Symbol)\n\nTerminate the event loop g if it is running.\n\n\n\n\n\n","category":"function"},{"location":"compat/#Qt-path-fix","page":"Compatibility Tools","title":"Qt path fix","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"PythonCall.fix_qt_plugin_path","category":"page"},{"location":"compat/#PythonCall.Compat.fix_qt_plugin_path","page":"Compatibility Tools","title":"PythonCall.Compat.fix_qt_plugin_path","text":"fix_qt_plugin_path()\n\nTry to set the QT_PLUGIN_PATH environment variable in Python, if not already set.\n\nThis fixes the problem that Qt does not know where to find its qt.conf file, because it always looks relative to sys.executable, which can be the Julia executable not the Python one when using this package.\n\nIf CONFIG.auto_fix_qt_plugin_path is true, then this is run automatically before PyQt4, PyQt5, PySide or PySide2 are imported.\n\n\n\n\n\n","category":"function"},{"location":"compat/#IPython","page":"Compatibility Tools","title":"IPython","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The juliacall IPython extension adds these features to your IPython session:","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The line magic %julia code executes the given Julia code in-line.\nThe cell magic %%julia executes a cell of Julia code.\nJulia's stdout and stderr are redirected to IPython.\nCalling display(x) from Julia will display x in IPython.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The extension is experimental and unstable - the API can change at any time.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"You can explicitly enable the extension with %load_ext juliacall, but it will automatically be loaded if juliacall is imported and IPython is detected. You can disable this behavior with an environment variable.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"The %%julia cell magic can synchronise variables between Julia and Python by listing them on the first line:","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"In [1]: %load_ext juliacall\n\nIn [2]: x = 2\n\nIn [3]: y = 8\n\nIn [4]: %%julia x y z\n ...: z = \"$x^$y = $(x^y)\";\n ...:\n ...:\n\nIn [5]: z\nOut[5]: '2^8 = 256'","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Also see the IPython docs for more information on extensions.","category":"page"},{"location":"compat/#Asynchronous-Julia-code-(including-Makie)","page":"Compatibility Tools","title":"Asynchronous Julia code (including Makie)","text":"","category":"section"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"Asynchronous Julia code will not normally run while Python is executing, unless it is in a separate thread.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"This can be fixed by calling jl.yield() periodically from Python code, allowing the Julia scheduler to run.","category":"page"},{"location":"compat/","page":"Compatibility Tools","title":"Compatibility Tools","text":"When working at the Python REPL, you may call juliacall.interactive() which will allow Julia async code to run while the prompt is showing. This will allow interactive plots such as Makie to work.","category":"page"},{"location":"#PythonCall-and-JuliaCall","page":"Home","title":"PythonCall & JuliaCall","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Bringing Python® and Julia together in seamless harmony:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Call Python code from Julia and Julia code from Python via a symmetric interface.\nSimple syntax, so the Python code looks like Python and the Julia code looks like Julia.\nIntuitive and flexible conversions between Julia and Python: anything can be converted, you are in control.\nFast non-copying conversion of numeric arrays in either direction: modify Python arrays (e.g. bytes, array.array, numpy.ndarray) from Julia or Julia arrays from Python.\nHelpful wrappers: interpret Python sequences, dictionaries, arrays, dataframes and IO streams as their Julia counterparts, and vice versa.\nBeautiful stack-traces.\nWorks anywhere: tested on Windows, MacOS and Linux, 32- and 64-bit, Julia Julia 1.6.1 upwards and Python 3.8 upwards.","category":"page"}] }