Skip to content

Commit 79e8a44

Browse files
authored
Libptr by env (#781)
* pass libptr by env var instead * update changelog --------- Co-authored-by: Christopher Rowley <github.com/cjdoris>
1 parent 34d3f55 commit 79e8a44

3 files changed

Lines changed: 18 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Changelog
22

33
## Unreleased
4-
* Add method `pynext(x, d)` to return a default value `d` if there are no more elements.
54
* Add option `lib` to JuliaCall. Setting this will skip the discovery subprocess.
5+
* Add support for using a system image in `juliacall` that has `PythonCall` baked in.
6+
* Add method `pynext(x, d)` to return a default value `d` if there are no more elements.
67
* Bug fixes.
78

89
## 0.9.34 (2026-05-18)

pysrc/juliacall/__init__.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,11 @@ def args_from_config(config):
242242
jl_parse_opts(c.pointer(argc), c.pointer(argv))
243243
assert argc.value == 0
244244

245+
# override some environment variables
246+
# we do this here because PythonCall is initialised during jl_init if it is in a sysimg
247+
os.environ['JULIA_PYTHONCALL_EXECUTABLE'] = sys.executable or ''
248+
os.environ['__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__'] = hex(c.pythonapi._handle)
249+
245250
# initialise julia
246251
try:
247252
jl_init = lib.jl_init_with_image__threading
@@ -271,23 +276,22 @@ def jlstr(x):
271276
return 'raw"' + x + '"'
272277
script = '''
273278
try
274-
Base.require(Main, :CompilerSupportLibraries_jll)
275-
global __PythonCall_libptr = Ptr{{Cvoid}}(UInt({}))
276-
ENV["JULIA_PYTHONCALL_EXE"] = {}
279+
import CompilerSupportLibraries_jll as _
277280
using PythonCall
278281
catch err
279282
print(stderr, "ERROR: ")
280283
showerror(stderr, err, catch_backtrace())
281284
flush(stderr)
282285
rethrow()
283286
end
284-
'''.format(
285-
hex(c.pythonapi._handle),
286-
jlstr(sys.executable or ''),
287-
)
287+
'''
288288
res = jl_eval(script.encode('utf8'))
289289
if res is None:
290290
raise Exception('PythonCall.jl did not start properly')
291+
292+
# unset this env var so any other julia processes started do not think they are
293+
# embedded in python
294+
os.environ.pop('__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__', None)
291295

292296
CONFIG['inited'] = True
293297

src/C/context.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,14 @@ on_main_thread
105105

106106
function init_context()
107107

108-
CTX.is_embedded = hasproperty(Base.Main, :__PythonCall_libptr)
108+
CTX.is_embedded = haskey(ENV, "__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__")
109109

110110
if CTX.is_embedded
111111
# In this case, getting a handle to libpython is easy
112-
CTX.lib_ptr = Base.Main.__PythonCall_libptr::Ptr{Cvoid}
112+
CTX.lib_ptr = Ptr{Cvoid}(parse(UInt, ENV["__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__"]))
113+
# Delete the env var so subprocesses don't think they are embedded
114+
delete!(ENV, "__JULIA_PYTHONCALL_EMBEDDED_LIBPTR__")
115+
# Initialise pointers from libpython
113116
init_pointers()
114117
# Check Python is initialized
115118
Py_IsInitialized() == 0 && error("Python is not already initialized.")

0 commit comments

Comments
 (0)