anki icon indicating copy to clipboard operation
anki copied to clipboard

feat(launcher): embed python

Open iamllama opened this issue 1 month ago • 1 comments

Closes #4151

Looked into why embedding statically/dynamically python would need version-scoped installers, and found that PyConfig's layout depends on the targetted version. If we went that route, we could use pyembed (of the dead pyoxidizer family) or pyo3 and link against a specific version

Instead, i've opted to link against libpython at runtime, using the venv bin* to get the libpath for the currently selected version (3.9/3.13 etc.), using the venv activation script to setup up sys.path, sys.prefix etc, and only relying on the 3.x stable api and The Very High Level Layer to setup and start the interpreter. If it fails, it'll fallback to the usual launch method of spawning the venv bin

Wasn't able to find any examples of run-time linking python, but i did see a mention in the python manual so we're not doing anything untoward here (hopefully)

Portability: this Just Works™ on my wsl ubuntu and win10 machines (after wrestling with the quirks of 3.9 and 3.13 on each platform), but i've not been able to test on macs

Overhead: once on first-startup to get and cache libpython's path, and none as far as i can tell on runtime

*this may seem weird but there's precedence: pyo3 invokes python in build scripts

iamllama avatar Nov 01 '25 15:11 iamllama

I've just come across this nugget on https://docs.python.org/3/library/site.html

Changed in version 3.14: site is no longer responsible for updating sys.prefix and sys.exec_prefix on Virtual Environments. This is now done during the path initialization. As a result, under Virtual Environments, sys.prefix and sys.exec_prefix no longer depend on the site initialization, and are therefore unaffected by -S.

Which means that the venv activation script (activate_this.py) will no longer work from 3.14 onwards. Made a venv with cpython-3.14.0b2-linux-x86_64-gnu to check, and it turns out the script isn't even available anymore, which is disappointing to say the least.

~~Will look into using pyo3/PyConfig instead~~

EDIT: I've used bindgen on the 3.9/3.13 lin/win cpython headers to codegen PyConfig. This way we can avoid using pyo3 which, as far as i can tell, needs a concrete python version to configure itself and link against. I'd hoped to avoid version-scoping, but with this we'll still have installers that support <=3.X instead of one fixed version per. In any case it falls back to the usual launch so there's no difference

NB: The pythonistas have realised this is very inconvenient (PEP 741), and so from 3.14 onwards we can set sys.argv and sys.executable without knowing any layouts. ~~But this still isn't headache-free as we'd need to manipulate PyObjects. And having to support 3.9/3.13 won't allow us to actually use it~~

iamllama avatar Nov 01 '25 18:11 iamllama