Error with importing matplotlib.pyplot for use with PyCall.jl

I am having an issue with PyCall.jl. For context, I am using a Windows PC with a Julia 1.11.2 and Python 3.13.1. I first created a Python virtual environment in the following directory:

"C:\Research Software\Python\Virtual Environments\venv_1"

I used venv to create the Python virtual environment. In venv_1, I installed matplotlib (see image below):

Then I created Julia virtual environment in the following directory:

"C:\Research Software\Julia\Virtual Environments\venv_1"

I then activated venv_1 (the Julia virtual environment) and did:

add PyCall
using PyCall
ENV[“PYTHON”]="C:/Research Software/Python/Virtual Environments/venv_1/Scripts/python.exe"
build PyCall

Then I restarted Julia and activated the venv_1 (the Julia virtual environment) again and did:

using PyCall
 plt = pyimport(“matplotlib.pyplot”)

This is where the following error is thrown:

ERROR: PyError (PyImport_ImportModule

The Python package matplotlib.pyplot could not be imported by pyimport. Usually this means
that you did not install matplotlib.pyplot in the Python version being used by PyCall.

PyCall is currently configured to use the Python version at:

C:\Research Software\Python\Virtual Environments\venv_1\Scripts\python.exe

and you should use whatever mechanism you usually use (apt-get, pip, conda,
etcetera) to install the Python package containing the matplotlib.pyplot module.

One alternative is to re-configure PyCall to use a different Python
version on your system: set ENV["PYTHON"] to the path/name of the python
executable you want to use, run Pkg.build("PyCall"), and re-launch Julia.

Another alternative is to configure PyCall to use a Julia-specific Python
distribution via the Conda.jl package (which installs a private Anaconda
Python distribution), which has the advantage that packages can be installed
and kept up-to-date via Julia.  As explained in the PyCall documentation,
set ENV["PYTHON"]="", run Pkg.build("PyCall"), and re-launch Julia. Then,
To install the matplotlib.pyplot module, you can use `pyimport_conda("matplotlib.pyplot", PKG)`,
where PKG is the Anaconda package that contains the module matplotlib.pyplot,
or alternatively you can use the Conda package directly (via
`using Conda` followed by `Conda.add` etcetera).

) <class 'ImportError'>
ImportError('Error importing numpy: you should not try to import numpy from\n        its source directory; please exit the numpy source tree, and relaunch\n        your python interpreter from there.')
  File "C:\Research Software\Python\Virtual Environments\venv_1\Lib\site-packages\matplotlib\__init__.py", line 161, in <module>
    from . import _api, _version, cbook, _docstring, rcsetup
  File "C:\Research Software\Python\Virtual Environments\venv_1\Lib\site-packages\matplotlib\cbook.py", line 24, in <module>
    import numpy as np
  File "C:\Research Software\Python\Virtual Environments\venv_1\Lib\site-packages\numpy\__init__.py", line 132, in <module>
    raise ImportError(msg) from e

Stacktrace:
 [1] pyimport(name::String)
   @ PyCall C:\Users\ericd\.julia\packages\PyCall\1gn3u\src\PyCall.jl:558
 [2] top-level scope
   @ REPL[5]:1

It seems there is an import error, specifically with numpy but I am not sure if I am reading it correctly nor how to resolve it.

Additionally, as per the PyCall.jl documentation, after checking the build.log the Python executable used in the virtual environment is linked against the same libpython used by PyCall:

[ Info: PyCall is using C:/Research Software/Python/Virtual Environments/venv_1/Scripts/python.exe (Python 3.13.1) at C:\Research Software\Python\Virtual Environments\venv_1\Scripts\python.exe, libpython = C:\Research Software\Python\Python-3.13.X\python313.dll
[ Info: C:\Users\ericd\.julia\packages\PyCall\1gn3u\deps\deps.jl has been updated
[ Info: C:\Users\ericd\.julia\prefs\PyCall has been updated

I do not want to have PyCall.jl use a Python distribution via the Conda.jl package. The error message also says that PyCall.jl is configured to use the Python installation at:

“C:\Research Software\Python\Virtual Environments\venv_1\Scripts\python.exe”

which is where I installed matplotlib via pip. I am not sure what the issue is or how (or if) it can be resolved so I can use PyCall.jl with a Python virtual environment in the fashion that I am describing. Any help would be appreciated.**

Hi, and welcome to the Julia community!

I can replicate your issue, also when following the PyCall instructions concerning virtual environments. Could you try the same steps, but with pyimport("os") at the end? For me this still just loads from the base Python environment. EDIT: This os behaviour is normal (also the case in Python itself), but trying to pyimport any package installed in the virtual environment but not in the base environment yields that same error.

In case you only dislike Conda.jl, but are fine with using conda in general, then I’ve encountered no issues configuring PythonCall.jl to work with an existing conda environment.

Thank you so much. Is this a recent behavior? I would prefer to use Conda not at all and stick with pip. On my laptop which has Julia 1.11.1 and Python 3.13 I have a Julia virtual environment and a python virtual environment and PyCall.jl works fine for PyPlot.jl.

For PyCall.jl, this sequence is incorrect:

add PyCall
using PyCall
ENV[“PYTHON”]="C:/Research Software/Python/Virtual Environments/venv_1/Scripts/python.exe"
build PyCall

I recommend the following order.

ENV[“PYTHON”]="C:/Research Software/Python/Virtual Environments/venv_1/Scripts/python.exe"
using Pkg
Pkg.add("PyCall")
Pkg.build("PyCall")
using PyCall

As others have mentioned, PythonCall.jl is surplanting PyCall.jl.

Also consider using PythonPlot.jl.

1 Like

Seeing as PyCall.jl hasn’t been updated in some time, it’s unlikely to be a very recent development, though I would assume venvs would have worked at some point.

What does seem to work for me is to just add the venv’s site-packages:

ENV[“PYTHON”]="C:/Research Software/Python/Virtual Environments/venv_1/Scripts/python.exe"
using Pkg
Pkg.add("PyCall")
Pkg.build("PyCall")
using PyCall
site = pyimport("site")
site.addsitedir("C:/Research Software/Python/Virtual Environments/venv_1/Lib/site-packages")
plt = pyimport("matplotlib.pyplot")

The underlying assumption here is that python.exe knows where to find its site library directory. I believe this is true of conda environments but perhaps not of venv.

My guess is that this case is particularly unusual because this is also on Windows.