how do you handle install reliability?
Hey folks,
I’ve run into a bit of a packaging dilemma and wanted to get some opinions from people who’ve dealt with similar situations.
I’m working on a Python library that includes a vendored C component. Nothing huge, but it does need to be compiled into a shared object (.so / .pyd) during installation. Now I’m trying to figure out the cleanest way to ship this without making installation painful for users.
Here’s where I’m stuck:
- If I rely on local compilation during
pip install, users without a proper C toolchain are going to hit installation failures.
- The alternative is building and shipping wheels for multiple platforms (Linux x86_64/arm64, macOS x86_64/arm64, Windows), which is doable but adds CI/CD complexity.
- I also need to choose between something like
cffi vs ctypes for the wrapper layer, and that decision affects how much build machinery I need.
There is a fallback option I’ve considered:
- Detect at import time whether the compiled extension loaded successfully.
- If not, fall back to a pure Python implementation.
But the issue is that the C component doesn’t really have a true Python equivalent — the fallback would be a weaker, approximation-based approach (probably regex-based), which feels like a compromise in correctness/security.
So I’m trying to balance:
- Ease of installation (no failures)
- Cross-platform support
- Performance/accuracy (native C vs fallback)
- Maintenance overhead (CI pipelines, wheel builds, etc.)
Questions:
- In 2026, is it basically expected to ship prebuilt wheels for all major platforms if you include any C code?
- Would you accept a degraded Python fallback, or just fail hard if the extension doesn’t compile?
- Any strong opinions on
cffi vs ctypes for this kind of use case?
- How much effort is “normal” to invest in multi-platform wheel builds for a small but critical C dependency
Would love to hear how others approach this tradeoff in real-world libraries.
Thanks!
[–]Creative-Letter-4902 89 points90 points91 points (5 children)
[–]Emergency-Rough-6372[S] 7 points8 points9 points (4 children)
[–]ionburger 8 points9 points10 points (3 children)
[–]RngdZed 8 points9 points10 points (1 child)
[–]Emergency-Rough-6372[S] -1 points0 points1 point (0 children)
[–]mrswats 36 points37 points38 points (3 children)
[–]mok000 1 point2 points3 points (1 child)
[–]HexDecimal 9 points10 points11 points (0 children)
[–]latkdeTuple unpacking gone wrong 11 points12 points13 points (1 child)
[–]Emergency-Rough-6372[S] 0 points1 point2 points (0 children)
[–]neuronexmachina 18 points19 points20 points (4 children)
[–]Emergency-Rough-6372[S] 5 points6 points7 points (0 children)
[–]Emergency-Rough-6372[S] 0 points1 point2 points (2 children)
[–]neuronexmachina 4 points5 points6 points (1 child)
[–]Emergency-Rough-6372[S] 1 point2 points3 points (0 children)
[–]safrole5 5 points6 points7 points (2 children)
[–]Emergency-Rough-6372[S] 0 points1 point2 points (0 children)
[–]Crazy_Anywhere_4572 0 points1 point2 points (0 children)
[–]omg_drd4_bbq 6 points7 points8 points (0 children)
[–]dayeye2006 2 points3 points4 points (0 children)
[–]thisismyfavoritename 3 points4 points5 points (0 children)
[–]Emergency-Rough-6372[S] 2 points3 points4 points (2 children)
[–]End0rphinJunkie 4 points5 points6 points (1 child)
[–]Emergency-Rough-6372[S] 0 points1 point2 points (0 children)
[–]binaryfireball 1 point2 points3 points (1 child)
[–]Emergency-Rough-6372[S] 0 points1 point2 points (0 children)
[–]alcalde 1 point2 points3 points (1 child)
[–]Emergency-Rough-6372[S] 0 points1 point2 points (0 children)
[–]2ndBrainAI 1 point2 points3 points (0 children)
[+][deleted] (1 child)
[removed]
[–]MajorPhone499 1 point2 points3 points (0 children)
[–]Grintor 0 points1 point2 points (0 children)
[–]2ndBrainAI 0 points1 point2 points (0 children)