From ed981ffd69584ed6ffb49a9e6179372f88b7c329 Mon Sep 17 00:00:00 2001 From: Christopher Rowley Date: Sun, 31 May 2026 15:59:29 +0100 Subject: [PATCH 1/2] pass libptr by env var instead --- pysrc/juliacall/__init__.py | 18 +++++++++++------- src/C/context.jl | 7 +++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/pysrc/juliacall/__init__.py b/pysrc/juliacall/__init__.py index 33991fae..f99e7c2c 100644 --- a/pysrc/juliacall/__init__.py +++ b/pysrc/juliacall/__init__.py @@ -240,6 +240,11 @@ def args_from_config(config): jl_parse_opts(c.pointer(argc), c.pointer(argv)) assert argc.value == 0 + # override some environment variables + # we do this here because PythonCall is initialised during jl_init if it is in a sysimg + os.environ['JULIA_PYTHONCALL_EXECUTABLE'] = sys.executable or '' + os.environ['__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__'] = hex(c.pythonapi._handle) + # initialise julia try: jl_init = lib.jl_init_with_image__threading @@ -269,9 +274,7 @@ def jlstr(x): return 'raw"' + x + '"' script = ''' try - Base.require(Main, :CompilerSupportLibraries_jll) - global __PythonCall_libptr = Ptr{{Cvoid}}(UInt({})) - ENV["JULIA_PYTHONCALL_EXE"] = {} + import CompilerSupportLibraries_jll as _ using PythonCall catch err print(stderr, "ERROR: ") @@ -279,13 +282,14 @@ def jlstr(x): flush(stderr) rethrow() end - '''.format( - hex(c.pythonapi._handle), - jlstr(sys.executable or ''), - ) + ''' res = jl_eval(script.encode('utf8')) if res is None: raise Exception('PythonCall.jl did not start properly') + + # unset this env var so any other julia processes started do not think they are + # embedded in python + os.environ.pop('__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__', None) CONFIG['inited'] = True diff --git a/src/C/context.jl b/src/C/context.jl index 0a1c9eb6..6ccdab89 100644 --- a/src/C/context.jl +++ b/src/C/context.jl @@ -105,11 +105,14 @@ on_main_thread function init_context() - CTX.is_embedded = hasproperty(Base.Main, :__PythonCall_libptr) + CTX.is_embedded = haskey(ENV, "__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__") if CTX.is_embedded # In this case, getting a handle to libpython is easy - CTX.lib_ptr = Base.Main.__PythonCall_libptr::Ptr{Cvoid} + CTX.lib_ptr = Ptr{Cvoid}(parse(UInt, ENV["__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__"])) + # Delete the env var so subprocesses don't think they are embedded + delete!(ENV, "__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__") + # Initialise pointers from libpython init_pointers() # Check Python is initialized Py_IsInitialized() == 0 && error("Python is not already initialized.") From 573d7b996187bea9d5c2c3c3eb5cb54e46ab5d8f Mon Sep 17 00:00:00 2001 From: Christopher Rowley Date: Sun, 31 May 2026 16:00:59 +0100 Subject: [PATCH 2/2] update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1bc832e..47926555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog ## Unreleased -* Added option `lib` to JuliaCall. Setting this will skip the discovery subprocess. +* Add option `lib` to JuliaCall. Setting this will skip the discovery subprocess. +* Add support for using a system image in `juliacall` that has `PythonCall` baked in. * Bug fixes. ## 0.9.34 (2026-05-18)