The Changelog: Software Development, Open Source - Free-threaded Python (Interview)
Episode Date: October 2, 2024Jerod is joined by the co-hosts of core.py , Pablo Galindo & Łukasz Langa, a podcast about Python internals by people who work on Python internals. Python 3.13 is right around the corner, which means... the Global Interpeter Lock (GIL) is now experimentally optional! This is a huge deal as Python is finally free-threaded. There's more to discuss, of course, so we get into all the gory details.
Transcript
Discussion (0)
What up, Python nerds?
I'm Jared and you are listening to The Change Log, where each and every week we sit down
with the hackers, the leaders, and the innovators of the software world to pick
their brain, to learn from their mistakes, to get inspired by their accomplishments,
and to have a lot of fun along the way.
On this episode, I'm joined by the co-hosts of the Core.py podcast, Pablo Galindo and
Lukas Langa, whose name I will pronounce Lukas from here on out because it's just a lot easier for me.
On Core.py, they talk about Python internals because they work on Python internals.
And today we're talking about Python 3.13, which is right around the corner.
When we recorded this conversation last week, it was slated to be released on October 1st, but now they are targeting October
7th. So if you're listening to this in the future, 3.13 is fully baked. But if you are
listening right after we hit publish, wait a week or grab the release candidate, which
is 99% baked. Why are we all so excited about Python 3.13? Well, the Global Interpreter Lock, aka the GIL, is now experimentally optional.
This is a huge deal, as Python is finally free-threaded and able to run with true parallelism.
There's more, of course, and we get into all the details. I think you'll enjoy it, even if,
like me, you aren't a regular Pythonista. But first, a mention of our partners at Fly.io.
Over 3 million apps have launched on Fly, including ours. And you can, too, in less than five minutes, learn how at Fly.io.
Okay, free-threaded Python on the changelog.
Let's do this.
Hey, friends. I'm here with Dave Ros rosenthal cto of century so dave i know lots of developers know about century know about the platform because hey we use century and we love century
and i know tracing is one of the next big frontiers for century why add tracing to the
platform why tracing and why now when we first launched the ability to collect
tracing data, we were really emphasizing the performance aspect of that, the kind of application
performance monitoring aspect, you know, because you have these things that are spans that measure
how long something takes. And so the natural thing is to try to graph their durations and
think about their durations and, you know, warn somebody if the durations are getting too long.
But what we've realized is that the performance stuff ends up being just a bunch of gauges to look at. And it's
not super actionable. Sentry is all about this notion of debuggability and actually making it
easier to fix the problem, not just sort of giving you more gauges. A lot of what we're trying to do
now is focus a little bit less on the sort of just the performance monitoring side of things and turn
tracing into a tool that actually aids the debug ability of problems.
I love it. Okay. So they mean it when they say code breaks, fix it faster with Sentry.
More than 100,000 growing teams use Sentry to find problems fast. And you can too. Learn more
at Sentry.io. That's S-E-N-T-R-Y.io o and use our code changelog get 100 off the team plan
that's almost four months free for you to try out sentry once again sentry dot i o Today I'm joined by Pablo Galindo and Lucas Longa from Core.py,
a podcast all about Python internals because these two work on Python internals. Welcome to the show
guys. Thank you very much for having us. Happy to be here. Now your podcast is usually just the two
of you talking to each other or do you have a third party ever? Every now and again we would
invite a guest but mostly it's just the two of us. Yeah when people are fed up of listening to us
and then we read someone's show.
Now, we've been asked to start a Python podcast a few times, as well as an Elixir podcast and a Rust podcast.
And we don't usually feel like we have anything to add to the conversation, except when it
came to Python, I remember telling our friend Brett Cannon, I said, you guys should have
a podcast where it's like the people who work on Python talking about Python,
not randos like I would be or people on the,
it's a huge community, but there's no voice
that is coming from the core team.
And so I think it's pretty cool.
When did you guys start this and what was the big idea?
So we started actually one year ago.
We were in the, right now we are in the core developer
sprint at Meta.
So this is
basically a meeting
that we do every single year
when we try to bring
all the core developers
together
and, you know,
the sparks and conversation
in person because,
you know,
open source is basically
based on asynchronous
communication,
but from time to time
it's very good to,
you know,
not having to discuss
and wait like an entire day
just to tell the other person
I don't like your
proposal.
So, yeah. So yeah.
So after that,
these meetings have a lot of discussions
and they are super rich regarding that.
It's fantastic.
It's one of my favorite moments of the year.
And so I reached the bookish
and I say,
it would be actually very cool
because what happens here,
people don't really know the discussions,
they just know the output of them.
And there's many of these projects that take years
or they only show after a time.
And there are some of these projects that just die
and they never happen.
And I was telling Lucas, it would be super cool
if we have this space where we can talk about
how the sausage is made, right?
And all these crazy ideas that we're having
and how they kind of transform into it.
Because there is this, I mean, to some extent it's improving,
but there is this perception from people
that core developers are these alien developers
that, you know, like, I don't know,
they go into this room and then Python happens.
But it's just like, we are just regular people, right?
Exactly.
So our idea was first kind of demystify
the core development thing.
So it's not just, you know, we're just regular people, right?
Just doing the thing.
And the other is that trying to inspire people to join this, right?
So ideally we can talk about like,
not only the projects that we're doing,
but also like how hard it is or how we struggle.
And we try to always have some inspirational notes
on the episodes so people can say,
hey, maybe this is something that I want to do.
And then, and this was a good idea, we also tried to highlight contributions that people
have done.
Because at the end of the day, people only know the big things.
Okay, the new parser or the JIT or the garbage collector or whatever it is.
But there is a lot of very cool contributions for core developers or regular people that
are contributing to CPython.
So we spent at the end of the episode
some time trying to go through the last,
we call this section,
what's going on in CPython.
We try to highlight the different things
that people are doing
so people know about them
and hopefully if a name comes again and again,
people say, I know that person.
That's cool.
So Lucas, Pablo speaks very fast.
How do you keep up with him?
Experience.
It's just a matter of just doing this for long enough.
We've known each other for a few years before that.
So I was prepared for the Spanish 2x speaking speed.
Yeah, built in 2x.
Right.
We were joking about this many times because people who are listening to our podcast, Yeah, built-in 2x because Pablo is speaking quickly. I am not speaking so fast.
So maybe with this development of AI and everything,
we should have some adaptive playback speed
where it recognizes who is talking.
And for me, it would be 2x.
For Pablo, it would be like, whoa, whoa, whoa, no.
0.75, actually.
I don't think 1x is enough.
Yeah, some sort of normalization
where they just both go to the same speed.
That would be a cool feature.
As an anecdote, a small anecdote,
at PyCon, this is this big conference
that happens every year.
Well, there's several other ones,
but the big one is in the US.
So I normally give a talk every year.
Especially at PyCon US,
there is these people that try to transcribe life.
So people with hearing problems can read, so it's really cool.
And this year, before giving the talk, I apologized to the person.
I was like, I'm really sorry about what is going to happen,
but I'm not being able to speak slower.
And she was like, yeah, no problem.
But she really struggled with that.
But yeah, she kept up. She was really good.
Yeah, the closed captioning at PyCon is a magical thing.
It turns out that it does help people
with hearing disabilities to participate in the conference,
but it's also helpful even for other participants.
So just as subtitles are being turned on
by most people watching now TV shows
and other programs at home,
the closed captions happen to be helpful for regular attendees as well.
So this is something that has become a staple of PyCon US.
I'm very happy that this is there.
Definitely some people present more of a challenge to the persons actually doing the closed captioning.
I'm always amazed not just at how fast they go,
but how much they can express the different TLA's
and Python specific terms that we're using.
You would think, okay, this is very industry specific.
And if you talk to your dad or to some of your friends
that are not in tech, some of the words, verbs,
and so on that we're using
might be mystifying.
You don't even know how to spell this.
And yet the people doing the closed captioning
are excellent at this.
You'll be surprised how obscure project names and so on,
they are just perfectly able to spell just correctly.
And it always touches my heart
when I see my own name spelled correctly
uh which also does happen they added me to their alphabet so like you know i'm like ah
this is awesome that is awesome the personal touch means so much it does and it's worth uh
it's worth going that extra mile in those circumstances well we're here today to talk
about python 3.13 hopefully i'll be able to keep up with you, Pablo.
Because not only do you speak fast, but I'm kind of a visitor to your guys' world.
So maybe keep them in check, Lucas.
We're going to specifically talk about the biggest, and I guess this is monumental.
In fact, our community member who thought we should do an episode on this,
shout out to Christian Klaus,
says this is kind of massive for Pythonistas.
This is the biggest feature coming out in 3.13,
which should probably be out there if you're listening to this.
We're shipping this October 2nd
and slated to release October 1st officially.
At least the RC is out there, but software and ship dates,
we think it's probably out there.
If not, coming very, very, very soon.
The ability to disable
or remove the global interpreter lock
or the GIL, as it's so lovingly referred to.
Let's start at base principles.
What is the GIL?
And then after that, why would you want to remove it?
Right.
So the GIL is basically a ginormous lock all around Python.
So Python is really the language,
but it really doesn't exist.
It's an abstraction.
And really, normally there is a second language behind it.
In C Python it's C,
which is the default implementation of Python
that normally people use.
There are others.
But then when this program that is the Python interpreter
is executing Python code,
it can have multiple threads at the same time.
And all these little objects that Python exposes
could be mutated at the same time, which is a problem.
And Python in particular, Cpython as well,
and most of the implementations is reference counted.
This means that to decide if an object is still alive
or the interpreter can actually get rid of it,
we have this little number inside every object
that tells how many different structures
or fields are using it.
When this number reaches zero,
we know that we can remove it.
But as any person who has done some multithreading
in computer science knows,
having a little number being mutated
by multiple threads
at the same time is not bueno.
So the solution is basically to add a ginormous lock
all around the interpreter.
Because we don't know what the threads are doing,
we need to just basically lock the entire thing.
So this means that only one thread at a time
can be accessing Python code and executing Python code,
which means that you can still use threads
because those threads can switch from one to the other,
which is what we call concurrency.
You don't need to wait until one thread finishes
to start the other.
So they interleave, but there's no parallelism really
because only one thread at a time
can be executing Python code,
which is a big problem in these days
when we have machines with 120-something cores
if you have a repair or servers, right?
Or even your phone, right?
Your phone has plenty of cores.
And right now you're running Python on iOS,
which is now a thing, by the way.
Python on iOS is a thing as well.
Let's earmark that for a future part of this conversation.
So what you're saying is, when running Python,
you can switch quickly between cores,
but you can't actually run the same code
on multiple cores at the exact same time.
So you're saying it's concurrent, but it's not parallel.
Yes, correct.
Because of that lock, one at a time,
and it can switch at the speed of light,
but no true parallelism until now.
Right, so there were a few ways
in which we worked around this obviously huge design limitation.
So there are plenty of cases in which we're confident
we can drop the global interpreter lock
for what is happening on a particular thread.
So if your particular thread is doing some big
NumPy computation that is only on the sides of numbers
that are not shared as Python objects,
you can drop the global interpreter lock in the time
that this computation happens, so you can let other threads
execute Python in that time.
If your thread is waiting on a blocking network connection,
it also does not need to
hold the lock because that particular moment in time, there is not going to be any Python code
executing. So you can give that gill to somebody else. So there are special cases in which we were
already sort of parallel more than not, but it is very implicit. It depends on us carefully finding
all those special cases and enabling them.
And in the end, it does not scale
for regular user applications.
So if you just write Python code
that loops over things
and just executes some string concatenations,
that's like all these regular things
that you expect from a Python program,
most of the time you're not going to be seeing any parallelism there.
And what is worse, one important thing here is that
technically a GIL is more than just a lock.
It's a condition variable, which is a very specific kind of
secretization primitive.
It's a Boolean that tells you if you have it or not,
and an actual lock.
And the thing is that you cannot select,
like when one thread says,
oh, I don't need the GIL,
like someone else, you know, pick it up.
You cannot select which one is going to do it.
Like this is up to the OS.
Like you're using Linux,
so the Linux kernel decides who is the next one.
And this can be not great
because like the Linux kernel
may not know what you're doing.
So you can have one thread, for instance,
that is super CPU hungry,
like it's just crunching numbers.
So that thread is all the time wanting this GIL, right?
And then you have many threads
that are doing these I.O. operations.
Maybe they are waiting on a socket or something like that.
But because of how condition variables work
and the scheduler in Linux works,
which you can pick a bit,
but not from Python normally,
that CPU thread will pick up that condition variable
and the GIL many more times.
So it's almost like a race.
When the guild is released,
you have a gun in a
race and you fire the gun to
signal that the race starts and then all the threads
try to grab it at the same time. And the first one that has
it, that's the one that wins. But there is
nothing preventing that thread to keep
it getting it the next time and the
next time. So even if
you are used to it and you can still say,
well, maybe I can work with that limitation,
it's very difficult to reason about it
and to try to adapt it to your needs
because it's really up to the OS who gets the yield or not.
This is one of the primary reasons why Python's reputation
is being serviceable in terms of speed,
but for certain workloads, certain things,
it's too slow because of the GIL.
This is one of the reasons why people will say,
eh, I might pick something else because of the GIL.
Fair or not fair?
Yes, well, it depends.
It depends.
It's a factor.
Tell me why.
Right.
So first of all, the speed of Python
is mostly affected by the fact
that it does a ton of indirection.
The thing that costs the most in computer science, say for bad algorithms, is indirection.
So every time where some language can just point at memory, read a value, and it's done,
it's going to be faster than a language that, well, actually everything is dynamic.
So you point at a value, but then that value has another value. So you have to go somewhere else in memory to read another value,
then decide what to do and read yet another value. So every time in Python that you're
accessing an attribute, you're executing a ton of code compared to accessing a field in a struct
in C. So that's going to be the main factor of it being slow. But the way where GIL is hampering us is scalability,
which means simply for things that you could parallelize,
you cannot do that effectively. So this is where the reputation of
not really scalable comes in. But ironically, the GIL also
makes Python faster than it would be without it. The reason
why is because reference counting
is a major reason for the global interpreter locks existence.
But it's not the only reason you need a lock in your interpreter.
There's going to be internal data structures like dictionaries
where if you insert another key that wasn't there before,
maybe there's going to be some rehashing that happens, right?
So suddenly this simple operation is going to take a little more time than usual.
So there's going to be a time, a split second where the internal structure of the dictionary
is inconsistent, right? For example, you would be able to see that it has more elements in terms of
count than you actually are able to access access or you're going to be trying to
access an element that is there. It claims it's there, but you cannot get it yet because the
dictionary is being mutated, right? So for all those things, and there's plenty of cases like
that, the global rapid lock is very convenient because we are already holding it because we
care about the reference counts to be always correct.
So there's no other lock we need to care about.
And this is actually making matters cheaper because we only have this one.
And once you hold it, you can just run and it's great.
And plenty of authors of C extensions like NumPy and so on can also depend on the fact
that as soon as you have the golden web lock,
you have a lock that you can yourself
depend on for your own synchronization needs.
So now without that,
you're going to have to have fine-grained locking.
So for every of those use cases
that require synchronization,
you're going to have to have a smaller lock.
And it turns out that if you do this,
then you gain scalability,
but you pay the price of single-threaded performance
since catching, you know,
being able to acquire multiple locks
is necessarily slower than just doing it once, right?
It also has other consequences
apart from this particular aspect,
which is correctness.
Right now, if you have ever done multi-thread
in a language which requires locks,
like C or C++ or something like that,
when you don't have those locks,
then you go into this thing that people call
undefined behavior, right?
Like unicorns can appear in your program
and things can happen.
In Python, because it's serial,
sure, the results can be garbage, but it's not going to crash
because it's just one at a time.
And this especially happens as well on these C extensions
or these native extensions, which can be anything.
You could think about, well, if I add one of these logs
per extension, sure, I may have these problems
that Gukashi is mentioning, but it doesn't sound too bad.
But one of the problems, if you have many locks,
is that now those locks can interact between themselves.
So if one extension just happens to call another for any reason,
like there is callbacks scheduled,
or there is actually direct interaction or something like that,
those locks now can do things like deadlocking or livelocking
or reentrancy if you don't have something prepared.
And remember that these extensions
are made by different people.
So now you have bugs that only happen across them.
And that is a nightmare.
It's a real nightmare, right?
And Regil is basically protecting this
because there is one single one.
So all of them share it.
So it's very easy to reason about it
compared to not having it. Hey, friends, you know, we're big fans of Fly.io.
And I'm here with Kurt Mackey, co-founder and CEO of Fly.
Kurt, we've had some conversations and I've heard you say that public clouds suck.
What is your personal lens into public clouds sucking?
And how does Fly not suck?
All right.
So public clouds suck.
I actually think most ways of hosting stuff on the internet sucks.
And I have a lot of theories about why this is, but it almost doesn't matter.
The reality is, like, I've built a new app for, like, generating sandwich recipes because my family's just into specific types of sandwiches.
They use Braunschweiger as a component, for example.
And then I want to, like, put that somewhere.
You go to AWS and it's harder
than just going and getting
like a dedicated server from Hetzner.
It's like, it's actually like more complicated
to figure out how to deploy my dumb sandwich app
on top of AWS,
because it's not built for me as a developer
to be productive with.
It's built for other people.
It's built for platform teams
to kind of build the infrastructure of their dreams
and hopefully create a new UX
that's useful for the developers that they work with.
And again, I feel like every time I talk about this, it's like, I'm just too impatient.
I don't particularly want to go figure so many things out purely to put my sandwich
app in front of people.
And I don't particularly want to have to go talk to a platform team once my sandwich app
becomes a huge startup and IPOs and I have to do a deploy.
I kind of feel like all that stuff
should just work for me without me having to go ask permission or talk to anyone else. And so
this is a lot of, it's informed a lot of how we've built Fly. Like we're still a public cloud. We
still have a lot of very similar low level primitives as the bigger guys, but in general,
they're designed to be used directly by developers. They're not built for a platform team to kind of cobble together.
They're designed to be useful quickly for developers.
One of the ways we've thought about this is if you can turn a very difficult problem into a two-hour problem,
people will build much more interesting types of apps.
And so this is why we've done things like made it easy to run an app multi-region.
Most companies don't run multi-region apps on public clouds because it's
functionally impossible to do without a huge amount of upfront effort. It's why we've made
things like the virtual machine primitives behind just a simple API. Most people don't do like code
sandboxing or their own virtualization because it's just not really easy. There's no path to
that on top of the clouds. So in general, I feel like, and it's not really fair of me to say public clouds
suck because they were built for a different time.
If you build one of these things starting in 2007, the world's very different than it
is right now.
And so a lot of what I'm saying, I think, is that public clouds are kind of old and
there's a new version of public clouds that we should all be building on top of that are
definitely gonna make me as a developer much happier than I was like five or six years ago when I was kind of stuck in this
quagmire. So AWS was built for a different era, a different cloud era and fly a public cloud. Yes,
but a public cloud built for developers who ship that's a difference. And we here at change all
our developers who ship. So you should trust us. Try out Fly, fly.io.
Over 3 million apps, that includes us, have launched on Fly.
They leverage the global anti-cast load balancing, the zero config private networking, hardware isolation, instant wire guard VPN connections with push button deployments, scaling to thousands of instances.
This is the cloud you want.
Check it out, fly.io.
Again, fly.io.
And I'm also here with Kyle Carberry,
co-founder and CTO over at Coder.com.
And they pair well with fly.io.
Coder is an open source cloud development environment, a CDE.
You can host this in your cloud or on-premise.
So Cal, walk me through the process. A CDE lets developers put their development environment
in the cloud. Walk me through the process. They get an invite from their platform team to join
their coder instance. They got to sign in, set up their keys, set up their code editor.
How's it work? Step one for them, we try to make it remarkably easy for the
dev. We never gate any features ever for the developer. They'll click that link that their
platform team sends out. They'll sign in with OIDC or Google, and they'll really just press
one button to create a development environment. Now that might provision like a Kubernetes pod
or an AWS VM. We'll show the user what's provisioned, but they don't really have to care. From that point, you'll see a couple of buttons appear to open the editors that you're
used to like VS Code Desktop or, you know, VS Code through the web, or you can install our CLI.
Through our CLI, you really just log into Coder and we take care of everything for you. When you
SSH into a workspace, you don't have to worry about keys. It really just kind of like beautifully,
magically works in the background for you and connects you to your workspace.
We actually connect peer-to-peer as well.
You know, if the coder server goes down for a second because of an upgrade, you don't have to worry about disconnects.
And we always get you the lowest latency possible.
One of our core values is we'll never be slower than SSH, period, full stop.
And so we connect you peer-to-peer directly to the workspace.
So it feels just as native as it possibly could.
Very cool. Thank you, Kyle. Well, friends, it might be time to consider
a cloud development environment, a CDE.
And open source is awesome.
And Coder is fully open source.
You can go to Coder.com right now,
install Coder open source,
start a premium trial or get a demo.
For me, my first step,
I installed it on my Proxmox box and played with it. It was
so cool. I loved it. Again, Coder.com. That's C-O-D-E-R.com.
So if you have slower single threaded performance, you have loss of features in terms of it being a,
or more complexity potentially, because your loss of a single terms of it being a, or more complexity, potentially,
because your loss of a single lock,
now you need fine-grained locks
and all kinds of other things you can do,
which is problematic,
and a huge lift by many developers over,
how long have you guys been working on this?
This has been many years in the making.
Many years in the making.
Yes.
Okay, add all those together.
Worth it?
Well, we don't know. We'll see.
We'll see.
We cannot answer that.
We cannot answer that.
We don't know.
So we're in the stage of,
so actually this is an important thing,
by the way,
which I don't think we have mentioned.
This, in 3.13,
indeed there is a build of Python
that will not have the Glow interpreted log,
but you don't get it by default.
You need to manually compile Python. I mean, there is people that are already streaming Python with't get it by default. You need to manually compile Python.
I mean, there is people that are redistributing Python with this,
so probably you don't need to manually do it.
You can fetch it from your distribution probably.
Somebody will build it.
Yes, exactly.
But it's not the normal one.
If you install Python 3.13, it has the GIL.
It's not like a flag that you give when you run Python.
It's a separate executable.
Yes, you need to, it's actually called Python 3.13 T.
T.
Or 4.3. Whatever.4-3-3-T.
Whatever.
It's just the way it is.
Sure, it's free-threaded.
Yeah, exactly. So you need to run
that. And with that build, you can actually select
a runtime only with that one.
You can select a runtime if you want the GIL or not.
And this is very useful in case you want to try
the performance difference or because
you want to, like imagine, for instance,
you are doing one of these libraries
and you want to test if your library works with and without,
but you don't want to run your CI with two builds or whatever.
So you can do it.
There are consequences of this because, for instance,
in Python over the years,
we have added a lot of new optimizations.
Like, for instance, one of the things
that I think Lucas was missing on the reason Python is slow
is that apart from this old new direction, and it's actually part of the
reason, but is that it's dynamic, right? Like, so this is very important. Like if you are
adding two variables, X and Y, the interpreter is going to say, what is X? Oh, X is an
integer. Okay, let me fix the code for adding integers. Okay, what is Y? Oh, it's an
integer. Okay, let me fix the code. Okay. And then the next iteration of the loop is
going to say the same thing. What is X? So like, it's very annoying
compared to just like,
you know, here's a bunch of bytes
and I'm going to add this
to this bunch of bytes
because I know where they are, right?
So in this particular case,
precisely to avoid this dynamism,
we have added a lot of optimizations
that try to find this pattern.
So they say, okay,
you're adding these two variables together,
but you know,
the last 3,000 times
I have seen this addition,
they were integer.
So it's kind of a good chance
that they are integers the next time.
So I'm going to create this super performance code
that is going to just reach into the internals
of the integer object in Python.
It's going to grab the real integer
and it's going to add it at C speed.
It's going to create a result
without asking all these stupid questions.
And then it's going to box it again into a Python object.
And it's much faster.
You can still have a float suddenly and it will de-optimize and whatnot, but
that is a good problem. All those
optimizations don't work without the GIL
because they are not thread-safe.
So if you use
the single-threaded version
or the free-threaded version, which is a bit of a
mouthful, so you use Python 13t
but you don't have the GIL activated.
You also don't have the optimizations activated
because we don't know if they're safe or not.
So what does it mean?
It means that the free-threaded version
is slower in single-threaded.
So you only run one thread
and you're using the Python 3.13.t version,
it's slower because they don't have
those optimizations activated.
Slower for now or slower for good?
Right. For now. Great question.
So let's maybe take a step back and explain
the kind of strategy that we took
with this particular project
which is a huge undertaking
but at the same time we have
a release cadence that releases
Pythons every year. Predictably
in October you're going to get a new version
of Python. So there's no way you can shove
a big transition like this within 12 months.
So what we're doing instead, essentially what you're getting
is a state of the project as we are in
right now. So there are things that we still
need to do that are still not done.
Most importantly, this split for the main interpreter
still having the global interpreter lock and so on,
and an experimental one that you have to build yourself
and then you can run without a global interpreter lock,
that is deliberate because with all those costs that we described,
we really need to reach out to the community saying,
look, this is now not an idea
you can actually grab this Python and check
whether this helps you. Is it better?
Is it worthwhile the scalability for this extra
complexity within the implementation and maybe
this cognitive complexity that is going to be
sort of passed on to the user. Is that worth it?
So the community will have to now step in
and try out this new Python and see,
okay, this is slower than the non-server version,
but that's hopefully temporary.
But the question to answer is,
does the scalability that this enables help, right?
So we really need them to give us two thumbs up,
like, okay, keep actually working on this.
Since this specialization that Pablo described
and the JIT compilation that follows from that
and so on and so on are obviously features
that we really want to have,
including in the free-threaded version.
And there are ways to go around it,
but they are very complex. It is in fact like on the bleeding edge of computer science as we know
it. There are plenty of known strategies for improving performance of interpreted languages
that are single-threaded. For free-threaded interpreted languages, this is really where the science sort of is still unclear, right?
Because JavaScript, there has been so much investment in that,
like making that fast with V8, right?
Like in Chrome and so on and so on.
Well, that is single-threaded,
like for the intent and purposes of our understanding of the interpreter.
With a free-threaded Python,
how to make that fast is more of a challenge.
Literally, members of our team are going to be the people
writing papers about this later.
So this is going to take time.
No longer than one release, longer than two releases.
But at the same time, we want to release what we already have
so that it's no longer just a pipe dream.
It's no longer just a plan or idea. Users can actually experiment with this and tell us, okay,
this is actually awesome. This enables a use case we couldn't even try before because that's our
chicken and egg problem. Before we actually enable this, we don't see use cases that are now impossible. So we cannot tell whether there's an untapped area
of Python usage that would be now enabled
with free threading.
So this is what we're doing with 3.13.
This is essentially this current state of the project.
Now you can experiment with it.
You can see whether your web framework
is going to be faster now,
whether now you're going to be able to process data
in parallel and so on and so on.
This is essentially one step of a longer project.
Right, and it's out there in Release Canada.
It's probably out there as we speak,
at least in the official 3.13 experimental,
as you guys pointed out.
Are there early indicators?
Are there people who have been just pining for this
and they've already tried it in the RC
and are saying, wow, we're seeing this, or no?
Actually, that's a very good point.
One of the things that actually surprised me a lot,
because one of the unknowns here
was how the community was going to adopt this.
The reason being that it's just not that Python
needs to be multi-threaded.
Now, if you compile
C extensions, which are really, really popular
in Python, that's one of the reasons
why so many people use
Python as a language because
all the machine learning doesn't happen in pure Python.
It happens on compiled code and
Cuda and GPUs, but Python is the
driver or the glue.
All that code needs to be changed
or adapted at least.
Because now you don't have the lock protecting you
and who knows what happens now, right?
So you need to, which is really challenging
because right now you need to go
through the entire code base,
like the huge thing and sanitize the code base
through this particular problem.
And there is not a manual for that,
if you think about it.
So you need to reason about the entire thing.
And we were a bit scared
about how people will approach this,
or what will happen,
in the sense that if you don't do this,
or you don't do this correctly,
it's going to crash all the time,
or it's going to crash just once
every blue moon or whatever, right?
So we don't know.
So one of the things that we have seen,
and it's really impressive,
is that the community has jumped this incredible.
Like people are building like two versions
of every of these extensions,
one for the normal build,
one for the free thread build,
which is already huge, right?
It's doubled your CI time,
doubled your storage for the extensions.
So it's a lot of work, actually.
And there's a lot of people that are so excited
to jump to these extensions, and they try to
fix it and reason and try
these little locks all around.
So all those people have been
trying it, and one of the things that
have been super, super surprised here is that
once you add
those extensions and you have a final
application, like, I don't know, a machine learning
whatever it is, or like an LLM
or whatever you're thinking that uses
a lot of these things, right? It's just
not one, like five, six, seven
really complex one, plus the interpreters,
plus maybe a web server, something like that.
And then you run it through the free thread version,
it just works. I mean, again, who knows?
Maybe every Saturday,
you need your entire SRE
team looking at it. But right now, it's not mega crashing.
Because what we thought is that this was going to immediately crash
when you add enough complexity to this.
Because it's just a statistics thing.
The chances that there is some bad interaction
when you pull out of threads and the amount of code that is here
is inevitable.
And still, from time to time,
we find very funky in an interpreter
when you call a method and sometimes another method is called
because there was something like a memory reordering problem,
which is a very technical, deep thing.
And debugging that particular thing is just hard.
But that is very rare, and obviously we fix it immediately.
And we are really surprised about, first,
how many people have jumped at this
and they're super excited
and they want all of those extensions working.
And second, how quote-unquote stable this is.
Meaning that how little bugs we have seen in a while.
We expected many, many, many more
and we are seeing very little.
So right now it's super promising.
Yeah, what does help is that we do have
the people behind it,
like some girls who actually did the prototype of 3.9 and then 3.12,
now who is working on making this for 3.13 and forwards,
is being helped by other engineers who are really into this
and are able to find threat safety issues and data races and so on, we were
able to set up Thread Sanitizer,
which is very
complex to set up in
an interpreter environment like
Python. Turns out it does help us
with finding those issues.
Some of them are pretty funny, like
figuring out that
for this entire time, the
thread handle in Python was not thread safe itself.
Or the threading lock was not thread safe itself.
So once you actually did the operations of locking,
yes, those were thread safe,
but the Python object that you used was not
because it didn't have to be.
And now all of those things have to be actually fixed
so they are probably formally correct now. So yeah, there's been a lot of work and a lot of work is still to
be done. But our hearts are warmed by how little terrible and unsolvable issues we've
seen so far. Some of them are complex to debug and complex to diagnose,
but we've been successful in improving the situation so far as we go.
So for your average programmer out there with their average
Python app, whether it be a web app or a desktop app or whatever,
should they be hopping on this experimental and giving it a try?
Or is it a thing where it's like, if you don't know that your code is thread safe
it's probably not
or is it the other way around
like what's the water feel like
is it warm
is it
are there alligators in there
well it depends right
like if they
if they are paid to make sure
that the thing is stable
the recommendation is no
like because like
I mean try it out
sure
you can get very excited, by the way.
Like one of the things that we have seen,
me, myself, right?
Like for instance, I'm at the company I work,
Bloomberg, is that we have tried,
like to see what will happen.
Like even if it crashes from one,
every three months, right, whatever it is.
But just to see a sense of like,
what is the improvement here?
Because like, if then down the line,
you're going to justify any effort on your side
to, you know, adapt your thing
to the free thread version, it's really good that you know what you're going to justify any effort on your side to adapt your thing to the free-threaded version,
it's really good that you know what you're going to gain.
So that for sure.
Trying, we really want people to try.
And tell us what they see and what doesn't work.
Is this a production-ready workload?
Absolutely not.
Not because we know it's going to crash or anything,
but because we don't know the real status of the thing.
We take stability very, very seriously in the core team. is going to crash or anything, but because we don't know the real status of the thing, right? Like, we take
stability very, very seriously
in the core team, so
we are not comfortable right now.
That's why the thing is called experimental,
because we are not comfortable right now
recommending people, you know,
especially when you not only have the interpreter
but all these other things, right?
And, you know, still we need to figure out
good APIs for those extensions
to hook into the interpreter
and things like that,
and that is not there right now.
So the chances that we can look at these things
and say, yeah, this can run in production,
no problem, is almost zero right now.
But as we release Python 3.14 and 15,
we will move this experimental into supported,
which means that you can run it in production
but there still will be two versions
and eventually when we gain enough confidence
that this is the future we all wanted
it will be only one Python
which will be Python without the free third version.
But until we call it stable and supported
that's the keyword, supported
I wouldn't recommend people to actually use it in production environments.
Yeah, production environments. However, I would be a little more optimistic about this
saying that if you are an end user, probably
the amusement park is still being built for you.
So this is not something that is ready for end consumption.
Unless you are really just
trying to just see how pure Python works without all the libraries that you depend on. However,
if you are a maintainer of a library that a lot of people depend on, you might be interested in
checking it right now, right? So we already see plenty of interest from the data science libraries and web frameworks and so on and so on.
And that's exactly the right moment for them to identify whether there's any blocking issues or whether the gains are not enough for us to justify the change.
Or maybe the opposite, or maybe they're amazed at how better things are right now. And like, funnily enough, even things that were not ever designed with free threading
in mind, like async IO, like you run the test suite of async IO and it's just faster on
free threading because it just can magically utilize the fact that it is now truly parallel.
So there is promise there.
Definitely, we expect that, you know, once the library authors actually, you know, go
through some of those hoops that are required for their things to be supported by the free
threaded version, we're going to see uptake on more libraries and then more users and
so on.
So now's the time for the library maintainers to check it out.
But for end users, it is a little soon.
That makes a lot of sense. time for the library maintainers to check it out. But for end users, it is a little soon.
That makes a lot of sense. Somebody should start a list of libraries which have taken that initiative.
There is a list like that right now. There is a website. I forget the name right now.
We might add this to the metadata of this episode so that you can check this out. Just
as in the Python 2.2.3 transition, we had a list like this.
There is a list.
It is very fresh,
so I forget the website name right now.
But it's there.
Cool.
Very cool.
Well, it's definitely exciting times.
I'm even excited.
I don't use Python on the regular.
But I think that's early indicators
of something that's potentially a huge success.
So congrats to you guys and the whole team for the effort, at least,
to make it no longer theoretical and make it an actual piece of software,
bleeding-edge piece of software that's going to produce even some papers.
Should we move on to the JIT?
Lucas, you mentioned the JIT is another feature of 3.13.
Is there more to say about the GIL?
I'm assuming these things will probably interact as topics.
Right, so the JIT is still one of those other topics
that I remember being this big pipe dream of CPython
for as long as I can remember.
We grew a few attempts to have a JIT
in forks of Python or entirely new Python interpreters,
most of those efforts failed.
There's one holdout that is actually doing very well,
that's PyPy, and that is actually JITed,
which proves that this language can successfully
use this performance strategy for good results.
As a clarification also for the people that don't know.
ByPy is not a JIT for CPython, it's an entire different interpreter.
It's like the same language, but it's just a different interpreter written
actually in Python, which is JIT at the end.
But it's a separate thing.
Yes, it is an entirely separate technological stack.
It is attempting to be bug-to-bug compatible with CPython.
People adopting it have seen,
your mileage may vary sort of results
where it might be really a drop-in replacement in some cases
and might be more tricky to actually adopt it otherwise.
Plus the approach of JITing they're using
has some characteristics with memory usage being larger and so on.
So it depends on your use case.
But obviously the most popular version of Python is CPython,
is the version that we are working on.
So this is an idea that just comes back and comes back and comes back.
Like when will Python have a just-in-time compiler?
So to a large approximation, if you squint really hard,
this specialization that Pablo already mentioned
is sort of slowly becoming a form of what digits are doing,
which is to remove all this indirection.
But the last step that they did not take so far,
those optimizations, is to actually replace
running this C code with this C code with an actual
compilation to machine code as we go dynamically,
which is what the JIT is doing. And Brandt Bucher, one of our
core team members, found out this paper about
how you can automatically generate a JIT
for the Lua interpreter
and how it is slower than a handwritten JIT,
but not by that much as you would expect,
and it is much more maintainable.
And using this approach,
with this additional machinery that is needed
for the JustTime compiler
that tries to compile
during our build time, like the simple opcodes
that are later glued together to this optimized machine code
and so on, and to discover whether that trace
that we're running is still correct
or maybe we need to throw it away
because we thought this thing that we're running
is like adding two integers, right?
But now we're seeing, oh, there's a float
that we did not expect.
So we need to throw out this optimized code
and actually go back to the interpreter again.
So all this infrastructure is already in 3.13.
And so far, we can proudly say
that with all this added, Python is not slower.
It's 0% faster. Yes, It is 0% faster because, again,
with the release cadence that we're having,
12 months of work is a lot, obviously,
but it is not enough to just say,
we started from zero JIT and ended up with a mature JIT
like V8, we are done.
It is just simply impossible,
especially that our team is much smaller than the V8 team,
much smaller than the Java hotspot team,
and so on and so on.
So yeah, so far there is another experimental feature
in Python 3.13, which is the JIT.
You have to compile with that,
and you have to enable it when you're running Python.
So it does not have most of the optimizations
that you would expect from the just-in-time compiler
because that entire technology of just-in-time compilation
is essentially a framework on top of which
you can now make optimizations that make things faster.
For example, if within the trace that you're building,
connecting all those machine code blocks
that are now faster and removing indirection,
you have multiple checks whether something is none
or something is an integer,
you can move that check of that same piece of data
to the front of the trace and just do that check once
and you don't have to repeat it in different parts of the code and so on.
And to make sure that the traces are as long as possible,
those are different levels of optimization.
You want to JIT relatively quickly
so that people can see the uplift very quickly,
but you don't want to JIT every code
that is being executed
because that would make the memory usage crazy.
So there's things that you need to dial in there and implement.
So it is very much an in-progress project. It looks very promising,
but so far Python 3.13 is a snapshot
of the current stage of that effort as well.
Pablo, anything to add?
Well, one of the things that is very exciting with the JIT right now is that
the approach itself is quite cool.
Like for instance, if you're making a JIT
for a dynamic language,
one of the biggest challenges is not only
adding the infrastructure itself for a particular CPU,
but like our architecture,
is that you need to do it for all of them
and for every single OS.
Because at the end, you're writing machine code
and machine code depends on your CPU architecture,
your platform.
So the JIT is not the JIT
or as we like to call it
legit.
You need one for
Windows, one for Mac OS,
one for Linux, but also one for
AMD 64, one for AR 64,
one for ARMv7.
So you can imagine how hard
this actually is because you basically
are implementing a compiler, right?
But this approach that the brand
is taking not only has the advantage
that it's basically leveraging an existing
compiler behind, in this particular case
LLVM, but also
it's doing it at the front.
So it doesn't happen at compile time.
All that assembly code has been generated before
and the only thing that we need to do at runtime
is stitch those things together.
So we have these templates.
So Clang is basically, or LLV is not a runtime dependency.
Like it's just a build time dependency.
So you build all these like assembly code
and it uses the native compiler for your platform.
So if you're in some forsaken platform
like, I don't know, AX or something like that,
it will work if you are able to run Clang there. So if you're in some forsaken platform like, I don't know, AX or something like that, it will work
if you are able to run Clang there.
So that's great, but also,
which is really cool, and most
Jits need to also implement themselves,
is that we are able to leverage
an optimizing compiler for this particular
workload, right? So not only that assembly
code works for every
architecture because someone else actually implemented
the backend.
But also we can leverage all the
optimizations that
everybody that's using
LLVM is using.
It's the same
optimizations that
Rust is using.
Rust is using LLVM
these days still.
And they are using,
I mean, if you
program the IR, the
intermediate representation
correctly and then you
are able to leverage
that well, which is
not, you know, it's
easier said than done.
But the idea is that
now you can use this
set common of very, like these many years of
compiler research just to make your code faster.
And you can just leverage that immediately as opposed to having to reimplement all those
things and have like SSA ourselves and like, you know, dreaming and all that stuff.
Like now, you know, you just run Clang and you get some super cool assembly out.
You need to just stitch it together
and feel like the symbols and whatnot.
But you can get results much, much faster
than if we need to implement a full-blown JIT for Python.
So very excited.
It's like a JIT factory.
Yeah, literally.
Java style.
You guys use factories in Python?
JIT template factory.
What's up, friends?
I'm here in the breaks with Dennis Pilarinos,
founder and CEO of Unblocked.
Check him out at getunblocked.com.
It's for all the hows, whys, and WTFs.
So, Dennis, you know we speak to developers.
Who is Unblocked best for?
Who needs to use it?
Yeah, Unblocked helps large teams with old code bases
understand why something has been done in the past.
It helps them understand what happens if they make changes to it.
Basically, all the questions that you would typically ask a co-worker,
you no longer have to interrupt them.
You don't have to wait for their response.
You don't have to, if you're geographically distributed, you don't have to wait for their response, you don't have to, if you're geographically
distributed, you don't have to wait for that response, you
don't have to wait for, you know, you don't have to dig
through documentation, you don't have to try to find the answer
in confluence and Jira, what we basically do is give you the
answer by you just asking a question, the way that we got to
the problem was a consequence of our kind of lived experience,
we're actually going to call the company bother, which is like, you don't bother me, I don't bother you, right? Instead of
like being tapped on the shoulder or interruptive Slack messages, we could just use Bother and get
the answers that we wanted. We didn't go with that name because it's a little bit of a negative
connotation, but helping developers get unblocked by answering questions or surfacing data and
discussions within the context of their IDE relative to the code that they're looking at is something that thousands of developers love so far.
I think our listeners are really familiar with AI tooling, very familiar with code generation, LLMs.
How is unblocked different from what else is out there?
A lot of code generation tools help you write the code to solve a problem.
We sit upstream of that. Our goal is to help provide the context that you need.
If you think about where you spend your time when you're trying to solve a new problem,
understanding how that system works, why it was built that way, what are the ramifications of
changing something? That's the problem that Unblock tries to solve for you. We take the
data and discussions of all of these, the source code
and all those systems to provide that answer for you so that you can get that context and then you
can go and write that code. We have this great example of a company who hires, you know, very
competent developers. It took them five days, that developer, five days to write 12 lines of code.
And his feedback to us was, it's not that it takes you five days to write 12 lines of code. And his feedback to us was it's not that it takes you five days
to write 12 lines of code. It took them five days to get the information that they needed to write
those 12 lines of code. And that takes probably about 30 minutes to write those 12 lines of code
and rip off that PR. Okay, the next step to get unblocked for you and your team is to go to
getunblocked.com. Yourself, your team can now find the answer they need to
get their jobs done and not have to bother anyone else on the team, take a meeting or waste any time
whatsoever. Again, getunblocked.com. That's G-E-T-U-N-B-L-O-C-K-E-D.com and get unblocked.
If we can move this conversation up a level for a moment, do you guys like
this one-year release cadence? It seems like
it has its drawbacks. Well, this guy implemented
that idea, so what do you think he's going to say?
Who did?
You did this? Yes.
So we can make this
good cop, bad cop, or
actually devil's advocate,
and this guy is trying to buy this, this is good.
So I'm also the release manager of some ancient Python versions.
In fact, when Python 3.13 comes out,
the first version I released, which is Python 3.8,
is going end of life.
So we're going to say goodbye to that.
It was a very, very nice release.
I really enjoyed Python 3.8, but it's time to move on.
So if your use case, if your production is still running on 3.8,
well, now it's high time to move
since it's not going to receive any security updates anymore.
Right, so at the time I joined as the release manager,
the release process was a little bit hand-wavy in
terms of when are we releasing Python. So the theory said we're releasing it every 18 month-ish,
but it could be anywhere between 18 and two years. And you know, you couldn't really tell.
And definitely what you could not expect was which time of the year is this going to happen in. And the consequence of this
was that Linux distributions in particular, but also other operating systems and users,
were lagging behind adoption of Python 3 versions a lot. People are like, well, Python 2, no,
because Python 2.7, right? But Python 2.7 was out and then essentially frozen for a long, long time.
So people forgot how this thing looked like before in times of Python 2.3, 2.4, 2.5, 2.6,
and then 2.7. That unstable release cadence was problematic. And that cost, for example,
for Fedora, which later is source for what is happening in Red Hat, was lagging behind with
the releases that we had.
And it turns out that the infrastructure that the big Linux distributions have, like Ubuntu
and like Red Hat, is extremely useful for us to early find bugs in a new version that
we are developing in the betas, in the release candidates, and so on. So it would be worthwhile if we could actually ship the newest version of Python with those
Linux distributions as they are also developed and go through their respective betas and
so on.
That's also great for the end user, right?
Because then by your autumn release of Fedora, you are released with the newest version of Python
that was just released.
That is a great experience for the end user.
So I wrote a Python enhancement proposal document
arguing those things that I'm just telling you,
that it would be amazing to have a fixed release cadence
that we can trust and share with the Linux distributions
such that they can essentially rely on us
having certain milestones in the release,
like reaching data one, like reaching release candidate one,
so that they can use the latest version as soon as possible.
And we switched to the release cadence in Python 3.9,
and we've been using it ever since.
So yeah, your honor,
that's my position
on this issue.
Well, as the other release manager
of Antim versions now,
so I release 3.10 and 3.11.
I mean, one of the problems
that this thing,
I mean, it has worked really well, I think.
People in general, and just to be clear,
so Wookas doesn't kill me after we finish the podcast.
I think it's a positive chase, right?
So in general, very good.
I think it has been some predictability.
People actually now have dates
and they can put their lives around.
One of the interesting side effects of this
is that now people have this impression that Python
is releasing too often, so every single year there's a new version, and then the old version
gets out of support, or first backfix support and then security support. So they have this
feeling that if they don't move fast enough, they are going to be able to support super
soon, which was always true, is that you get the numbers changing slower,
so the impression was that it's happening slower.
But right now, this is moving this impression
that Python is changing too quickly, right,
or whatever it is.
The other downside that this has is that,
as you can see, for instance, for Python 3.13,
it means that because we need to release every single year,
we're releasing these features, maybe like big ones,
like the Nogil or the JIT in particular,
not being super exciting.
So for instance, JIT in particular is 0% faster.
Well, it's kind of cool, but where would you use it?
Well, if we have a two-year release,
maybe it would be a bit better.
So you get these weird situations.
So planning big projects right now
is a bit more challenging.
For instance, one of the things that happened
in Python 3.9, if I recall,
we changed the entire parser of the language. Like, bonk,
different parser, which I'd like to describe
as changing the wheels of a car that is moving.
Not the best feeling.
But that was a bit,
like, that could have,
we could have had some extra
rest if that was a two-year
release cadence and we didn't have to
finish everything and all the validation in one year. I mean, this doesn't mean that it was rushed.year release cadence and we didn't have to you know uh like finish everything
and all the validation in one year i mean this doesn't mean that it was rushed it's just that
we have to put four hours just because we wanted to make to the release but on the other hand like
this you know it's humans making it so uh even before when when the situation was uh like bookish
was describing the day of beta freeze which is the moment when that no new features can come in and
only backfixes from that point on in the release,
everybody was rushing their feature on the last day.
All the new features.
Humans are humans, so it doesn't really matter.
Certainly the hit has been raised a bit
because right now it's released more often
and the numbers are changing faster.
That was more the angle I was coming from.
When the train leaves the station once a year you better get your stuff on it
whether it's ready or not right and i appreciate i didn't know the history of where it came from
so i think this is definitely progress and improvement predictability you know each time
a year it's going to go out etc etc and it makes a lot of sense especially a large project like this with tons of people using it you want to be predictable but also not
too frequent i would probably tend towards more frequent because now you have the train leaving
the station more times and if you don't if you miss this one that's all right we got another
train leaving six weeks from now and so you can hop on when it's ready versus having to hop on
once a year and that's you know we've seen success in projects like Chrome, etc.,
with rolling every six weeks, whatever's ready,
we're going to ship a new version.
I don't know if that works with languages and runtimes.
You guys know way better than I do, which is why I asked the question.
I guess for compiled languages that might in fact work better,
for us the difference is that we're interpreted.
So there's a lot of code that is lying next to your interpreter
and then you're trying to run it with whatever is available to you.
With a lot of the libraries that we're supporting, they're a particular issue.
So now I'm going to be the devil's advocate because Pablo
was too apologetic.
Let me just say,
hey, this is all a compromise.
And there's obviously going to be things that are better
and things that are worse.
The price to be paid for shorter release cadences
is that the matrix of tests of CI
that a library maintainer has to now kind of suffer with,
has to run, is larger, right? Because the number
of versions that is out there that people are using, there's just more versions than there
were before, right? You had 2.7 and 3.6 maybe, and then 3.7 appeared some 18 or 19 months later. So
then the growth of this matrix was sort of spread out in time. Now that matrix is bigger.
I would claim that, okay, it's good that we're testing with every particular version to identify
where an incompatibility arose or something. However, I always like to say that it's still
the same sausage, right? We're still the same sort of team that is developing the thing. We still have the same velocity,
only we slice it
thinner now. So
every release is easier to
migrate to compared
to the last release because
not necessarily
there were fewer changes.
Psychologically speaking, that's a very good point, actually.
I'm glad that you mentioned it.
One of the things that happens when you release every two years or more,
especially for a language that needs to evolve and needs to change things,
and maybe doesn't have...
I mean, we can add a backwards compatibility, don't get me wrong,
but other languages like C++ clearly carry even more.
So for a language that changed this much,
changing and adapting your code and all the libraries
for a two-year worth of changes is brutal.
Which means that, and we saw
that before, right? Which means that
until new libraries are compatible with
the new version, there's a non-trivial amount
of time. So as a user
or as a company employee that you want to leverage
these new features, you probably want to wait a lot
because now people talk
about scheduling their work and
finding even how much it is.
And library maintainers say, well, I will fix it later.
But when the changes are smaller,
that is psychologically speaking, obviously,
in reality, it's more or less the same,
modulus and nonlinear interaction.
But in general, when the changes are smaller,
then it's more enticing, because at least you know,
okay, maybe this, this, this, and this thing.
And sure, maybe you need to wait for another library to do it,
but normally, this, this, and this thing. And sure, maybe you need to wait for another library to do it, but normally
and right now, what we have
seen compared with 3.8
when we started doing this, is that
people jump earlier. Before,
for instance, one of the biggest libraries is
NumPy, which is numerical
computing in C, and
Fortran and whatnot. So that library
used to take a long time to be
compatible with new versions, like months
or sometimes even like half a
year or something. And right now we are having
it almost day one.
So this is fantastic because
people that want to use the new features
in the language, they are not held
back by the fact that their own particular
dependencies don't
have the support for this.
So most of these things, I don't think you can
approach it from a data-driven
perspective because it's
very difficult to say what is better and what is worse.
But certainly
from a psychological point of view,
again, I think you have a very good point.
Not too soon, not too often, sorry,
but also not too
lagging behind. I think
earlier is better, Maybe not too early.
Every three weeks it will be impossible
for a compiled language.
We will ship a JIT compiler
that unoptimizes your code.
It will be like 6% slower or something.
But one year, yeah, good.
I want to add one thing.
So NumPy is not doing as well as Pablo is claiming.
They're doing way better.
There are already wheels for Python 3.13.
Before the release of Python 3.13,
those wheels are going to work on the final version of Python 3.13
released October 1st.
We're releasing this mid-September.
They're already there.
Moreover, they're also already there for the specific version
that is this experimental
interpreter
that does not have the GIL.
I think everyone,
a non-trivial amount of listeners probably are
saying, what is that wheel?
What is this thing?
Yeah, so it's this binary
package that lives on the Python package
index on PyPI that people
download NumPy from
when they say pip install NumPy.
So if you say pip install NumPy from Python 3.13 on day one,
you're going to be using wheels that are already there
before the release of Python 3.13.
Is this another word for a build?
Basically it's a binary package.
So it's a package that doesn't contain Python code only.
Why do we make up another term for it?
Well, this is the key, right?
Because the Python package index used to,
well, I think it still is,
it's called a cheese shop
because it's all about these Monty Python references
and jokes, right?
So it's a sketch of Monty Python
that goes to this cheese shop.
And a wheel is a wheel of cheese.
Oh, gosh.
So, you know, ha, ha, ha.
I'm taking that one a bit too far, maybe.
Or like pip
pip is a slightly different joke
pip is a package installer for python
so when you install python you do pip install
do you know what pip means?
python install packages?
pip installs packages
so a recursive acronym
recursive
recursive acronyms I'm well aware of
but I'm not a Monty Python guy
so I missed completely this reference
well you know
I was missing this reference for years
and someone pointed it out
I have to watch it
is it from Holy Grail
or which movie is this
no I think it's one of the Flying Circus movies
yes one of the episodes of the Flying Circus
has a skit about the cheese shop.
And that's where that comes from.
It's an obscure reference to build
an entire Python ecosystem around, but okay.
I think it's not helping for Python programmers
to look like they're in a co-win or something.
But you just need to have some file extension
for those things and some name for those things.
We used to have a more primitive early format
for this sort of thing, and those were called eggs.
Eggs were because snakes lay eggs, right?
So that made this other sort of reference
because Python and the name comes from Monty Python,
but a lot of people just see the name Python
and they're like, yes, snakes are cool, so snakes.
We accept both sort of
ways of interpreting this because
snakes are indeed cool. Yes, sure.
But yeah, like now that we
knew that eggs are not enough
for what we need for proper binary
packages, we were like,
where to go now with names? And naming is
hard, let me tell you this much. Naming is
very hard. Someone jumping in the middle of the podcast
listening to us talk about eggs and snakes.
Wasn't this about tech?
Again, this background is spectacular
because you do run out of references with snakes.
How many things can you actually reference?
But with Monty Python,
there's just countless references you can make.
Just people won't get them.
But yeah, they're very obscure these days.
It's increasingly old and hard to get.
For instance, one of the funny ones,
one of these attempts at deep compilers from back in the day,
I think from Google, was called Unladen Swallow.
From the Monty Python Life of Rangin.
No, no, no, sorry.
Holy Grail.
The speed of the Unladen Swallow.
Good stuff. Okay, good meta conversation on sorry, Holy Grail. Holy Grail. The speed of the unladen swap. Good stuff.
Okay, good meta conversation on release cadence.
I think I agree with all your points.
You have to find that sweet spot
and as frequent as you can be reliable
without being too frequent.
And that probably varies per project.
And I'm happy that you guys are happy with once a year.
Certainly better than what y'all were doing before.
That's very cool.
Let's go back to Python 3.13,
because Pablo, at the beginning you mentioned
it's officially iOS compatible or something.
What does this mean?
You can just fire up Python on your iPhone?
Well, not quite yet, I would say.
But one of the things that...
So see, Python has a very old build system, right?
It's AutoTools, which is this computer make.
People that have been doing Linux for a long time
probably have run into this.
And one of the challenges of this is that...
And then it's another different for Windows.
But both macOS and most Unix platforms use that.
So for a long time, that was okay.
But there was a lot of platforms that we couldn't support
partially because of the build system
and partially because the source required changes.
For instance, many of the efforts that we are trying to do right now
to make Python available in the browser,
I don't know if you have heard about this,
but right now there is a good effort to ensure that Python can run in the browser
and it's a good alternative to JavaScript.
This is a project, for instance, called PyScript,
which allows people to run Python instead of JavaScript,
which is quite cool.
So those require changes in these build systems
and even in the source of itself.
And iOS in particular has quite a lot of challenges.
Actually, probably Lucas can chime in to specify those
since this is very
close to his heart.
But one person in particular
that has been working
for iOS support,
which is Russell
Kim-Magee.
Yeah, he works right now
at Anaconda,
which is one of these
Python companies.
So he has been working
quite hard to ensure
that both the build system
and the source itself
works on iOS,
which has a lot of challenges, right?
Because iOS has not only
an alien way of doing things,
but many APIs are not available there,
or other apps are not available, but you need these specific
things that you need Apple to
bless you with their power just to be able to
use. Like the GIT compiler,
how does the GIT compiler run iOS?
Who knows?
Maybe let's start from the very beginning there.
So the goal that we have with this iOS support,
for the time being at least,
is not to have an application on the App Store called Python.
That's not what we're doing.
What we are doing right now is to have the Python distribution,
the source distribution, ready entirely
for being embedded within another
application that somebody wants to release on the App Store for iOS, right?
This was theoretically possible in the past with already a ton of hacks that Russell Keith
McGee historically made for a project called Beware that is just running Python on mobile
on both Android and iOS.
But the Python source code, our source distribution,
was not making this easy.
There are plenty of changes that you may have to make
because the phone platform that Apple came up with
is very limited.
It is limited by design, such that it's more secure and it doesn't waste
your battery too much. And it does a bunch of other things that make it easier for applications
to be just swiped up to kill them and they don't run any runaway processes and whatnot.
So there are APIs there that are not allowed. There are others that are just not implemented,
so they're not available.
So you cannot run threads and so on.
So this sort of thing causes embedding Python to be complex.
Then there's the new and increasingly strict rules
around when you're packaging some sort of binary blob
and want to put it on the official app store for Apple,
they have this automated and sometimes in person,
but mostly automated review process,
whether what you're publishing is safe.
So there's plenty of things that interpreted language
like Python would do that would be flagged
by those automated systems as unsafe,
that this code is doing something fishy.
So there are changes needed for those things
to just pass review so that your application
that embeds Python can successfully actually appear
on the App Store.
Like including until very recently,
you couldn't really have just dynamic libraries
lying around in your bundle
that you're publishing on the App Store.
Everything had to be statically compiled,
which puts, depending on libraries like NumPy, into jeopardy
because it is very hard for external C extensions to be built
in a way that they are both all part of a single binary.
Now this extension is lifted.
However, you have to sign everything that you're publishing
to the App Store separately.
So it has to be notarized by Apple, it has to be signed with your application developer
certificate and so on. So you know, you know, when you're sending out this code to Apple that,
okay, this is the code I built, nobody meddled with it. And then Apple notarizes it that, okay,
this one is safe to be run by, you know, users' phones and so on.
So all this infrastructure, like it seems like something that shouldn't really be our concern.
But all of this was making it hard for Python to just be embedded.
And now with Russell's hard work, this is a platform that we support.
So if you want to have a text editor that has automation in Python,
if you do want to have an editor for Python source code,
there's a few of those, like Pythonista, Pyto, and so on.
Now it's going to be much easier for the authors of those
to upgrade to a newer version of Python.
This is why all those apps lagged behind
and they were still on Python 3.8 or 3.10,
because it was a ton of work to upgrade
and redo all those hacks in a newer Python version.
So now, unnecessary, we support it.
That definitely wasn't what I was thinking,
but it makes a ton of sense.
I think it's going to make some people very excited.
What were you thinking about?
Yeah, what were you thinking about?
Write some Python code and deploy an app based on it.
Like, build an app in Python.
Right, so this is kind of step two for the Beware project
that Russell Keith-Magee is part of,
which is now being essentially sponsored by Anaconda,
where you're going to be able to build Python applications
from scratch and end up with an app on the iPhone
that you can put on the App Store and it's fine.
But the first step of this is that
all this additional tooling that Viewer is building
on top of Python needs to rely on Python being embeddable.
Right, also conceptually speaking
it's not different from the first use case
because you're not going to have one single Python
in the App Store that everybody can use.
You need to have, everyone will have a different Python in the app store that everybody can use. And you need to have,
everyone will have a different Python version.
So it's a trivial embedding.
So you're not embedding this on a text editor.
You're embedding it on a binary that is just Python.
But you also want to see,
not only your Python code,
you want to see your dependencies as well.
So now, okay, this is the same.
If you want a text editor to have Python inside
to do some extension, you may want some extensions
that Python can do to interact with something else.
So maybe you want also that and the dependencies.
So technically, if you screen hard enough,
it's really the same case.
It's just that for the developer that just wants
to put some files and maybe to say,
I require this and that, that's a lot of work.
You're in the business of compiling
Python yourself, what are you talking about?
So it's much better
if we can offer a specific workflow
that says,
okay, your case is only
this and that, and you only have these dependencies,
then you just click this, put this here,
and the build process will take that
for you, so you don't need to, that's step two.
But conceptually speaking, it's just a web tooling,
not really a huge undertaking.
But really, it's like, again, incremental steps.
So the important thing here is as well
that this is now part of our CI.
We are building Python on iOS every time you make a change.
So it's going to be much less probable for us to introduce changes
without knowing that they break support for running this on the phone,
which should be great news for anybody that actually wants to see Python on mobile devices,
because now we are going to care to keep this running.
Well, now you have me thinking about the future.
Let's close on this wish list.
Imagine that the three of us are sitting down next September and talking about 314.
What do you want us to be talking about?
What do you hope we're talking about going into 314, each of you?
Oh, okay.
So my dreams are simple.
I want everything.
I like that.
So honestly,
I sponsored the,
you know,
making the optional PEP.
So this is very close to my heart.
What I would like to see
is for this to pay off
for the library developers
to step in,
try it out and say like,
hey, actually,
this is helping us.
What is related to this
to see that the performance efforts
that we are having separately
from the global network block removal
actually converge and kind of do work
with this free threaded version.
And also finally, again, free threading.
We don't expect people to actually start new threads randomly and end up in this crazy world of free threading. We don't expect people to actually start new threads randomly
and end up in this crazy world of free threading
where you can just easily just write bad applications
by writing on top of your variables
and accessing data you shouldn't.
We don't want to reintroduce models
that already we know failed in other languages.
We want tooling to be more high level.
So I want this more high level tooling
to start popping up slowly.
We deliberately didn't suggest any so far.
We want to see what the community actually wants to use.
There's kind of things that happened
in other more younger programming languages.
You know, you have goroutines, right?
Like you have channels in different programming languages, you know, you have Go routines, right? Like you have channels
in different programming languages and so on. So I'm very excited to see where this
goes. So this free threading evolution is what I would like to be able to tell you next
year that, you know, has done great leaps and it's now way more usable and it's literally
the future. So yeah.
Well, in my case, I think apart from what Gukas just said,
I think the key for me is that this pays off,
which is not trivial, right?
It may pay off for some users, for sure,
that are really hungry about this.
But what I really want to know is that people,
for a lot of time, removing the guild
has been almost like a joke about,
this is what is missing.
This will be the last thing and everything will be so green and fantastic
when we remove the guild.
Well, now I didn't approve it.
So I want to see everybody saying, now that there is no guild,
I finally can do this and this thing,
which is not going to happen fully, right?
Because people still will reach to other languages
for other reasons and performance, right?
But I just want to see a big impact there.
And ideally, we talk again for 3.14,
we are saying, okay, this makes a difference, right?
So it was cool, sure, and some people really like it,
but wow, now it's a different play field, right?
So it's different.
The other thing that I would like to see,
and this is a bit more personal,
so this is a project that I started I think in Python 3.10
which is that a lot of people were complaining
that the user experience of the language
was not really great in terms of error messages
and things like that
so syntax errors
and you mistyped something
or there is some import problem
so that was really bad to the point that there were some situations that were laughable.
And we have worked quite a lot with the new parsers
and with many other improvements to improve this, to the point that right now I'm super happy
to see that many, even papers that are researching error messages are citing Python
as one of the, obviously not in the same category as Rust, because we can all agree that
Rust has fantastic error messages.
Different kind because those are compiled time
error messages that we're talking about runtime ones
if you don't consider the parser bad.
But we are right now
quite high in that sense to the point
that I think there was some
research about how LLMs can
reason about what's wrong about your code from the errors
and you run it in 3.11
it was like a 13
sorry a 30% like better
you know performance of those
just because it's telling you a bit more right so you can
fix the code a bit better which is quite cool
so we continue doing this thing
and we are trying to add like even
bigger changes to the interpreter that help
in this regard which is challenging because
those changes sometimes require
some non-trivial performance
games there. So obviously we don't want to
affect performance, but to do that
we need to put a lot of engineering there.
So in 3.14
we are probably going to try
some new ones that are quite big.
So hopefully when we talk again
those have actually been implemented
and they have been successful,
which I would love to see.
Yeah, that's awesome.
I was reading about your improved error messages
and I think that's the kind of thing
that has to be a sustained effort over time.
It's like one of those paper cuts kind of things
where it's like, we're just going to continue
to polish this thing.
And so a great effort.
I'm glad that you struck that up.
Well, the podcast core.py,
if you are a super Python nerd and want to nerd out with these
two about internals on a more frequent basis then we'll cover it here on the changelog which sounds
like it's going to be about once a year i'd love to have you guys back next september and be talking
about 314 hopefully all of our wishes will have come to fruition and we'll have people out there
free bird net i mean free threading it.
Free threading it.
Cue Leonard Skinner here.
Won't you fly free birding?
And enjoying the new Python with no gill
and the performance improvements that are possible there.
Lots of potential.
I'm certainly looking forward to it.
Guys, thanks so much for coming on the show this week.
Thanks for having us.
Yeah, thanks for having us.
It's been a pleasure.
Okay, so now that Python is officially,
experimentally, free-birded,
I mean, free-threaded,
are you going to defenestrate the gill?
Let us know in Zulip.
Yes, the Changelog community's conversations are now happening in Zulip.
Join today by signing up at changelog.com slash community.
If you've already signed up, but you want your Zulip invite,
just sign in and click on send me a Zulip invite.
You'll see it.
Of course, it's totally free
and a totally cool place to hang out and discuss let's do one more big thanks to our sponsors of
this episode Sentry we love Sentry you might too use code changelog save 100 bucks fly.io
the home of changelog.com ship something in five five minutes or less. Learn how at fly.io.
And of course, to Coder.com and Unblocked.
Please support our sponsors.
They support us.
And thank you, of course, to The Goat.
Breakmaster Cylinder is the greatest beat freak of all times.
Finally, thank you for listening to our shows.
We truly appreciate you spending time
with us each week. That is all for now. But on Friday, we are talking about developer happiness
and unhappiness and productivity or lack thereof with our friend Abinoda from DX. That is a fun
one. So stay tuned. That's all for now, but we'll talk to you again on Friday. Thank you. Game on