Skip to content

feat(launcher): embed python#4414

Open
iamllama wants to merge 27 commits intoankitects:mainfrom
iamllama:launcher-embed
Open

feat(launcher): embed python#4414
iamllama wants to merge 27 commits intoankitects:mainfrom
iamllama:launcher-embed

Conversation

@iamllama
Copy link
Copy Markdown
Contributor

@iamllama iamllama commented Nov 1, 2025

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 iamllama marked this pull request as ready for review November 1, 2025 15:04
Comment on lines +367 to +369
let console_snippet = if console {
r#" sys.stdout = sys.stderr = open("CONOUT$", "w"); sys.stdin = open("CONIN$", "r");"#
} else {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very jank, but apart from using the console subsystem, i've not been able to find another solution for this. It also potentially doesn't show output between starting the interpreter and running this snippet

Perhaps anki-console could be changed from a wrapper that just spawns anki.exe with env vars to a stripped-down version of the launcher but with the console subsystem

@iamllama
Copy link
Copy Markdown
Contributor Author

iamllama commented Nov 1, 2025

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 iamllama marked this pull request as draft November 1, 2025 18:27
@iamllama iamllama marked this pull request as ready for review November 2, 2025 10:07
@iamllama iamllama changed the title feat(launcher): embed python dynamically feat(launcher): embed python Nov 3, 2025
@dae
Copy link
Copy Markdown
Member

dae commented Feb 11, 2026

This is some impressive technical work Llama, and ties in to the decision we need to make as mentioned on #4390 (comment). I might create a new issue to discuss, and respond there.

@dae dae mentioned this pull request Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider integrating Python in the launcher

2 participants