Installing on Linux under Pyenv

My OS is MX Linux 23, based on Debian 12, the default Python 3 version is 3.11.2. I installed the package python3-wxgtk4.0 through the package manager, everything worked fine. The version is ‘4.2.0 gtk3 (phoenix) wxWidgets 3.2.2’.

I have additionally installed Python 3.13.12 with pyenv and tried installing the latest version of wxPython there with pip install wxPython - failed at first, but then sort of succeeded, after installing the system libgtk-3-dev package. pip install wxPython was doing something for about 20 minutes (building from the sources, I assume) and then reported a successful installation of wxPython-4.2.5.

However, attempting to import wx gives the following error:

File "/home/<username>/bin/pyenv/versions/3.13.12/lib/python3.13/site-packages/wx/__init__.py", line 17, in <module>  
   from wx.core import *  
 File "/home/<username>/bin/pyenv/versions/3.13.12/lib/python3.13/site-packages/wx/core.py", line 12, in <module>  
   from ._core import *  
ImportError: /lib/x86_64-linux-gnu/libwx_baseu-3.2.so.0: version `WXU_3.2.6' not found (required by /home/<username>/bin/pyenv/versions/3.1  
3.12/lib/python3.13/site-packages/wx/_core.cpython-313-x86_64-linux-gnu.so)

There’s another file with that name: .../pyenv/versions/3.13.12/lib/python3.13/site-packages/wx/libwx_baseu-3.2.so.0 that was created during the installation and, I assume, is of the required version. How do I tell wxPython to use it instead of the one from /lib/...?

I don’t know if this is more about Pyenv than wxPython, but I’ve installed a few other modules that are not pure Python (i. e. also have binary libraries in their directories), and they seem to work fine.

I might have solved it - not sure if completely, or in the most sensible way, but my simple test GUI works, wxPython-demo-4.2.5 also mostly works, except some samples that require additional libraries I currently don’t have installed in the environment (cairo, pdf, etc.).

To run from the terminal

export LD_LIBRARY_PATH="<path to pyenv>/versions/3.13.12/lib/python3.13/site-packages/wx"
(append with :$LD_LIBRARY_PATH if you must, add to .bashrc or whatever), then it can be ran with python myscript.py or ./myscript.py if it has the permission and the shebang pointing to the correct interpreter.

To run without the terminal

i.e. by double-clicking in the file manager, etc. I’ve found two ways.

1. Patching the libraries

(sudo apt install patchelf)
From within the directory where the library resides (<path to pyenv>/versions/3.13.12/lib/python3.13/site-packages/wx)
do:
patchelf --set-rpath '$ORIGIN' _core.cpython-313-x86_64-linux-gnu.so
This will patch the library, making it look for dependencies in the same folder. This was enough to make everything (?) work.

2. Creating symlinks to the libraries

Without patching, the library searches for its dependencies in <path to pyenv>/versions/3.13.12/lib (can be checked with the same patchelf tool as patchelf --print-rpath _core.cpython-313-x86_64-linux-gnu.so). The library is not there, so it defaults (I guess?) to the system-wide location (/lib/...). There are these libraries in .../site-packages/wx: libwx_baseu-3.2.so.0 and libwx_gtk3u_core-3.2.so.0, create symlinks to them in <path to pyenv>/versions/3.13.12/lib. This was enough to make everything (?) work.

Final thoughts

There are other libraries like that in .../wx - maybe the others like _adv.*, _aui.*, etc. would also require patching, or the others like libwx_* would also require the symlinks, but so far everything seem to work without that, including wx.adv, wx.aui, etc.

I kinda feel like there should be an installation or configuration option making all of the above unnecessary, but so far I haven’t found anything.

What is strange is that a wheel installed in a venv with pip has the rpath already set to $ORIGIN.

$ patchelf --print-rpath _core.cpython-312-x86_64-linux-gnu.so 
$ORIGIN

I’m wondering if pyenv is changing the rpath during installation somehow?

By a “wheel” you mean a binary .whl file for your distribution you downloaded somewhere? Or built by yourself from the sources into a binary wheel first and then installed with pip? Or the same pip install wxpython done to venv, not pyenv?

Both (using venv in both cases). :slight_smile:

I tried one of the Ubuntu 24.04 wheels here:
https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-24.04/

And also pip install wxpython on Fedora. Both result in rpath set to $ORIGIN.

I made a venv with my default system python 3.11.2 and installed wxpython there with pip install wxpython. For that:
patchelf --print-rpath _core.cpython-311-x86_64-linux-gnu.so
outputs
$ORIGIN

I also found the .whl files in the pip cache, unpacked them and checked their binaries.

For the one I installed in venv:
patchelf --print-rpath _core.cpython-311-x86_64-linux-gnu.so
outputs
$ORIGIN

For the one I installed in pyenv:
patchelf --print-rpath _core.cpython-313-x86_64-linux-gnu.so
outputs
<pyenv path>/versions/3.13.12/lib
same as reported in my second post above. So when the wheel is built under pyenv, the hard-coded path is there. As to be expected, I guess - pyenv patching the already built binaries would be a bit unorthodox. Still, don’t know either what to do about that or which side is guilty - wxpython build scripts or something in pyenv.

Do you happen to have a build log for the one built under pyenv? Alternatively, do you have a rough set of steps for how to reproduce using pyenv?

By a build log, do you mean the stuff it outputs to the terminal in the process? Well, no. I can re-run it for that, but, as far as I remember, it outputted literally nothing informative, it was almost like “building… OK, built”. Or should I run it with some additional parameters, so that it would produce more verbose output?

Alternatively, I have the exact set of steps that “worked on my machine” - if that would help with anything, here it is (some of this is specific to fish terminal, but anyway, until the last two lines I was just following the instructions from pyenv’s github):

git clone https://github.com/pyenv/pyenv.git

set -Ux PYENV_ROOT $HOME/bin/pyenv
test -d $PYENV_ROOT/bin; and fish_add_path $PYENV_ROOT/bin

Add to ~/.config/fish/config.fish:
pyenv init - fish | source

exec "$SHELL"

sudo apt update; sudo apt install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl git \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

pyenv install 3.13

pyenv shell 3.13.12

sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev

pip install wxPython

Thanks for the steps. That was helpful and I was able to reproduce. I’ll let you know what I find.

OK, I found the culprit. The python-config installed by pyenv is setting the rpath using a linker flag:

$ python-config --ldflags
 -L/home/xyz/.pyenv/versions/3.13.12/lib  -ldl -L/home/xyz/.pyenv/versions/3.13.12/lib -Wl,-rpath,/home/xyz/.pyenv/versions/3.13.12/lib -lm

I am not sure what to do about it, yet, though.