What's up Python? Unpacking in Comprehensions, Android Wheels, and uv is a big boy now...
July, 2025
Summary
PEP 798 proposes to extend unpacking in comprehensions
cibuildwheel reaches milestone in mobile support
uv
adds Python toPATH
and the Windows registry now, and it's a big deal
PEP 798 – Unpacking in Comprehension
Iteration in Python is one of those features that keeps giving. Unpacking is one of the great things about it, and it comes with a nice syntax to merge arbitrary iterables.
E.G:
>>> start = "123"
... mid = [4, 5, 6]
... end = open("foo.txt", 'w+')
... end.write('7\n8\n9\n')
... end.seek(0)
... total = (*start, *mid, *end)
... print(total)
...
('1', '2', '3', 4, 5, 6, '7\n', '8\n', '9\n')
But while you can unpack a generator from a comprehension list as well:
>>> alternative_end = (x + 3 for x in mid)
>>> (*start, *mid, *alternative_end)
('1', '2', '3', 4, 5, 6, 7, 8, 9)
And you can unpack elements of iterables inside a comprehension list at the loop level:
>>> pairs = list(zip(start, mid))
[('1', 4), ('2', 5), ('3', 6)]
>>> [int(a) + b for (a, b) in pairs]
[5, 7, 9]
You cannot unpack those same elements at the result level. This doesn't work:
>>> [*pair for pair in pairs]
File "<python-input-31>", line 1
[*pair for pair in pairs]
^^^^^
SyntaxError: iterable unpacking cannot be used in comprehension
I would expect this should give you:
['1', 4, '2', 5, '3', 6]
But to get this result, you would need a much less natural construct, such as nested comprehensions:
>>> [element for pair in pairs for element in pair]
['1', 4, '2', 5, '3', 6]
PEP 798 aims to change that for Python 3.15 and allow all the following forms:
[*i for i in l] # list with the concatenation of iterables in 'l'
{*i for i in l} # set with the union of iterables in 'l'
{**d for d in dicts} # dict with the combination of dicts in 'dicts'
(*i for i in l) # generator of the concatenation of iterables in 'l'
I personally think it's a no-brainer. It's the natural continuation of the existing set of features, and it's just weird that it's not possible right now.
In fact, I'm a strong proponent of extending the unpacking syntax even further so that we can unpack dictionaries into variables the way we do it with lists.
We can do:
color1, color2, color3 = ["blue", "white", "red"]
We should be able to do:
{color1, color2, color3} = {
"color1": "blue",
"color2": "white",
"color3", "red"
}
JavaScript has been able to do that for ages, after all.
Anthony Sottile, the maintainer of the deadsnake PPA, even has a demo using a clever little hack.
cibuildwheel adds Android support
This is the kind of thing that only gets excitement from a small niche of people, but I'm definitely in that group. cibuildwheel (for "CI Build Wheel") is the de facto standard tool to build Python packages (the little .whl
files) across multiple platforms at once.
It handles CPython 3.8 to 3.14, PyPy 3.8 to 3.11, and historically covered Mac, Linux, and Windows. The idea is to run it on your Continuous Integration server, with official support for GitHub Actions, Azure Pipelines, Travis CI, CircleCI, and GitLab CI.
V3.1.0 added the ability to build wheels for the Android platform, which has been the result of a long work with the help of the folks from BeeWare (that probably doesn't surprise you if you listened to our podcast episode with Russel Keith-Magee and noticed that mobile is now a Tier 3 platform for the Python project).
In March, iOS support was merged, so with this release, we finally have the mobile platform covered, getting us closer and closer to a nice Python experience on smartphone where pip
or uv
are relevant, where you can casually import numpy
and where a “hello world” in your pocket won't seem like a tedious affair.
This once again highlights how much there is to do to add new targets. This takes a lot of time and many dedicated and talented people to get there.
Because of React Native, JS is already half there. But PHP and Ruby don’t have a great story for this, so Python would become kind of an outlier, especially if it supports its complicated ecosystem of compiled extensions. After all, it's the beauty of the wheel format and the amazing feat that cibuildwheel helps you achieve.
uv becomes a serious system installer contender
In its latest 0.8 release, uv
went for a bunch of breaking changes to stabilise its API, and two of them are pretty important for the future of the tool:
First, it now installs a versioned Python executable into a directory on the PATH
. So now if you uv python install python3.14
, you will be able to just type python3.14
and get it to run. This makes it an alternative to python.org installers, OS stores, and packaging systems.
To avoid shadowing existing Python, it adds it way down the chain, so if you already have a Python with this exact name and version, it should not replace it. Still, this is tricky, and I'm glad they didn't start with this approach, but made it about projects first, so people get used to focusing on that. Most users rarely need a global Python install, they just think they do. But as a professional, I'm happy to have this feature.
Second, it registers Python versions with the Windows Registry. This is important if you want to help tooling recognize uv
-installed Python as available on the Windows platform.
The new version comes with many other interesting goodies, so check it out. But those two defaults mean I now struggle to find reasons to use anything else than UV. I mean, even the lovely deadsnake ppa will likely gather dust from now on.
And a few things
Mypy 1.17 is out, adding an option to check
match/case
exhaustiveness. Nice if you want the extra safety net, ensuring you handled all the possibilities, and no one will add anything in your back without triggering a warning. But it does drop 3.8 support.It's not you, it's us: Pypi search index was in degraded mode for a few hours.
Pypi users have been targeted by phishing attacks.. If you see a mail from "noreply@pypj.org", trash it.
VSCode Python extension is finally gitignoring
.venv
by default. Many people using the VSCode UI to interact with Git are not very comfy with it in the first place, and it's easy to add the universe to your index by mistake.