PyCall pointing to correct venv but not picking up the correct path (likely related to .pythonstartup)

Hi all,

I have PyCall.jl configured to point towards my venv. For example:

julia> using PyCall

julia> PyCall.python
"/home/colin/.pyvenv1/bin/python3"

This is exactly where I want it to point. Next, I do the following:

julia> py"""
       from os import sys
       """

julia> py"sys.path"
4-element Vector{String}:
 "/usr/lib/python312.zip"
 "/usr/lib/python3.12"
 "/usr/lib/python3.12/lib-dynload"
 "/home/colin/.pyvenv1/lib/python3.12/site-packages"

This is not the same output for sys.path that I get if I run Python from the venv directly. For example, in a fresh terminal:

colin@colin-Creator-16-AI-Studio-A1VIG:~$ /home/colin/.pyvenv1/bin/python3
Python 3.12.3 (main, Sep 11 2024, 14:17:37) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
running .pythonstartup
>>> import sys
>>> sys.executable
'/home/colin/.pyvenv1/bin/python3'
>>> sys.path
['', '/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/home/colin/.pyvenv1/lib/python3.12/site-packages', '/home/colin/Dropbox/Codebase/Python', '/home/colin/Dropbox/Codebase/Python/Modules']

We can see that I’ve called the same Python executable as PyCall.python, yet sys.path is returning different results.

I’m pretty sure the problem is that when I run Python in a terminal, it calls .pythonstartup on, well, startup, and .pythonstartup is indeed where I add the additional paths to sys.path. But it appears when I initiate Python in PyCall.jl it does not run .pythonstartup. Is this expected? Is there any way to get it to run .pythonstartup? I guess it isn’t a big deal as I can just manually add the appropriate paths after loading PyCall.jl, but thought I’d ask here in case there is an easy fix (and also to save time for anyone else who encounters this).

Thanks in advance,

Colin

Hi Colin,

Maybe this is not the approach you’re after, but you could just use @pyinclude(ENV["PYTHONSTARTUP"]).


For a Python startup file containing

import sys
sys.path = ["FromStartup"]

(the path of which is contained in the environment variable PYTHONSTARTUP), I get

using PyCall
sys = pyimport("sys")
println(length(sys.path))  # 6, i.e. not just ["FromStartup"]
@pyinclude(ENV["PYTHONSTARTUP"])
println(sys.path)  # ["FromStartup"]

Nowadays PythonCall.jl seems to be preferred over PyCall.jl. As far as I can tell there is no equivalent to @pyinclude, but you could use something like

# (After restarting)
using PythonCall
sys = pyimport("sys")
println(length(sys.path))  # 6
# So also PythonCall.jl does not run the startup file automatically
@pyexec (path=ENV["PYTHONSTARTUP"]) =>
    """
    with open(path) as f:
       exec(f.read())
    """
println(sys.path)  # ['FromStartup']
2 Likes

Yep, that works! Thanks for that. Also, somehow the existence of PythonCall.jl had managed to pass me by, so thanks for the heads up.

1 Like