# Exposing julia packages to python users

**URL:** <https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272>\
**Category:** General Usage\
**Tags:** python, pythoncall, package-extensions, package-development\
**Created:** [March 19, 2026, 10:04am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272 "2026-03-19T10:04:41Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![aris](https://avatars.discourse-cdn.com/v4/letter/a/258eb7/32.png) [@aris](https://discourse.julialang.org/u/aris)\
**Post date:** [March 19, 2026, 10:04am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/1 "2026-03-19T10:04:41Z")

</div>

Hello everyone.

I have a Julia package which I would like to expose to python users.

Seems the most obvious way would be using [juliacall](https://github.com/JuliaPy/PythonCall.jl), similar to how [diffeqpy](https://discourse.julialang.org/t/mixed-python-julia-package/117299/2) seems to do it. I tried working with that approach for now, but I’ve got a few questions.

- Would it be best to have the python code at a separate repository (like diffeqpy), or at the same one as the Julia code? Any (dis)advantages in either way?

- The package I’m working on has a `GLMakie` [extension](https://docs.julialang.org/en/v1/manual/code-loading/#man-extensions), which provides some very useful GUI capabilities. Seems like using `GLMakie` from juliacall is not seamless, and some [workarounds](https://github.com/JuliaPy/PythonCall.jl/issues/212) might be required. Has anybody managed to deal with this matter in an elegant way (e.g. wrap Makie functions with `juliacall.interactive()` somewhere in the python codebase)?

- More generally, would there be any pitfalls to avoid when working with Julia package extensions in this context?

- I was wondering whether the relatively recent updates in [AOT compilation](https://docs.julialang.org/en/v1/devdocs/aot/) would enable better solutions to this, exposing the same functionality while avoiding a Julia installation for the python user. Has anybody experimented with this?

- Any other methods or resources I’m missing here?

I was also thinking, since most people are probably not going to be migrating from python to Julia anytime soon, might be useful to have such information for Julia package developers available somewhere in the documentation?

Any help or comments would be much appreciated!

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 19, 2026, 4:56pm UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/2 "2026-03-19T16:56:30Z")

</div>

I don’t know how complex your package is or how long a single function call takes. But as long as your functions are large and take at least 5ms to execute, you could use a JSON over HTTP approach. I found this less error-prone than JuliaCall. In my case, the Python code had to use an outdated Python version that was not supported by JuliaCall.

Example package: [GitHub - ufechner7/pykitemodels: Kite power system models for Python · GitHub](https://github.com/ufechner7/pykitemodels)

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [March 19, 2026, 8:47pm UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/3 "2026-03-19T20:47:30Z")

</div>

Hello, I am also interested, can you expand a bit your answer and provide a high level overview of how your solution works ?

---

<div class="post-metadata">

**Author:** ![aris](https://avatars.discourse-cdn.com/v4/letter/a/258eb7/32.png) [@aris](https://discourse.julialang.org/u/aris)\
**Post date:** [March 19, 2026, 8:55pm UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/4 "2026-03-19T20:55:33Z")

</div>

Sounds interesting, but also more complicated than the juliacall solution.

Ideally I’d be looking for something as seamless as possible, where the python user only does a pip install (or equivalent) and forgets about the existence of julia, working only within their python comfort zone.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [March 20, 2026, 10:08pm UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/5 "2026-03-20T22:08:19Z")

</div>

> [@aris](#):
>
> Would it be best to have the python code at a separate repository (like diffeqpy), or at the same one as the Julia code? Any (dis)advantages in either way?

Either is fine, it’s up to personal preference and how you want to manage things.

> [@aris](#):
>
> The package I’m working on has a `GLMakie` [extension](https://docs.julialang.org/en/v1/manual/code-loading/#man-extensions), which provides some very useful GUI capabilities. Seems like using `GLMakie` from juliacall is not seamless, and some [workarounds](https://github.com/JuliaPy/PythonCall.jl/issues/212) might be required. Has anybody managed to deal with this matter in an elegant way (e.g. wrap Makie functions with `juliacall.interactive()` somewhere in the python codebase)?

Not that I’m aware of. However I suppose one thing we could do is have JuliaCall fire up a separate thread which calls Julia’s `yield` in a loop. This would just run continuously and allow the Julia event loop to keep looping even when back in Python.

> [@aris](#):
>
> More generally, would there be any pitfalls to avoid when working with Julia package extensions in this context?

I’m not aware of any particular pitfalls of using Julia package extensions from JuliaCall.

> [@aris](#):
>
> I was wondering whether the relatively recent updates in [AOT compilation](https://docs.julialang.org/en/v1/devdocs/aot/) would enable better solutions to this, exposing the same functionality while avoiding a Julia installation for the python user. Has anybody experimented with this?

I’ve experimented with this a bit and you can indeed compile a Python extension module from some Julia code using `juliac --trim`. I meant to write a post about it but never did. The big caveat is that it still requires the Julia runtime library (i.e. essentially a full Julia install anyway) but we could wrap up into a Python package rather than install it like JuliaCall does. Then we’d need to figure out how to get a juliac-compiled module to link against that runtime when loaded. Must be doable I just haven’t tried it. The JuliaCall route is fine, but the compiled route should have really small TTFX.

> [@aris](#):
>
> Any other methods or resources I’m missing here?

I think your two options are:

- The in-process option: use JuliaCall.
- The separate-process option: wrap the functionality up as a REST API server that Python can call, as suggested by @ufechner7. I’m sure you could automate the launching of the server and connecting to it so that it is transparent to the user. And you can still use pyjuliapkg to handle the Julia dependencies.

Unless you’ve got a strong technical reason not to (e.g. you need really old dependencies, or multi threading) then JuliaCall will be the simplest route.

---

<div class="post-metadata">

**Author:** ![attdona](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/attdona/32/15859_2.png) [@attdona](https://discourse.julialang.org/u/attdona)\
**Post date:** [March 21, 2026, 9:32am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/6 "2026-03-21T09:32:01Z")

</div>

For the goal to preserve the Python (and Julia) “comfort zone” when building a  
multi-language system, another approach may be [Rembus](https://github.com/cardo-org/Rembus.jl).

I recently released [Rembus for Python](https://github.com/cardo-org/rembus.python), which allows Python and Julia components to communicate seamlessly in the same distributed system. If you want a gentle introduction, I started a mini blog with worked examples: [Rembus Blog – Rembus](https://cardo-org.github.io/posts.html)

A few things to give some more context:

- Exchanged data are CBOR encoded (binary data, not JSON or base64 encoding)

- DataFrame support out of the box: polars/pandas interops natively with Julia DataFrames

- Rembus supports both brokered and brokerless (client/server) topologies

- Optional DuckLake integration for persistent data at rest (ignore if not needed)

Without more details about your requirements it’s hard to say if it’s the right fit, but happy to answer any questions.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 21, 2026, 9:57am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/7 "2026-03-21T09:57:11Z")

</div>

Does Rembus support Matlab?

---

<div class="post-metadata">

**Author:** ![attdona](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/attdona/32/15859_2.png) [@attdona](https://discourse.julialang.org/u/attdona)\
**Post date:** [March 21, 2026, 10:15am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/8 "2026-03-21T10:15:19Z")

</div>

At the moment, Rembus only supports Python and Julia.

If it gains traction, I’d definitely consider adding support for more languages.

Also, if someone is interested in implementing a client in another language, I’d be happy to document and publish the CBOR-based protocol so it can be extended more easily.

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [March 21, 2026, 10:24am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/9 "2026-03-21T10:24:14Z")

</div>

> [@ufechner7](#):
>
> I found this less error-prone than JuliaCall.

Yes, people have been anecdotally reporting problems, and I’ve also personally experienced bugs, but I hope any bugs and inherent limitations can be documented precisely, so that you only reach for alternatives in these corner cases. “Just giving up” on PythonCall and JuliaCall is not very appealing since they’re **so much** more convenient and integrated than alternatives.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 21, 2026, 10:29am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/10 "2026-03-21T10:29:04Z")

</div>

> [@greatpet](#):
>
> I hope any bugs and inherent limitations can be documented precisely, so that you only reach for alternatively in these corner cases.

Well, it is documented that you can call Julia functions only from the main thread of Python, and the application I had to connect needed to call Julia from another thread.

---

<div class="post-metadata">

**Author:** ![aris](https://avatars.discourse-cdn.com/v4/letter/a/258eb7/32.png) [@aris](https://discourse.julialang.org/u/aris)\
**Post date:** [March 22, 2026, 5:40pm UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/11 "2026-03-22T17:40:19Z")

</div>

Thank you so much everyone for the helpful discussion!

I believe I’m convinced for now that JuliaCall should be able to do the job for my relatively straightforward use case.

However, I do plan to play around with the other suggested options to see if they suit my needs.

---

<div class="post-metadata">

**Author:** ![xgdgsc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xgdgsc/32/608_2.png) [@xgdgsc](https://discourse.julialang.org/u/xgdgsc)\
**Post date:** [March 23, 2026, 2:45am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/12 "2026-03-23T02:45:25Z")

</div>

Another choice is [GitHub - Suzhou-Tongyuan/jnumpy: Writing Python C extensions in Julia within 5 minutes. · GitHub](https://github.com/Suzhou-Tongyuan/jnumpy) , they fixed the previous multithreading issue recently.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 23, 2026, 9:42am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/13 "2026-03-23T09:42:49Z")

</div>

Anyone who could compare [jnumpy](https://github.com/Suzhou-Tongyuan/jnumpy) with [PythonCall](https://github.com/JuliaPy/PythonCall.jl)? As far as I see, `jnumpy` does not support Julia 1.12 yet. Anything else?

---

<div class="post-metadata">

**Author:** ![xgdgsc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xgdgsc/32/608_2.png) [@xgdgsc](https://discourse.julialang.org/u/xgdgsc)\
**Post date:** [March 23, 2026, 10:24am UTC](https://discourse.julialang.org/t/exposing-julia-packages-to-python-users/136272/14 "2026-03-23T10:24:27Z")

</div>

Isn’ t 1.12 supported in [make finalizer thread-safe & compat 1.11+ by songjhaha · Pull Request #89 · Suzhou-Tongyuan/jnumpy · GitHub](https://github.com/Suzhou-Tongyuan/jnumpy/pull/89/changes) ? [bump jnumpy version v0.4.10 & TyPython version v0.2.7 · Suzhou-Tongyuan/jnumpy@499481c · GitHub](https://github.com/Suzhou-Tongyuan/jnumpy/actions/runs/22752520247/job/65989870527)
