Have you heard that Python is not good for writing concurrent asynchronous code?
This is generally a misconception, but there is one class of parallel computing that Python is
not good at, CPU-bound work running in the Python layer. What's the main problem? It's Python's
GIL or global interpreter lock, of course. Yet the fix for this restriction might have been hiding
inside Python for 20 years, sub-interpreters. Join me to talk about PEP 554 with core developer
Eric Snow. This is Talk Python to Me, episode 225, recorded August 2nd, 2019.
Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem,
and the personalities. This is your host, Michael Kennedy. Follow me on Twitter, where I'm at
M. Kennedy. Keep up with the show and listen to past episodes at talkpython.fm, and follow the
show on Twitter via at Talk Python. This episode is supported by Linode and TopTal. Please check out
what they're offering during their segments. It really helps support the show. Eric, welcome to
Talk Python to Me. Hi, how's it going? It's going really well. It's an honor to have you on the show.
We met up at PyCascades and talked a little bit, but this latest work you're doing to address
concurrency and parallelism in Python is super interesting. So I'm looking forward to talking
to you about that. Well, it's super interesting to me too. Yeah, I can imagine. I'm glad you're
interested. This kind of stuff is, I don't know, there's just something that draws me in and I'm
really enjoy exploring it. But before we do, let's start with your story. How'd you get into programming
Python? Oh boy. I had all sorts of ideas on what I wanted to do growing up and computers was not
really one of them. But then I ended up at school and somehow ended up signed up for computer stuff,
ended up getting a CS degree. And then it's funny because I actually, while I was in school, I was
working for a web hosting company doing technical support. Once I graduated, I moved over to a development
team. And the guy I replaced is, you may know him, he's named Van Lindberg.
Okay. Yeah.
So it's kind of funny. So I ended up working on this project that Van had been running and ultimately
ended up kind of being the tech lead on that project. It was all written in Python. And so I
have Van to thank for my introduction to Python.
That's really cool. So you went from talking to the customers and helping them with the problems
the developers created to creating the problems for the person who took the job.
Just kidding.
Kind of.
Yeah. That's a really great progression, right? Like you sort of get your foot in the tech space
and then, you know, you make your way over to kind of running the team. That's great.
It was a good experience. One neat thing is that it was pretty flexible as far as the job goes.
There were only a handful of us on the team and we're doing a pretty big job, but we had taken an
approach of highly automating stuff. So it was mostly just a matter of making the effort to address
automation stuff, which meant that otherwise we had a little more time to kind of delve into issues and
solve problems in a better way. And as part of that, whenever I'd run into Python stuff, like I couldn't
figure out what was going on or I wanted to understand how something worked, I had the time
to go and explore it. And, you know, within a year or something, I discovered the mailing lists.
And then, you know, before long, I was actually active in email threads and, you know, I started
getting involved with the import system. And by 2012, so this is over the course of a few years,
I got commit rights and was pretty heavily active in core development.
That's so cool. I think there's something special for working for a small company. You get to touch a
lot of different things. You get this freedom that you're talking about to kind of solve the problems
the way you see they should be solved and then go and, you know, kind of explore. Right. I work for a
small company and I think I really attribute like being in that company in the early days to like a lot
of the success of my career because it gave me a chance to like round out the corners that I didn't
really know. I wasn't like just pigeonholed into like some super narrow role. Right. You work on what
this button does. That's your job. Like, right. Right. Right. Exactly. That reminds me what you
just said. That's been my experience with CPython that as I've gotten involved in the mail list and
the bug tracker and everything, I feel like is really rounded me out a lot because I'm exposed to
so many things, you know, the breadth of programming and just 90% of it, I probably never really would have
been introduced to because probably isn't that interesting to me, but because, you know, their
email threads and whatever, you know, I learned about it and that's, it's really made a huge
difference for me, I think. Yeah. I can imagine. It's just, it's an amazing group of people working
on there and then get down into the technical details. Oh yeah. So you started out and in this
web hosting company and now you work for a really big web hosting company, right? Yeah.
With Azure? Oh yeah. No, not exactly. But definitely, definitely I got some web hosting
going on. What do you do day to day over at Microsoft? So I work with Brett Cannon on the
Python extension for VS Code. I joined the team a little over a year and a half ago.
Nice. That's got to be a fun team to work on. You know, the excitement around VS Code is massive,
right? It's, you know, I always ask this question, what's your favorite editor? What editor do you use?
Things like that in the show. And yeah, VS Code is definitely tracking as a major thing. And
it used to sometimes be Sublime or Atom or something. It's, it seems like certainly for like that type
of interface, what would you call it? So what would you call it? I mean, it's, it's not an IDE
really. It's not like a terminal app. What, what category of editor is our Sublime Atom VS Code?
What's the name? What should I be calling these things?
I don't know why. Like a full featured editor?
Yeah, exactly.
You can't call it an IDE because that's, that's verboten.
Yeah. And there's not enough buttons. It needs more buttons and windows, right?
It needs more menus and more stuff so you can get lost in there, right? Right now.
Yes, exactly.
It's too easy not to get lost.
Yeah. There's not enough floating windows. Congratulations. I'm sure that's a super
exciting thing to be working on and it's, it's really growing quickly.
No, it's funny. This is a team that I first talked with them about getting on the team
in 2014 and it almost happened. And then there were some complications because I was only going
to work remote. At the time I was working for Canonical who makes Ubuntu. So I ended up just
kind of waiting and it took like what, two, three years or something like that. But it worked
out in the end. But that's, it's kind of a story of my life. I just kind of find a good
thing and then wait for it to work out. I'm not, I'm never really in a big hurry, which,
which I suppose we'll talk about relative to the stuff I've been working on.
Yeah, absolutely. So, well, that's, that's really good. And that's, that's a great project
to be working on day to day. And you said that Microsoft actually gives you a decent amount
of time to focus on CPython as well.
Yep.
As they do with Brett and some other folks. And that's, that's really quite, quite cool.
Yeah. I get to work basically my Fridays. I work on exclusively on Python. So that's been
a big boost to, to what I've been able to get done.
That's awesome. So you're saying the fact that we scheduled this on Friday is actually
cutting in your time to make Python better for everyone.
You know, it's actually part of why I just, yeah, no, it's cool.
That's the cost.
Yeah. But I think awareness of what you're doing is really good because I think it can make a
big difference. So let's just talk about parallelism and concurrency and asynchronous
programming and stuff kind of in general and in the, in the Python space. I feel like there's a lot
of people who look at what Python does with async. They see things like the GIL and they say, well,
this just doesn't work for parallelism. I'm switching to go or some, you know, some,
something like that. And I feel like it's, you know, there may be situations where you got to
switch to see you, you got to switch to go, but they're like 1% of the situations where people
actually do that. Right. Like most of the time, I think that's just not taking advantage of what's
out there. So maybe like, let's just set the stage with talking about like concurrency in general.
Yeah, you bet. If you look at it, the history of computing, other than really large systems,
most computers have been single processor, single core until relatively recently.
Yeah. Like 2005 or so, it just used to be the clock speed went up and up and up.
And that was how computers got faster.
So it's kind of funny because threading, sure, you can kind of logically program for different threads,
but ultimately it was just a single thread getting switched by the OS. And that's kind of the,
what you had to deal with, but it's a different story now.
Yeah. And back in the early days, you didn't even have preemptive multi-threading.
Oh yeah. Cooperative multi-threading, like you had to like give it up. Right. It was like in
Windows 3.1 in the early days, there was some weird stuff where like you had to be a good citizen on
the operating system to even allow that. We're kind of full circle here with async.
Yeah. Async it away is exactly the same thing.
Yeah. So it's kind of a conceptually the same. So it's really interesting, but now not only do we
have concurrency where you have to deal with matters of who's running at a given time, but now we also
have parallelism, which gives us performance boosts. But of course with Python, it's an issue with the
GIL, which everyone likes to complain about.
Right. Exactly. So within a single process, you can't really, unless you are doing certain operations
that release the GIL, you can't really run more than one interpreter instruction at the same time.
Right. Right. It's really a CPU bound code that suffers.
Right. Yeah, exactly. So if you're talking to like databases or you're waiting on web services,
all that stuff's fine, right? Like CPython interpreter, once it opens a network socket down
the C level, like while it's waiting, we'll release the GIL. And you can do those kinds of things in
parallel with threads already. Right. Yeah.
Not computationally. Yeah. It's kind of funny because if you look at it and I think Guido's
mantra has always been, well, you aren't really hurt by the GIL as much as you think you are,
because a lot of code that we write really isn't CPU bound. Very often it's not. And especially
for some of the CPU bound stuff, you know, a lot of the critical stuff, people have moved into C
extensions anyway. There's still a set of problems that are affected by the GIL. And people have had
to work around that number of solutions. You know, asyncio is kind of one thing,
but you also have multiprocessing and you have, you know, all sorts of distributed frameworks.
Right. Like Dask and other types of things. Yeah.
So all that stuff is in part, well, for distribute, it's a little different, but
part of the motivation there has just been to leverage parallelism better. So that's one of the
biggest complaints that people have with Python. It has been for a while, just parallelism,
multicore. And it's a bigger problem now that multiple cores are essentially ubiquitous.
Right. Even here on my MacBook, if I go and ask it how many processors it has, how many cores rather,
it says it has six and each of those are hyper-threaded. So as far as the OS is concerned,
I effectively have like 12.
Yeah.
And yet it's super difficult to take advantage of those.
Yeah. Yeah.
In Python.
Yeah. Yeah. It's just, it's really interesting. So it's funny the way things have gone and it's,
it's going to go even more, more this way. I mean, I expect that the way people program
will be different as we think about multiple cores more, but maybe not. I mean, because how often are
we writing, you know, CPU bound code?
I feel like there's just a couple of situations where it really matters and there are already to
some degree, some escape hatches, right? So the most obvious place where in Python,
it really matters for computational parallelism is in data science, right? Like I've got a billion of
these things. I want to run some crazy algorithm on it and like machine learning training or whatever.
But a lot of the libraries that the machine learning folks already have, have some capability
for, or for data science folks have, have some capability for parallelism at their lower C levels
anyway, right?
Yep. That's exactly right. I mean, a lot of these libraries have C extensions where they need them.
Exactly. The other place where I feel like you really could get a lot better support is on the web.
Yeah.
Right. Like we have some of the newer frameworks, we have Molten and Jepronto and Starlette and all these things,
Responder that let us write async def, some web method and truly leverage the asyncio components there.
But, you know, the main ones, Flask, Django, others, Pyramid, whatever, they don't, right?
They're all WSGI based and it's, you just can run into issues, right?
I mean, I know the web servers themselves have some capability just to parallelize it out, but it's still, it's, it would be much easier if you did.
So I don't think it's that big of a problem.
Like there's these two areas, the data science space, and I think the sort of like high-end web serving space that could be handled a little bit better.
Yeah.
We're already seeing some stuff with async and away on the web, which is, I think, where it's appropriate.
I think there's one important caveat too, and it's something that we, we don't really bring up a whole lot in the community, which is that there are a lot of enterprise users of Python that we never hear about how they're using it.
In part because of, you know, competitive advantage and that sort of thing, but we don't really hear about it.
Yeah.
Or they just, they just don't go to the conferences and they don't like spend all their time on Twitter.
They just see it as a job.
They do their work.
They go home.
Like they don't, not also their hobby necessarily.
Yeah.
So in a lot of those cases, performance matters and not just performance, of course, efficiency and, and that sort of thing.
I mean, it really adds up.
So I'm sure there are a lot of folks that we don't even think about who would benefit from better multi-core support in CPython.
But, you know, we just, we don't hear about those folks.
Well, maybe that's not even them directly.
Right.
Yeah.
Maybe they, they pip install a thing and that thing now works better and they don't even know that it's using multi-core support.
Right.
But somebody who's really clever found a way to make something they were doing much, much better using that.
Right.
This work that you're approaching basically tries to deal with this limited,
implementation of the Python's guild, the global interpreter lock, which basically has the effect of what I said before, that only a single interpreter instruction can run at a time.
Maybe some low level C stuff can also happen, but like the stuff that you write runs, you know, only one like bytecode instruction at a time, basically.
Yeah.
So maybe just tell people like, that sounds bad.
But it's here for a reason, right?
It solves a lot of problems for us, right?
Oh yeah.
It hides a lot of problems that you face when dealing with threads that you don't have to worry about in Python.
But not only that, it's also when you're writing C extensions.
In C, you have to do a lot of stuff yourself.
And when you're dealing with threads, you have to deal with all that.
So when you're using Python and you're holding the GIL, you don't have to worry about other Python threads.
You don't have to manage your own locks for those threads, which is, I think, makes a threading at the C level in the C API easier.
But also, there's a lot of implementation details in CPython that depend on the fact that the GIL protects them.
We deal with re-entrancy a lot.
But other than that, we don't really have to worry about race conditions on any of the C types, the built-in types or any of those, because they're protected by the GIL.
Yeah, which is great.
And the GIL is largely a memory management thing.
It's not initial job.
I mean, it is for threading, but it's mostly to protect the memory management and making that thread safe, right?
In large part, it's to protect the runtime state, especially memory management.
Yeah.
So it serves this important role.
I mean, we still do have R-lock and things like that, because we might write algorithms that a whole bunch of different steps can't be interrupted, temporarily invalid state or whatever.
So we might have to think.
But it's very rare, actually, that you end up doing locks and stuff.
And other languages like C++ or C# or something, it's common to do locking all over the place, right?
For all kinds of funky things.
So it's nice that it's not there.
And there have been several attempts to take it out to switch to other types of memory management, other things that let us avoid it.
But it's always had these problems of making the C extensions not working well or breaking them, of actually making the single threaded case slower.
It's one thing to say, okay, we could switch to some other system that's not using the GIL, but now your code's 1.5 times slower.
Unless you send like six cores on it, then now it's faster, sort of, sometimes.
Like, that's not a great solution either, is it?
One of the key things that we protect with the GIL is ref counts.
Because we use ref counting for our, essentially for memory management, then we have to keep those ref counts safe from race conditions.
So we would have to do locking around all ref count operations, and that would get really expensive real fast.
Right, exactly.
There have been other projects in the past.
Several people have tried to get rid of the GIL, including most recently Larry Hastings with the Gilectomy.
And each time it comes down to having to add a lot of locks or similar mechanisms to protect those global resources.
And those things kind of fall apart and cause performance issues that ultimately kind of kill the goals of the project.
Right, or break the C APIs.
Yeah, yeah.
If you're looking for performance and you're like, well, we made the Python bit 1.5 times faster, but the C parse doesn't work.
Like, all of a sudden, it's much slower, right?
Like, that's a problem.
If we were able to just break the C API, or even get rid of it and use something else, then we'd be able to solve this problem, I think, without a lot of trouble.
But because people in C extensions rely on a lot of these details, we just can't get rid of them that easily.
There has been recognition of this kind of in the core team in the last few years,
and a recognition that we really got to figure out how to solve this.
So I'm hopeful that we're going to figure this out.
There have been a lot of smart people thinking about this and a lot of good ideas over the last year or two.
There are some things that will have to break, but I think we'll be able to sort it out.
That's good.
Let's talk about the proposal that you've been working on, PEP 554, which has this concept of a sub-interpreter.
And when I heard about this, I thought, wow, okay, this is like some creation that's going to be like this new thing that allows for isolation so you can effectively mimic what you're doing with sub-processing or multi-processing,
but without actually the overhead of processes and the inter-process communication.
I'm like, okay, this is great.
But then as I looked into it, this is not a new idea at the very core of it, right?
No.
But it's just not something anybody's leveraged.
Tell us about it.
It's interesting.
It really is.
Nick Coghlan kind of expressed it as the isolation of processes with the efficiency of threads.
And it's not a pure explanation, but it's pretty close.
Sub-interpreters have been around as part of Python.
Originally, CPython was just implemented as kind of a blob of state, and there was an effort to kind of bring a little sanity to that
and isolate all of the state related to Python threads in one C struct and interpreters, which can have multiple threads, in another C struct.
And then there's run type state still all over the place.
That's just global.
So at that point, that was, I don't know, 20, 21, 22 years ago, something like that.
And at that time, C API was added for creating and destroying sub-interpreters.
And the threading API is built around sub-interpreters to an extent.
But it's funny because, like you said, it's not a new thing.
And yet, a lot of core developers didn't even know about sub-interpreters.
Very few users knew about it.
I knew of only one project that was actually using sub-interpreters meaningfully up until four or five years ago.
And that was Mod Whiskey, Graham Dumbledon.
And it's funny because sub-interpreters now, there's more awareness and people are starting to use them more, and some big projects including.
And at the same time, a lot of old users, so Graham, and I've since heard from a few people that use sub-interpreters internally for a long time.
Now that we're fixing all the problems with them, they're actually moving off of sub-interpreters because they gave up.
It's like, no, just wait another year.
We'll probably have a lot of this stuff.
Yeah.
And you can benefit from performance improvements that we're doing.
So it's really funny.
A lot of people just didn't know about it.
And the people who did didn't really think about it all that much.
But it's funny, as C-Python progressed, things would get added in, and they would affect sub-interpreters, but nobody would realize it.
There wasn't good tests of sub-interpreters.
There weren't many users, so nobody would report problems.
Poor Graham, he'd report things, and nobody would really pick up the bugs and work on them.
Well, this guy's crazy.
What's he talking about, this weird sub-interpreter?
Yeah.
Is that even a thing?
Exactly.
There are a number of problems.
In my opinion, it never really was quite finished, because they're not as isolated as they probably should be.
And there are a number of other rough corners, bugs, and stuff.
So what's interesting is the stuff I'm doing, one consequence is that those things have to get fixed.
Yeah.
So the idea is to lift this concept of a sub-interpreter up out of the C layer, create a standard library module called interpreters, that allows you to program against this concept of the sub-interpreter.
Correct.
So it's definitely, I'm doing this with isolation in mind.
You know, at first, the proposal was just wrap the C-API in Python in a C extension and call it good.
Because it's there, right?
And somebody early, early on pointed out, well, if you can't share stuff between sub-interpreters, all you can do is just start one up.
It's not really nearly as useful.
In C, you just do the C thing, you know, pass stuff around however you want and shoot yourself in the foot if you want.
Here's a bunch of pointers.
Uh-huh.
You can talk to them all you want.
Exactly.
Make sure you don't talk to them at the same time.
Don't hurt yourself.
Yeah, exactly.
But in Python, you know, we don't have the opportunity, which is, I think, a good thing here.
So they're like, yeah, well, it's not nearly as useful as it would be if you had just at least some basic way of sharing data between them.
So I was like, oh, yeah, that's a good point.
And so really got me thinking about sub-interpreters more than just as a tool to achieve other goals, which I expect we'll talk about, but also as actually a vehicle to a concurrency model that I think fits the human brain better, at least in my opinion.
I'm not a big fan of async.
I'm sure it's great.
Some people really get it.
For me, it's just, it's, I don't like it.
Yeah.
But, you know, that's fine.
I think there are other ways of thinking about concurrency that work a lot better.
Things have been studied since the 60s.
Right.
Message passing and some of these types of concepts where you're more explicitly like, I'm going to send this over to the thread and the thread's going to pick it up and work on it or things like this, right?
Yeah, yeah.
Before I moved to Microsoft, I was at Canonical for three years working on various projects written in Go.
And Go has a concurrency model that's, I would say, loosely based on CSP, which is kind of a concurrency model that was researched and developed since the 60s, especially by a guy named Tony Hoare from over in the UK.
Really powerful stuff.
And, you know, it has a lot of similar roots with like the actor model.
Yeah, exactly.
Go is one of these languages that very explicitly controls how concurrency works.
And it's part of the language that this data sharing and whatnot happens, right?
I don't think it's great what they did because they took CSP and then they broke some of the fundamental ideas behind it, like isolation in these processes, right?
I mean, CSP is communicating sequential processes.
So the idea is that you have a process that is just, it's like a single threaded program, right?
You could break it down into just a linear flow of code, no matter what, deterministically.
And then you have a mechanism by which these processes can communicate.
Basically, just send messages back and forth.
And they block at those points.
I'm going to send a message and wait for the other process to pick it up.
And then at that point, both processes will move on.
So I spent a while trying to figure out really what would be the best way to set up rudimentary communication between subinterpreters.
And my experience with Go came about, so I don't know if I just said this, but Go routines, which are kind of the idea of these processes in Go, they're not isolated.
So you can share data between them.
So basically invalidates a lot of the ideas behind CSP.
I mean, it's interesting.
So I want to take advantage of the isolation between subinterpreters.
And so essentially, you end up with kind of opt-in data sharing or opt-in concurrency.
You don't have to worry about races and stuff like that.
It's very much kind of like what the multiprocessing communication flow is, right?
I'm giving this data over to this other process, and then they can just have it and they own it and don't have to worry about it.
Or they get a copy of it or something like that.
So I looked for a lot of prior art that kind of followed this model.
And the stuff in multiprocessing was one.
The queue module has a lot of stuff that's kind of a similar idea.
And there are a few other things out there.
And of course, in other languages, I really stuck with this idea of following the model of CSP as much as I could.
And really, while the proposal isn't like some CSP implementation, the whole thing is kind of with CSP in mind.
Okay, could I build like a nice CSP library on top of this?
Right.
Because like you said, without the communication, like you said, it's like, it's kind of interesting, but it's just like a task spawning type of thing.
Right.
Like it's not really any sort of cooperation.
This portion of Talk Python to me is brought to you by TopTal.
Are you looking to hire a developer to work on your latest project?
Do you need some help rounding out that app you just can't seem to get finished?
Maybe you're even looking to do a little consulting work yourself.
You should give TopTal a try.
Maybe you've heard we launched some mobile apps for our courses over on iOS and Android.
I use TopTal to hire a solid developer at a fair rate to help create those mobile apps.
It was a great experience and I can totally recommend working with them.
I met with a specialist who helped figure out my goals and technical skills required.
Then they did all the work to find the right person.
I had a short interview with two folks and hired the second one.
Then we released the apps just two months later.
I think what we ended up with, which is channels, really basic, but I wanted to keep the PEP as
minimal as possible.
And I think it really, I came up with a good solution for this.
So one of the tricks though, is that because of the isolation, you can't just share objects
between sub interpreters.
I mean, currently you can at the C layer.
But in the Python, I didn't want to give anybody ever the opportunity to share objects, at least
not at first.
Maybe we can come up with some clever solutions for that.
But currently you can't.
So, I mean, there's really a limit to what can be shared between sub interpreters as proposed.
And I want to keep it as minimal as possible so we can build from there.
Yeah, absolutely.
Well, one of the really exciting parts of that is one thing that is not shared between sub
interpreters is the global interpreter lock, right?
Well, currently it is.
That's the problem.
So right now, sub interpreters do share the gil.
So one of the things I'm working on is kind of the bigger problem.
And really, I'm trying to tackle this problem of supporting multi-core parallelism in CPython
using sub interpreters.
So kind of PEP 554 is just a vehicle to make sub interpreters accessible to Python users.
But really, the actual goal is to fix sub interpreters, including to stop sharing the gil between sub interpreters, which is kind of crazy.
That is crazy.
But at that point, then you can say start five threads.
Each thread starts a sub interpreter as its startup process.
And then all of a sudden, the gil is no longer a problem.
Precisely.
Potentially.
And because you're not sharing the objects, right?
You don't have to worry about that.
And now you have these channels where you can pass data back and forth in a thread-safe way.
That's super cool.
It sounds like sub interpreters as they exist don't do that.
But that's kind of the ultimate goal.
Yeah, yeah.
Create this exposure of the API to actually create sub interpreters.
Move the gil down so it's one per sub interpreter.
And then a way to communicate between them.
So that's the Harrier problem, right?
Is the gil.
What we have is, like I said earlier, we have a whole bunch of runtime state all over the place.
So one of the things I did a couple of years ago for this project, there are a bunch of things that we've done.
Big things that probably nobody even notices because they're all internal.
But one of the things I did was I took all the global state I could find and I pulled it all into one single C struct.
So what's neat about this project, the ultimate goal of not sharing the gil between sub interpreters
is that it requires just a ton of other things.
I think I list out 80 different tasks that are probably not even super fine grained that have to get done in order to make this work.
And probably 70, 75 of those are things that are a good idea regardless of the outcome of my ultimate goal.
Right?
Right.
See, Python is going to be cleaner.
Uh-huh.
If we get to those 75 things and then we're like, oh, it's not going to work.
Well, that's okay because, dang, you know, we got some good stuff done anyway.
Stuff that we wouldn't have done because we weren't really that motivated.
I mean, this is open source.
So I have a motivation and other people share some of the motivations.
It's really neat.
There's a lot of collaboration going on now because not just for the whole sub interpreter thing.
Some of the stuff that I need is stuff that other people need for different reasons.
And it's working out pretty well.
But the whole thing is I took all this state and smashed it into a single struct.
And as kind of a side effect, I just want to make sure I didn't hurt performance by doing that.
So I ran Python's performance suite and it turned out that I was getting a 5% improvement in performance.
Interesting.
Do you know why?
It's crazy.
Well, I expect it's because of cache locality of that struct.
That was my first guess as well, right?
As you load one element of that struct, everything drags along onto L2 cache or the local cache.
And it's just a little quicker, right?
You just accidentally do fewer deep memory lookups.
Somebody pointed out to me that it probably doesn't have quite the same effect on performance for a PGO build.
Where the compiler can optimize the layout of memory and various other things relative to what's hottest in the code, right?
Yeah.
So it kind of runs the thing through a workload and determines what's the hottest chunks of memory and pushes those together.
So you get those same cache locality benefits.
So ultimately under a PGO build, probably not the same performance benefits.
But I only bring that up because...
PGO performance guided optimization.
Yes.
Thank you.
For everyone out there.
Yeah.
Acronyms.
Yeah.
So maybe it's not as big necessarily.
Is that theoretical or is that something that is actually done on CPython builds?
Yeah, yeah, yeah.
People do it.
If the one that I brew install, is that one?
PGO?
I don't know.
Optimize?
Okay.
Yeah.
You get some real benefits from a PGO build.
There are lots of these little things.
One of the things I needed to happen was there was some work that Nick Coughlin started like four or five years ago to clean up runtime startup.
And I needed that because otherwise there were certain things I just couldn't do.
So I was blocked on that.
So finally, I got around to taking the branch that he had, which is on subversion, and moving it over to Git and then at the same revision.
And then I had to rebase it against master and fix all the conflicts and finally got that merge like two years ago.
And that was a big thing.
And then because of that, we're able to do a lot of really good things with startup that we weren't able to before.
So that's a side effect.
And there are all these things that are just good.
That was one of the larger goals of Python 3 as well is try to like fix the just the cold startup times, right?
No.
One of the goals that we have is to fix startup times so they're at least on par with Python 2, which they weren't.
Yeah, that's what I was thinking.
Weren't nearly at first.
That's what I was thinking.
Yeah.
So we're mostly on par now.
The biggest problem was all the codecs and Unicode stuff.
That really hits startup performance.
So if you think about subinterpreters, if you start up a new subinterpreter, it has to build all this state.
It has to load all these modules.
There's a ton of stuff that has to happen, right?
So you're going to incur that cost for each subinterpreter.
As a consequence of what I'm working on, I want to make sure that startup time is as small as possible.
So it's definitely one of the things, maybe not one of the immediate concerns, but kind of one of the relatively low-hanging fruit for this project once I finish this first phase is to go in and do things like make interpreter startup more efficient, whether it's sharing or whatever.
And those are things that are a good idea regardless of use of subinterpreters.
I mean, just for the main interpreter, getting startup faster is a good idea.
And that's something that I want for subinterpreters.
And I'm motivated to do it.
And I think other people, once subinterpreters get in widespread use, people are going to be like, oh, yeah, this is great.
And people are going to be motivated to fix some of these deficiencies in subinterpreters.
Yeah, absolutely.
And it'll definitely, as it's a little bit of a catch-22, right?
You said it wasn't even hardly quite finished because here's this idea.
But at the same time, if no one's really using it, why do you care about fixing this thing?
And if no one's fixing it, I'm not going to use it because it doesn't quite work.
And then here you are in this lock, right?
So it reaches a point where, well, for me, it was in 2014.
I was having a conversation with somebody at work.
And they were saying, yeah, Python's going to die because it doesn't do multicore because of the GIL.
And it was just, I don't know, one of those moments, you know, when something hits you so deep, you know, they dig a little too hard.
And you're like, okay, fine.
Forget you.
I'm going to fix this.
And I'm never going to hear anybody complain about the GIL again.
Yeah.
Yeah, absolutely.
That's what this project is.
That's what I've been working on for several years now.
It's basically just to get people to stop complaining about the GIL.
I definitely think, you know, rightly or wrongly, it's one of the perceived deep limitations of Python.
Yeah.
I think wrongly, but I do think that it is perceived to be that like Python is not nearly, is barely appropriate for like parallel computing.
Yeah, yeah, yeah.
I don't think that's right, but I think that's the perception.
Yeah.
Outside of a lot of Python, or maybe within it.
I think it's a fair perception for a class of users.
And as a community, we like to be inclusive.
We don't want to leave anybody out.
We want to make sure that things work out for folks.
It's just being open source.
It's nothing's going to happen until somebody cares enough to do something about it.
And that happened for me.
That's awesome.
Yeah.
And so here we are.
Yeah.
So it sounds like around September 2017, you introduced PEP 554 to address this.
Probably you've been working prior to that.
2018, you talked about it at PyCon US at the Language Summit and whatnot.
And then also, again, in 2019.
And like those, also, it sounds like those experiences were a little bit different.
Do you want to maybe recount those for us and tell us how this is being perceived over time?
You bet.
I mean, I've gotten support from the core team.
I think my first post about all of this to the Python dev mailing list was probably 2016, early 2016, I think.
And, you know, and there was a lot of discussion about it.
And there were really only a handful of people that had any sort of opposition to it, any major concerns, which I took as kind of a valid litmus test on if it was worth pursuing.
Yeah.
And when you initially presented it, what was the scope?
Was the scope like the final end goal where there's like you're trying to use it for concurrency and all that?
That was like from the start.
Talking about using subinterpreters and not sharing the GIL to achieve these goals of multi-core parallelism.
So, you know, at some level to the details, pursuing kind of a CSP model, a standard library module.
And, you know, and the response was pretty good.
There was several long threads and I incorporate all the feedback into the PEP ultimately.
But, yeah, the feedback from the PEP was great.
And then come PyCon 2018, I basically asked everybody I talked to, explained subinterpreters and what I was working on and asked them what they thought of it, how they would use it.
And it seemed like everybody had a different response.
Everybody was excited about it, almost universally.
And everybody had a different response on how they would use it.
Most people, I didn't even have to ask them.
The big guy, go like, wow, I have the perfect use case for that.
This, this, this, this.
And I even at one point asked, oh, his name escapes me, the maintainer of Dask.
Matthew Rockland.
You're welcome.
I asked him about this.
He's like, wow, subinterpreters sound neat.
But I doubt I would incorporate, I would make use of them for Dask, except Dask internally has all these control threads and all this machinery built out.
For managing all of the distributed programming.
Just so people know, Dask is a way to run your Python code potentially on a bunch of different systems.
It's kind of like, like a Pandas data frame style programming.
But you say run this computation, but like all over the place.
That's the problem that Das solves.
And then.
So it's really interesting.
He said, but yeah, I would totally use that for my internal stuff.
I mean, for these control threads.
I mean, I would totally make use of that because it was, it's perfect.
Or, you know, talking to web folks and they're like a bunch of different use cases for how this apply to web frameworks.
Or basically everybody had ideas.
Yeah.
There's a ton of great ways.
Yeah.
It was really neat.
So I got excited and then come the sprints that year.
Oh, and one of the people that was really supportive was Davin Potts, who's one of the maintainers of multiprocessing.
Which is, you know, I thought that was a pretty good sign that I was in the right direction.
It is absolutely a good sign.
I mean, this is like the next gen multiprocessing in my mind, kind of.
I still wonder if once we have sub interpreters, do we even need multiprocessing?
Subprocesses make sense.
But does multiprocessing make sense?
I'm not sure.
I mean, it's kind of like the big hammer to solve the GIL problem and this isolation problem by just going fine, the operating system will do it.
But if CPython itself does it, then I mean, maybe there's a memory.
But it's interesting to think about.
Yeah.
What's funny is now after I'm charged up, I'm excited.
I've got all sorts of notes.
I'm like, wow, you know, there's all this stuff.
Several people have said that they'd like to help out.
You know, and then I get to the sprints and you can imagine that Guido's a busy guy at PyCon.
You know, everybody wants to talk to Guido, taking pictures.
He can't get even a moment piece.
I know it's, yeah, it's definitely got people chasing him around.
It wears him out.
And there's always stuff going on.
There are people that he needs to talk to about different proposals and whatever.
And this is 2018.
He's still BDFL.
And there's a lot going on.
And what happens?
He actually comes and finds me, sits me down.
And for 45 minutes, he basically tells me that he thinks it's a bad idea.
And I can tell you, I walked to, so I understood where he's coming from.
And I think in part, he had misunderstood what I was trying to do.
Yeah.
It's like that telephone game where one person tells a person who tells a person something and
it's not the same on the other side.
And in the conversation, you know, I tried to clarify a few points, but it really wasn't
a great opportunity to try and explain really why this was a good idea.
I mean, the PEP to an extent does, but I think there's kind of a gap in the justification that
really Guido was just, I hadn't communicated well to him.
So 45 minutes.
And basically, you know, I conceded some of the points that he made and tried to explain
the others.
And ultimately, you know, it's not like he said, stop.
He basically said he thought it was a waste of my time that I should work on something
that's going to benefit people more.
Also, he was coming from thinking about the problem in a different way than I was and a
different understanding of exactly what I was trying to solve and what I was trying, what
the proposal was, what the solution was.
Well, he probably also has a lot of Gil fatigue hearing how Gil is ruining Python and all that,
right?
Yeah.
And I think in part, he was just worried that I was going to get people excited about something
that wasn't going to actually end up happening.
Okay.
So it was kind of a bummer.
I was bummed out probably the rest of the day.
Did you walk away less inspired or are you still excited after all the other input you
got?
I was still determined.
Yeah.
I probably, my excitement level was lower only because it'd been suppressed a little, but
you know, that wears off.
And talking to more people about it, same level of excitement, the same excitement about how
they would use it.
And so, you know, I didn't worry about it, but I was worried that if I couldn't convince
Guido, then A, of course, I didn't think it would happen.
And B, maybe it really wasn't a good idea.
Because Guido is smart and he's been doing this a long time.
And I have absolute trust in that uncanny ability he has to understand whether something
is good for Python or not.
Yeah.
I mean, he's amazing.
So it did make me wonder, well, what if he's right?
Maybe I'm not understanding.
That's probably more likely.
So, but I kept at it.
I was determined.
You know, like I said, I waited three years for the job I have now.
So I was like, you know, I'll just keep going.
And if nothing else comes of it, I was convinced that 80 or 90% of stuff that I was doing was
a good idea regardless.
So I was like, I'll just keep going.
And if it ends up that it's not going to work out, I won't feel too bad about it.
I'll have made a difference, I think.
So kept going.
But then 2019 rolls around and Guido pulls me aside again and says, oh yeah, that's
a good idea.
Been thinking about it.
Because he got it.
Well, the point that we were fixing, he saw over the course of the year, he saw that I was
working on all these things that I needed for the goal, but they were a good idea regardless.
And he's like, oh yeah, you're working on all this stuff.
And also, he probably heard my explanation a few more times and it clicked on how I was trying
to solve this problem.
And he said, yeah, that could work.
And so I was floating around for a while.
It was exciting.
That's super cool.
One of the challenges a lot of peps and projects have had recently, let's say since July 2018,
maybe, is we, more like you guys, have not really had a way to decide to make decisions
after Guido said, I'm stepping down, I'm just stepping back to standard core developer or
steering council now, but stepping back saying, you guys have to figure out a new way to like
make decisions and sort of govern yourself.
Right?
So that, your PEP spanned that gap.
So I'm sure that didn't.
Oh man, it was brutal.
Was it?
It literally killed a lot of the momentum I had coming out of PyCon 2018 because that happened
just a couple months after.
And basically, I kept working on stuff, but there was all these discussions about governance
and governance and governance, and it just dominated a lot of what we were working on.
So there wasn't a lot of collaboration going on with this project.
And there was a lot of just cognitive effort to stay on top of this stuff because it's important.
So really, until all this was solved, pep554 was ready.
Basically, right after PyCon, I was 2018, I'd worked up kind of a separate list of arguments
to make to Guido on why this was a good idea and try and kind of fill that gap that I had
perceived.
And then on top of that, I had updated the PEP to kind of iron out some of the small things.
I felt like it was ready.
And literally, right before I was going to ask for pronouncement on the pep, then, or no,
I think I was going to wait until the core sprints in September so that I could talk to
Guido in person and try and make the case and then ask for pronouncement.
So, you know, this was, it was brutal because then no peps got decided.
And the core sprint was mostly spent talking about governance stuff, which that's fine.
It was productive, but I wasn't able to get a lot of progress.
So it just kind of slowed things down so much.
And then when we finally got governance ironed out, you know, there's transition.
So this whole time I was honestly aiming to solve it, to get PEP 554 landed for three, eight,
and then even get the, the stop sharing the GIL stuff done for three, eight.
Neither one happened in large part because of the whole governance issue.
It's probably good in the longterm that this transition happened, but in the short term,
it definitely threw a bunch of molasses in, you know,
it's a little disappointed every release you miss on something.
It's a little part of you hurts, but.
I can imagine.
Well, and the releases are long, like the gaps are wide between them, right?
18 months is a long time in technology.
It's not like, well, maybe next month it'll come out.
We're actually talking about reducing the release cycle to a lot smaller, six or 12 months.
Depending.
I think that's interesting.
What's the trade-off there?
So our currently released manager, Rukash, he, he said for three, nine, I want it to be shorter.
So he basically said there are a variety of reasons.
The main opposition to having shorter release cycles was that it's more of a burden on the release team,
but that's less of an issue.
Now there's a lot more automation.
And so this is coming from the release manager.
So he was in a position to determine what made sense.
So that's, that's kind of how that's played out.
He's, he's like, let's do this.
And so there was some discussion for a stretch on what would be the best time.
And if it made sense at all, of course, but if we went with it, you know,
what kind of release interval we'd have and how that would work logistically and how that would play into other factors of core development.
So I, I don't remember where that's gotten to.
I think there was some consensus that it would make sense to look at it further, but I think like most long discussions do, it kind of tailed off without a good conclusion quite yet.
I don't know.
I don't remember.
It's, I don't remember what the PEP number is.
It's the, the release PEP for three, nine is where he started this discussion.
So there's a number of threads related to that PEP.
You know, to me, it sounds generally positive, right?
Like smaller releases that you can understand a little bit more completely rather than just like, here's a huge dump of 18 months of work.
But I definitely do understand it.
I mean, you've got all the places, all the Linux distributions, all the other places that are shipping it.
They have to now think probably about that more frequently.
That was definitely one of the concerns.
But now that the Linux distributions are moving away from exposing their system Python, that it's less of a concern.
Right.
So one interesting thing in this discussion was just the idea of moving to Calver for versioning Python.
I think that was something that Brett had talked about.
So, you know, there are a number of different ideas.
Like actually having the version number be like 2019.6 for June or something like that.
Yeah.
So then you'd end up with 2019.6.0.1, you know, for bug fixes and all that.
Definitely.
I like the calendar versioning for like packages and stuff.
But for the actual core, like that's pretty interesting.
I don't know.
It may not make sense.
There are a lot of things that people talked about.
We talked about the possibility of LTS releases or some variation on that.
And so that we'd be maintaining multiple.
But, you know, I think a lot of people are kind of burnt out on having maintained 2.7 and Python 3.
At this point, like, have we just about gotten out of this?
Most people don't bother with 2.7 at this point, core developers.
So it's really interesting.
I don't know.
There are lots of ideas.
I think ultimately we'll settle on the right thing.
Something that'll work well for us.
Even if it's a status quo, if we figure out that's the best way forward.
But we've already since 3.6, I think it was, we started doing a shorter release cycle, more like 14 months.
Because we used to do release cycle from release to release.
But now we do, or from final to final.
Now we do, if you think about it, it's more like final to beta 1.
Right.
Which we're already like way past 3.8 beta 1.
The final release date for the next version is basically 18 months from beta 1 now instead of final.
That's the way we've been doing the last few releases.
So it breaks it, shortens it to like 14 months.
So 12 months really wouldn't be that different.
Yeah, that's true.
We'll see what happens there.
But, you know, interesting topic.
For sure.
So the final takeaway is you're targeting Python 3.9, which will be basically where the work is going into now, right?
Like you're already in beta of 3.8.
It's kind of frozen and whatnot.
So it's going to be probably the next version of Python.
Maybe that will be shorter.
Maybe not.
A little undetermined at this point.
Might be 12 months from now or who knows.
I expect, regardless of when it is, that we're close enough that we'll be able to get all of this sub-interpreter stuff done for that.
Assuming PEP55R gets accepted, which I expect.
I hope it does.
I expect it will.
I don't see a reason why it wouldn't.
Yeah, it seems like the excitement is there for it.
To me, it clearly solves the problem, assuming like the startup time of the sub-interpreters is not just equal to multiprocessing and things like that.
It seems like it's going to be really great.
Yeah, and what's nice is I've done this in a way that will start really minimal.
Like you'll only be able to pass bytes or strings or other basic immutable types between sub-interpreters.
But with this foundation, then there's like a whole list of really neat projects that people can work on to improve things for sub-interpreters.
Like I talked about earlier, improving startup time, but also things like one neat idea is the idea of for memory allocators in CPython.
Right now, we use one memory allocator throughout the whole lifetime of the runtime.
Memory allocator is in charge of, of course, allocating and deallocating memory.
So what if you could use a different memory allocator per interpreter?
Well, what if you could at any arbitrary time swap out an allocator so that objects are allocated using different allocators?
Then you could manage relative to the allocators for those objects and you get some neat things.
Like what if you had an allocator that was page size, right?
And so then you actually can, in Python, have a class that kind of wraps that allocator so that you can create objects relative to that class.
Or create an object that represents allocator and then any attribute that you create on the object is in that allocator or whatever.
So now you have this self-contained memory page that then you could mark, let's say, read-only.
Suddenly, all that memory is read-only and you have truly read-only objects in Python.
What if you take that read-only and now you can pass that whole memory page over to another interpreter and you don't have to worry about any race conditions relative to that memory page?
One of the best ways to get parallelism is to have immutability.
I think there are lots of...
And so there's a...
I have a project open for this and a number of other resources where I've basically written all this stuff down.
Like, here's a whole list of awesome things that we can do once we have this foundation set.
Would you get things like maybe less memory fragmentation for long-running processes?
If you could start up these sub-interpreters, like give them a block of memory, let them throw that away.
And like things like this, like other benefits, possible memory leaks for like badly written code, but like it was all within a sub-interpreter.
There are a number of things there.
One is that I have a list of...
Like I said, there's all this global state all over.
This is kind of the main blocker for me right now.
And so we have all these static globals in the C code all over the place, thousands of them.
Most of them can't be global.
So I can't even pull them into the runtime state struct.
I have to pull them down into the interpreter state, which means I have to collect them out of static globals and kind of migrate them into this pi interpreter state struct.
And it's just a lot of work.
And then I have to make sure that nobody adds any static globals that they shouldn't in the future.
Or else, same problem all over again.
So, I mean, this is probably the main problem right now.
Aside from all those globals, there are some parts of the pi runtime state, which is this struct where I pulled in a lot of globals earlier, a couple years ago.
There are key items of that struct that I've identified that need to move over into the interpreter state.
The gil will be the last one of those.
But right before that is memory allocators.
So I'm pretty sure that we'll be able to do this just fine.
But I need to see how it affects performance.
But moving the memory allocators to per interpreter.
So I think one of the side effects, I mean, it really could be reducing memory fragmentation down, you know, isolating it to per interpreter.
Which, if you're using multiple interpreters, that's a good thing.
Yeah, it's really interesting.
And certainly the pressure that hardware is putting on top of programming languages and runtimes is not getting less, right?
Like, we're only going to have more cores, not fewer going forward.
So it's only going to be a problem that stands out more starkly if Python only reasonable runs on like one core at a time.
When you have 16, 32, 64 cores, whatever it is in like five years, right?
Yep.
So it's definitely a good project.
I'm really excited about it still after first motivated to work on this and five years ago.
You know, I'm still motivated.
Almost gave up at one point.
But plugging away.
And now a lot of people are excited.
Looks like it's really going to happen for 3.9.
Are some of the other core developers helping you?
Somewhat.
Everybody's got different goals in mind.
Victor Stinners, he's been really helpful for some of this stuff, especially relative to the CPI.
I've had offers of help from others.
Before Emily Morehouse became a committer, I was helping to mentor her.
And one of the things that we did, we met basically weekly.
And for the most part, we paired up on working on sub-interpreters.
And that was a big help.
Now she's...
Yeah, that's cool.
She's all important now.
No, no.
Emily's great.
But she's so busy.
Yeah, she's great.
She's running a successful company.
It's really busy.
And on top of that, she's the chair for PyCon 2020 and 2021.
Well, I'm guessing 2021.
Anyway, at least next year.
And then she's got a lot of this stuff going on.
And she did the assignment expression implementation.
And all sorts of stuff.
But during that time when she was helping out with this stuff, it was a really big help.
So lots of help.
I had help from a number of folks out in enterprise.
Talked to folks at Facebook and Instagram and some other companies.
I've had offers to help from other individuals.
Help from small companies.
People coming up and saying, hey, I want to get my whole team working on this.
It hasn't really gone anywhere.
I don't get my hopes up too high.
Yeah, it's such a big problem, right?
It's like so wide spanning.
It sounds like with all the globals and whatnot.
You got to really...
It's not very focused.
So it's hard to work on, I suspect.
One thing I made sure to do was break this problem down into zillion tasks.
As granular as I could.
So I think I gave you the link there to the multi-core Python project that I have.
If you look me up on GitHub, you'll find that repo.
And that repo is basically just a wiki and GitHub projects breaking down all this work into discrete chunks.
I'll certainly link to all those things in the show notes.
So we'll just click on it.
But yeah, that's great.
Link to your...
You gave a talk at PyCon 2019.
I don't think we mentioned that yet.
Yeah.
So it was a talk.
I actually proposed two talks.
One of them was specifically about subinterpreters and both PEPF5-4 and the whole effort to move GIL to per interpreter.
That got rejected.
That was the one I wanted to give.
I gave another one that's broader.
It was kind of a superset.
It included the stuff from the other talk, but it also talked about all about the GIL in general.
The history of the GIL, what really, you know, the technical ideas behind the GIL, really race conditions and parallelism, concurrency and all that stuff.
And then also talked about what we need to do to kind of solve that problem, including talked about some of the past efforts and also current efforts to make fixes in the CPI, changes in CPI so that we can move past the GIL.
And then I focus a lot of the talk on the stuff with subinterpreters.
Cool.
Yeah, that sounds really interesting.
We'll definitely link to that.
All right, Eric, I think we're just about out of time.
We'll definitely cover this.
And I'm really excited for this project.
So if you need any more positive vibes and feedback, I think this definitely has a chance to, like, really unlock this multi-core stuff in a general way.
I think there's interesting APIs you can put on top of it to even make it, like, almost transparent to folks.
You know, I'm a big fan of the unsync library, which has a cool unifying view on top of threading, multiprocessing, and async.
And this would dovetail, like, right into that, like, just a little decorative value.
Oh, yeah.
And boom, it's subinterpreter execution and all sorts of stuff.
That would be great.
Yeah, it's really awesome.
Excellent work.
I'm looking forward to using it in 3.9 beta 1.
Now, before you get out of here, though, I do have two final questions for you.
I think we may have spoiled the first response.
If you're going to write some Python code, what editor are you going to use?
I think people may be able to guess what you're going to say here.
You know, it's funny.
First, I'll say that the Python extension for VS Code is written not in Python, but in TypeScript.
Because it's an Electron JS app, yeah.
That's a whole other topic.
An interesting one.
So, for the most part, I've been using Vim forever.
As long as I've used an editor that wasn't on Windows, I've been using Vim.
And so, you know, naturally, after years, you kind of build up muscle memory, and you build up a whole set of configurations and all that stuff.
And so, changing editors is hard.
But given that I work on an extension for VS Code, it's pretty meaningful to actually use VS Code, right?
Right.
Just to experience the thing, right?
It just makes it all that better.
I really appreciate VS Code.
I'm not really a big use my mouse while I'm working sort of guy.
So, VS Code is definitely out of the box oriented towards use your mouse.
I mean, Windows is.
So, kind of there's that mentality.
And that's fine.
It's definitely, that's a target.
So, it's not really how I operate all that much.
There are ways, however, there's like a Vim extension, which basically makes VS Code work like Vim.
So, I tried it.
And it was nice.
There were only a couple problems.
And they're kind of blockers for me.
Okay.
I use VS Code for Python stuff sometimes, but most of the time not.
Once you know and love an editor, it's tough.
I think that they're solvable problems.
And I've kind of pushed the feedback upstream.
So, who knows?
I mean, maybe I'll move away from Vim at some point.
Makes it hard when I'm in a terminal and I need to edit stuff.
I can't really pop up VS Code.
Yeah, yeah.
But you do have that cool of like remote editing stuff that's coming in VS Code, which is pretty cool.
That was one of the blockers.
And now that there's that, it's less of an issue for me.
So, there are only really a couple things left that are kind of blocking me from using VS Code.
Otherwise, I like it.
There are a lot of things that I just don't, haven't bothered with them, but you just get out of the box with VS Code.
And it's nice.
Cool.
All right.
And then notable PyPI package.
Maybe not the most popular, but something you're like, wow, people should really know about this and maybe they haven't heard of it.
That's a great question.
There's a few out there.
I'm a big fan of projects that really have been able to stay on top of their growth.
That's a really hard problem when you're working on a project and it gets popular.
Trying to keep up.
Most of the time it's just volunteers, spare time.
Things often grow pretty organically.
I think for the most part, most programmers are pretty pragmatic.
So, they aim for immediate fixes.
So, it's really hard over time to keep a project under control, especially when it gets big.
So, I'm a big fan of projects that kind of keep that under control.
There's some projects I think that have aimed for simplicity and really focused on that.
See, I'm setting myself up for failure here though, because I want to give a good example of this.
And not having looked at any projects too closely in a while, I may be kind of invalidating my whole point.
There's some neat ones out there that people find useful.
Of course, adders, but adders is kind of, with data classes now, adders is, it still has a place, I suppose, but not quite as much as it did.
Yeah, it definitely seemed to have.
Did it directly inspire data classes?
Yeah.
It's kind of achieved its goal like in a meta way.
Anyway, yeah.
I have one on there, ImportLib2, which is a backport of Python 3's ImportLib to Python 2.
But I haven't really kept up with it, so it probably doesn't work anymore.
Those are good.
Yeah, adders is definitely a good one.
Backport ones are kind of useful sometimes.
But there's also, there's some that make it easier to use some of the trickier functionality of Python.
So, things that deal with descriptors, for instance.
There's some decorator packages out there.
I think Graham Dumbledore has wrapped.
That's an interesting one.
One that I think people don't think about a whole lot is PSUtil, which actually is really neat because it has some good abstractions cross-platform for a lot of the things that you do system-side.
Like monitoring processes, getting system information, killing processes, or whatever.
But it also stays pretty focused.
I think that's a good one.
Yeah, PSUtil, that's definitely a good one, yeah.
PyC parser is one I've looked at recently that does some neat things.
It allows you to parse C code.
Pure Python, though.
Oh, interesting.
Okay.
There's some limitations to it, but otherwise, I think it's actually pretty cool.
Awesome.
Very cool.
Those are definitely some good ones.
All right.
Final call to action.
People are excited about this.
Maybe they want to help out.
Maybe they want to try or see some of the changes.
Is there something they can do?
Is there like this list you talked about?
Can they find this list to see if they can take one of them for you?
First of all, if anybody's interested, they can just get in touch with me immediately.
I'll get right back to you.
We'll talk about all about the project, how they can help, what their interests are, how that lines up.
That project I talked about.
That project I talked about, the link that you'll have, has a lot of the tasks broken down as issues organized on the project board.
So you can take a look at those.
Also, the wiki is basically where I've dumped pretty much all of my notes on this stuff.
Read through there.
There's lots of stuff.
You can see how it applies.
Give feedback on the pep.
And there may be other ways that it could work that you've thought of that nobody else did that are worth talking about.
But again, just get in touch with me.
It wouldn't take a lot of effort.
And I can get you working on something right away, something that will interest you and will make a real difference here.
I think this is a feature that people, until they think about it, don't realize how important it is.
I really do think that it's going to make a big difference for people.
That's awesome.
Great bunch of ways for people to get involved.
I totally agree with you.
I've certainly put this in my top five most important projects for Python.
So very good work.
I love this deep dive.
Thanks for taking the time, Eric.
Yeah, thank you.
Thanks for having me, Michael.
Yeah, you bet.
Bye.
This has been another episode of Talk Python to Me.
Our guest on this episode was Eric Snow.
It's been brought to you by Linode and TopTal.
Linode is your go-to hosting for whatever you're building with Python.
Get four months free at talkpython.fm/Linode.
That's L-I-N-O-D-E.
With TopTal, you get quality talent without the whole hiring process.
Start 80% closer to success by working with TopTal.
Just visit talkpython.fm/TopTal to get started.
That's T-O-P-T-A-L.
Want to level up your Python?
If you're just getting started, try my Python Jumpstart by Building 10 Apps course.
Or if you're looking for something more advanced, check out our new async course that digs into all the different types of async programming you can do in Python.
And of course, if you're interested in more than one of these, be sure to check out our Everything Bundle.
It's like a subscription that never expires.
Be sure to subscribe to the show.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, the Google Play feed at /play, and the direct RSS feed at /rss on talkpython.fm.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.
I'll see you next time.