# Julia crashed when using PyCall in multiple threads

**URL:** <https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004>\
**Category:** General Usage\
**Tags:** pycall\
**Created:** [March 1, 2024, 9:20am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004 "2024-03-01T09:20:44Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![wly](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wly/32/49517_2.png) [@wly](https://discourse.julialang.org/u/wly)\
**Post date:** [March 1, 2024, 9:20am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/1 "2024-03-01T09:20:44Z")

</div>

I first make multiple copies of a PyObject, and then access them in multiple threads. Finally, I meet this error.  
`julia -t5`

```julia
using PyCall

py"""
class A():
    x = 0.0
a = A()
"""

alist = [deepcopy(py"a") for i in 1:10]
# @show alist

for j in 1:100
    Threads.@threads for i in 1:10
        alist[i].x
    end
end

```

error:

```julia
Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x7fff61685962 -- port with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x7fff61685962 -- at 0x7fff61685962 -- ION with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x7fff61685962 -- at 0x7fff61685962 -- ION with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x7fff61685962 -- at 0x7fff61685962 -- at 0x7fff61685962 -- ION with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x7fff61685962 -- PyObject_GenericGetAttrWithDict at C:\Users\wly\.julia\conda\3\x86_64\python310.dll (unknown line)

```

Julia version

```julia
Julia Version 1.9.3
Commit bed2cd540a1 (2023-08-24 14:43 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, goldmont)

```

Thanks.

---

<div class="post-metadata">

**Author:** ![wly](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wly/32/49517_2.png) [@wly](https://discourse.julialang.org/u/wly)\
**Post date:** [March 1, 2024, 9:58am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/2 "2024-03-01T09:58:47Z")

</div>

I find a similar question about this [https://juliacommunity.github.io/zulip-archive/stream/274208-helpdesk-(published)/topic/using.20PyCall.20object.20in.20threads.html](https://juliacommunity.github.io/zulip-archive/stream/274208-helpdesk-(published)/topic/using.20PyCall.20object.20in.20threads.html), which gives some reason but does not provide a possible solution.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [March 1, 2024, 1:15pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/3 "2024-03-01T13:15:15Z")

</div>

Can I suggest using PythonCall.jl? It seems to be the more mature option for calling Python from Julia, and it has some notes on multithreading [FAQ & Troubleshooting · PythonCall & JuliaCall](https://juliapy.github.io/PythonCall.jl/stable/faq/#Is-PythonCall/JuliaCall-thread-safe)?

---

<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 1, 2024, 1:19pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/4 "2024-03-01T13:19:30Z")

</div>

This is know to fail.

---

<div class="post-metadata">

**Author:** ![wly](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wly/32/49517_2.png) [@wly](https://discourse.julialang.org/u/wly)\
**Post date:** [March 1, 2024, 1:34pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/5 "2024-03-01T13:34:02Z")

</div>

> [Is PythonCall/JuliaCall thread safe?](https://juliapy.github.io/PythonCall.jl/stable/faq/#Is-PythonCall/JuliaCall-thread-safe?)  
> No.  
> Some rules if you are writing multithreaded code:
> 
> - Only call Python functions from the first thread.

Thanks for your suggestion. It seems that it also does not realize this.

---

<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 1, 2024, 2:28pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/6 "2024-03-01T14:28:37Z")

</div>

I mean, Python itself has a global interpreter lock and cannot handle more than one thread in parallel… There is not much anybody can do about it… Either you serialize the calls to Python, or you create multiple Julia processes calling multiple instances of the Python interpreter…

---

<div class="post-metadata">

**Author:** ![wly](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wly/32/49517_2.png) [@wly](https://discourse.julialang.org/u/wly)\
**Post date:** [March 1, 2024, 2:43pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/7 "2024-03-01T14:43:17Z")

</div>

What is `serialize the calls to Python`? Can you give me some examples or links?  
Thanks.

---

<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 1, 2024, 3:16pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/8 "2024-03-01T15:16:09Z")

</div>

> **[Writing reentrant and threadsafe code](https://www.ibm.com/docs/en/aix/7.2?topic=programming-writing-reentrant-threadsafe-code#writing_reentrant_thread_safe_code __title__ 9)**
>
> In single-threaded processes, only one flow of control exists. The code executed by these processes thus need not be reentrant or threadsafe. In multithreaded programs, the same functions and the same resources may be accessed concurrently by several...

It means you use a lock such that only one thread of your Julia program can access your Python call at any given time…

I did not try this yet, it might work, but it also might mean that you need a handler in the main thread that communicates with your other threads and calls Python…

---

<div class="post-metadata">

**Author:** ![hhaensel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hhaensel/32/1207_2.png) [@hhaensel](https://discourse.julialang.org/u/hhaensel)\
**Post date:** [June 12, 2024, 11:06pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/9 "2024-06-12T23:06:38Z")

</div>

Stumbled across this very problem and after some searching found the following solution:

```julia
using PythonCall
using ThreadPools

macro pythread(expr)
    quote
        fetch(@tspawnat 1 begin
            $(esc(expr))
        end)
    end
end

function babel_convert(input, informat = "cdxml", outformat = "mol")
    @pythread begin
        ob = pyimport("openbabel.openbabel")
        conv = ob.OBConversion()
        conv.SetInAndOutFormats(informat, outformat)
        
        mol = ob.OBMol()
        conv.ReadString(mol, input)
        
        if ! Bool(mol.Has2D()) && ! Bool(mol.Has3D())
            pgen = ob.OBOp.FindType("gen2D")
            pgen !== nothing && pgen.Do(mol)
        end

        pyconvert(String, conv.WriteString(mol))
    end
end

PythonCall.GC.disable()
Threads.@threads for i in 1:10000
    babel_convert(cdxml)
end
PythonCall.GC.enable()

```

---

<div class="post-metadata">

**Author:** ![hhaensel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hhaensel/32/1207_2.png) [@hhaensel](https://discourse.julialang.org/u/hhaensel)\
**Post date:** [June 13, 2024, 8:57am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/10 "2024-06-13T08:57:35Z")

</div>

Just tried to use `@pythread` in a more complicated scenario and found that it essential to call PythonCall.GC.isable() from the Main thread as well.  
As this is not always easy to do, it may be favorable to define `@pythread` as follows:

```julia
macro pythread(expr)
    quote
        fetch(@tspawnat 1 begin
            PythonCall.GC.disable()
            res = $(esc(expr))
            PythonCall.GC.enable()
            res
        end)
    end
end

```

---

<div class="post-metadata">

**Author:** ![deszoeke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deszoeke/32/2174_2.png) [@deszoeke](https://discourse.julialang.org/u/deszoeke)\
**Post date:** [January 21, 2026, 3:54am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/11 "2026-01-21T03:54:08Z")

</div>

After updating to Julia 1.12.4, the julia kernel is crashing inconsistently on some PyPlot calls with the error:

```julia-auto
Fatal Python error: PyThreadState_Get: the function must be called with the GIL held, but the GIL is released (the current Python thread state is NULL) Python runtime state: initialized Thread 0x00000001f6bc3ac0 (most recent call first): File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/PIL/ImageFile.py", line 559 in _encode_tile File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/PIL/ImageFile.py", line 540 in _save File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/PIL/PngImagePlugin.py", line 1412 in _save File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/PIL/Image.py", line 2459 in save File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/matplotlib/image.py", line 1656 in imsave File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py", line 446 in _print_pil File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py", line 497 in print_png File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/matplotlib/backend_bases.py", line 2043 in <lambda> File "~/.julia/conda/3/aarch64/lib/python3.10/site-packages/matplotlib/backend_bases.py", line 2193 in print_figure [5469] signal 6: Abort trap: 6 in expression starting at none:1

The Kernel crashed while executing code in the current cell or a previous cell. Please review the code in the cell(s) to identify a possible cause of the failure. Click [here](https://aka.ms/vscodeJupyterKernelCrash) for more info. View Jupyter [log](command:jupyter.viewOutput) for further details.

```

The vscode advice and logs are very generic, but the upper part of the message suggests the julia kernel or its vscode extensions are triggering errors for using python/PyCall in a non-thread-safe way.

---

<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:** [January 21, 2026, 4:12am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/12 "2026-01-21T04:12:46Z")

</div>

You have three options:

- use PythonCall/ PythonPlot instead of PyCall/PyPlot (now threadsafe, not in the past)
- run Julia with `julia -t 1,0` (single threaded)
- do the plotting in a separate, single-threaded process

---

<div class="post-metadata">

**Author:** ![deszoeke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deszoeke/32/2174_2.png) [@deszoeke](https://discourse.julialang.org/u/deszoeke)\
**Post date:** [January 21, 2026, 4:44pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/13 "2026-01-21T16:44:50Z")

</div>

Thanks, ufechner7. I am running a Jupyter notebook in vscode. It is using a single-threaded IJulia kernel, but perhaps julia 1.12.4 or PyCall is spawning multiple threads somehow.

The problem might be my reuse of PyPlot figures, which I just clear in a new cell with `clf()` and keep plotting.  
I am now using `close(gcf())` instead of `clf()`. It seems to work, but it’s hard to test for this intermittent problem.

I’ll also try migrating to PythonCall and PythonPlot.

---

<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:** [January 21, 2026, 5:07pm UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/14 "2026-01-21T17:07:13Z")

</div>

> [@deszoeke](#):
>
> single-threaded IJulia kernel,

Running `julia -t 1` results in Julia using two threads (from version 1.12 onwards), one normal and one interactive thread. Only if you run `julia -t 1,0` does it really use only one thread.

---

<div class="post-metadata">

**Author:** ![sparrowhawk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sparrowhawk/32/9148_2.png) [@sparrowhawk](https://discourse.julialang.org/u/sparrowhawk)\
**Post date:** [January 24, 2026, 10:56am UTC](https://discourse.julialang.org/t/julia-crashed-when-using-pycall-in-multiple-threads/111004/15 "2026-01-24T10:56:24Z")

</div>

I started getting strange VSCode crashes too, especially when PyPlot (installed through Conda/PyCall) plots were open (julia 1.12.4, VScode version code-1.108.2-1769004860, Julia extension 1.176.2 on linux). I’d get an error message which frustratingly disappeared as soon as the crash happened, so I resorted to screenshotting waiting for a crash … It seems to be something to do with Revise.jl and PyObjects, from the incomplete screen grab. Downgrading to Revise 3.13.0 (I had run update which brought me to 3.13.1 yesterday) or ensuring Revise is not loaded on VSCode startup seems to fix this – Phew!
