Skip to content

feat(launcher): embed python#4414

Closed
iamllama wants to merge 27 commits into
ankitects:mainfrom
iamllama:launcher-embed
Closed

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

Conversation

@iamllama

@iamllama iamllama commented Nov 1, 2025

Copy link
Copy Markdown
Contributor

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 thread qt/launcher/src/platform/windows.rs Outdated
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

iamllama commented Nov 1, 2025

Copy link
Copy Markdown
Contributor Author

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

dae commented Feb 11, 2026

Copy link
Copy Markdown
Member

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
@abdnh abdnh closed this in #5019 Jun 17, 2026
pull Bot pushed a commit to stungkit/anki that referenced this pull request Jun 17, 2026
## Linked issue

Closes ankitects#4556
Closes ankitects#4557
Closes ankitects#4144
Closes ankitects#4151
Closes ankitects#4152
Closes ankitects#4153
Closes ankitects#4229
Closes ankitects#4356
Closes ankitects#4401
Closes ankitects#4403
Closes ankitects#4519
Closes ankitects#4523
Closes ankitects#4390
Closes ankitects#4414
Closes ankitects#4484



## Summary / motivation

After 4 months of exploring Briefcase for packaging, we're confident it
solves most problems with the uv launcher with less complexity and at a
lower maintenance cost, especially with the parallel work on the release
CI, which we already used to make 5 releases.

This also removes platform-specific packaging/signing code used to
produce macOS dmg files and Windows NSIS installers, which is now
largely handled by Briefcase and the release CI.
The custom install scripts for Linux are mostly preserved under
qt/installer/linux-template and used in the Briefcase build.

## How to test

- [ ] No build problems.
- [ ] The `tools/build-installer` scripts still work.
- [ ] No CI/release workflow issues.
- [ ] No user-visible changes in dev environment and Briefcase build.
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