# Somewhere somehow Julia caches the path to Python, and I do not understand why

**URL:** <https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814>\
**Category:** General Usage\
**Tags:** python\
**Created:** [June 11, 2025, 4:22pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814 "2025-06-11T16:22:18Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 11, 2025, 4:22pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/1 "2025-06-11T16:22:18Z")

</div>

How, I ran into some strange behavior with Julia.

I have a software package that works like this

- Julia user code starts (via `dlopen`) a C library that instantiates an embedded Python
- Python user code does the same

Everything worked just a couple of days ago.  
However, I do not quite understand why, it broke: for some strange reason when the Julia user code is used, the path to `libpython` is completely wrong (it points to a Homebrew Python, in Ubuntu instead of the active Conda environment), and everything breaks.  
When the user code is in Python, it works correctly: libpython corresponds to the actual Python executable.

While trying to find out, why this happens, I have tried to install `PyCall.jl` and got the following:

```julia
julia> using PyCall
 │ Package PyCall not found, but a package named PyCall is available from a registry.
 │ Install package?
 │ (um02-open-interfaces) pkg> add PyCall
 └ (y/n/o) [y]: y
   Resolving package versions...
    Updating `~/Work/um02-open-interfaces/Project.toml`
  [438e738f] + PyCall v1.96.4
    Updating `~/Work/um02-open-interfaces/Manifest.toml`
  [8f4d0f93] + Conda v1.10.2
  [438e738f] + PyCall v1.96.4
  [81def892] + VersionParsing v1.3.0
Precompiling PyCall...
Info Given PyCall was explicitly requested, output will be shown live
ERROR: LoadError: could not load library "/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0"
/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0: cannot open shared object file: No such file or directory. Please run `Pkg.build("PyCall")` if your Python build has changed

```

My actual Conda Python is 3.13.2, not 3.11. **Question** why Julia memorizes somewhere the path to `libpython`? And, to the problem above, why Julia somehow breaks the search of the correct `libpython` inside a dynamically loaded C library?

I am on Julia 1.11.5, Ubuntu 22.04.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 11, 2025, 4:33pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/2 "2025-06-11T16:33:41Z")

</div>

> [@dmitry-kabanov](#):
>
> **Question** why Julia memorizes somewhere the path to `libpython`?

It’s the specific package that you’re using which handles how python is searched, reading its documentation may be helpful: [PyCall.jl/README.md at 2f600fbebee50ab0672e153455e3c0fda1694fba · JuliaPy/PyCall.jl · GitHub](https://github.com/JuliaPy/PyCall.jl/blob/2f600fbebee50ab0672e153455e3c0fda1694fba/README.md#specifying-the-python-version)

---

<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:** [June 11, 2025, 4:36pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/3 "2025-06-11T16:36:11Z")

</div>

Are you running Julia from the terminal, or from a VSCode terminal?

VSCode changes the python path if you ever installed some Python plugins using VSCode.

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 11, 2025, 4:40pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/4 "2025-06-11T16:40:22Z")

</div>

I am in the terminal. The weird thing is that when the (incorrect) libpython is loaded, subsequent `import sys; print(sys.executable)` shows the correct python (the one which gets invoked in the terminal as a command). Everything actually worked, because I had it working. Something got updated (probably, the homebrew packages), and it does not work anymore 😭

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 11, 2025, 4:42pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/5 "2025-06-11T16:42:05Z")

</div>

The version that `pyCall.jl` tries to use (Python 3.11) is not there at all. It was there before, but sometime in the past the conda environment was recreated and uses Python 3.13 now. That’s why I suspect some form of caching happening.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 11, 2025, 4:48pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/6 "2025-06-11T16:48:25Z")

</div>

> [@dmitry-kabanov](#):
>
> That’s why I suspect some form of caching happening.

Did you read the link I shared which tells you what you need to do to reset the path to python?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 11, 2025, 4:54pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/7 "2025-06-11T16:54:02Z")

</div>

> [@giordano](#):
>
> Did you read the link I shared which tells you what you need to do to reset the path to python?

Right. PyCall saves the path to libpython. You need to rebuild PyCall if you want to use a different libpython, or if your Python moves.

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 12, 2025, 8:58am UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/8 "2025-06-12T08:58:55Z")

</div>

Hi, sorry for the late reply, I am in another time zone.

Thank you for the link, I have just tried to set the `PYTHON` variable before installing `PyCall` (by the way, I am not reinstalling it, at least not in the current Julia environment), I receive the exactly same error where `PyCall` is looking for a verion of Python that is just not there (I use 3.13, not 3.11 that it is looking for):

```julia
um02-open-interfaces on  julia-ivp [$!?] via 🅒 um02-open-interfaces …
➜ which python
/home/dima/sw/miniforge3/envs/um02-open-interfaces/bin/python

um02-open-interfaces on  julia-ivp [$!?] via 🅒 um02-open-interfaces …
➜ PYTHON=/home/dima/sw/miniforge3/envs/um02-open-interfaces/bin/python julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.11.5 (2025-04-14)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

(um02-open-interfaces) pkg> add PyCall
   Resolving package versions...
  No Changes to `~/Work/um02-open-interfaces/Project.toml`
  No Changes to `~/Work/um02-open-interfaces/Manifest.toml`
Precompiling project...
  ✗ PyCall
  ✗ SciMLBase → SciMLBasePyCallExt
  0 dependencies successfully precompiled in 6 seconds. 266 already precompiled.
  2 dependencies errored.
  For a report of the errors see `julia> err`. To retry use `pkg> precompile`

julia> err
PkgPrecompileError: The following 1 direct dependency failed to precompile:

PyCall

Failed to precompile PyCall [438e738f-606a-5dbb-bf0a-cddfbfd45ab0] to "/home/dima/.julia/compiled/v1.11/PyCall/jl_Qptcah".
ERROR: LoadError: could not load library "/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0"
/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0: cannot open shared object file: No such file or directory. Please run `Pkg.build("PyCall")` if your Python build has changed
Stacktrace:
 [1] error(::String, ::String)
   @ Base ./error.jl:44
 [2] top-level scope
   @ ~/.julia/packages/PyCall/1gn3u/src/startup.jl:51
 [3] include(mod::Module, _path::String)
   @ Base ./Base.jl:557
 [4] include(x::String)
   @ PyCall ~/.julia/packages/PyCall/1gn3u/src/PyCall.jl:1
 [5] top-level scope
   @ ~/.julia/packages/PyCall/1gn3u/src/PyCall.jl:38
 [6] include
   @ ./Base.jl:557 [inlined]
 [7] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing)
   @ Base ./loading.jl:2881
 [8] top-level scope
   @ stdin:6
in expression starting at /home/dima/.julia/packages/PyCall/1gn3u/src/startup.jl:41
in expression starting at /home/dima/.julia/packages/PyCall/1gn3u/src/PyCall.jl:1
in expression starting at stdin:6

caused by: could not load library "/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0"
/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0: cannot open shared object file: No such file or directory
Stacktrace:
 [1] dlopen(s::String, flags::UInt32; throw_error::Bool)
   @ Base.Libc.Libdl ./libdl.jl:120
 [2] dlopen(s::String, flags::UInt32)
   @ Base.Libc.Libdl ./libdl.jl:119
 [3] top-level scope
   @ ~/.julia/packages/PyCall/1gn3u/src/startup.jl:48
 [4] include(mod::Module, _path::String)
   @ Base ./Base.jl:557
 [5] include(x::String)
   @ PyCall ~/.julia/packages/PyCall/1gn3u/src/PyCall.jl:1
 [6] top-level scope
   @ ~/.julia/packages/PyCall/1gn3u/src/PyCall.jl:38
 [7] include
   @ ./Base.jl:557 [inlined]
 [8] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing)
   @ Base ./loading.jl:2881
 [9] top-level scope
   @ stdin:6

```

On a side note, before that the `PYTHON` env variable was not set at all, but `PyCall` was still looking for the libpython inside the actual Conda environment that I use.

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 12, 2025, 9:00am UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/9 "2025-06-12T09:00:26Z")

</div>

> Right. PyCall saves the path to libpython. You need to rebuild PyCall if you want to use a different libpython, or if your Python moves.

This I can understand: if there is linkage to `libpython`, of course.

However, I am adding `PyCall` to the Julia environment, not reinstalling it. Or do you mean, that the path is saved somewhere globally, across multiple environments?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 12, 2025, 9:00am UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/10 "2025-06-12T09:00:35Z")

</div>

I don’t see evidences that you ran the command `Pkg.build("PyCall")`, as explained in both the link I shared and the error message you posted.

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 12, 2025, 3:50pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/11 "2025-06-12T15:50:42Z")

</div>

Ah, OK, I did not understand before that `> add PyCall` and `Pkg.build("PyCall")` are two different things. Yes, by invoking `PYTHON=path-here julia` and using the `Pkg.build` command, I was able to install it. Nevertheless, the error message above about a completely wrong version of Python that is not there, is still very cryptic.

And my main problem was that when starting with user code in Julia and then using a C library that starts an embedded Python, the wrong `libpython` was loaded (and this does not happen with user code in C or Python). I actually found the source of the error. For some reason, I had wrong `python3` priority in `PATH` (`python` was correct), and this was the influence.

Thank you everybody!

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 12, 2025, 3:52pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/12 "2025-06-12T15:52:33Z")

</div>

> [@dmitry-kabanov](#):
>
> Nevertheless, the error message above about a completely wrong version of Python that is not there, is still very cryptic.

You’re saying that

> [@dmitry-kabanov](#):
>
> ```julia
> Please run `Pkg.build("PyCall")` if your Python build has changed
> 
> ```

wasn’t clear enough?

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [June 12, 2025, 3:54pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/13 "2025-06-12T15:54:01Z")

</div>

This part was not clear:

```julia
ERROR: LoadError: could not load library "/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0"
/home/dima/.conda/envs/um02-open-interfaces/lib/libpython3.11.so.1.0: cannot open shared object file: No such file or directory. Please run `Pkg.build("PyCall")` if your Python build has changed

```

considering that I have never had this package installed in the used Julia environment. Why was it looking for Python 3.11 in the Conda environment with Python 3.13?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 12, 2025, 4:42pm UTC](https://discourse.julialang.org/t/somewhere-somehow-julia-caches-the-path-to-python-and-i-do-not-understand-why/129814/14 "2025-06-12T16:42:45Z")

</div>

> [@dmitry-kabanov](#):
>
> considering that I have never had this package installed in the used Julia environment. Why was it looking for Python 3.11 in the Conda environment with Python 3.13?

You must have installed PyCall using that Conda environment at some point and forgot about it.
