The great power of Python is it's over 400,000 packages on PyPI to serve as building blocks for your app.
How do you get those needed packages on your dev machine and manage them within your project?
What about production and QA servers?
And I don't even know where to start if you're shipping built software to non-developer end users.
There are many variations on how this works today, and where we should go from here has been a hot topic of discussion.
So today, that's the topic of Talk Python.
I have a great panel of guests, Steve Dower, Pradyun Gedam, Ofek Lev, and Paul Moore.
This is Talk Python to Me, episode 406, recorded February 21st, 2023.
Welcome to Talk Python to Me, a weekly podcast on Python.
This is your host, Michael Kennedy.
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython, both on fosstodon.org.
Be careful with impersonating accounts on other instances.
There are many.
Keep up with the show and listen to over seven years of past episodes at talkpython.fm.
We've started streaming most of our episodes live on YouTube.
Subscribe to our YouTube channel over at talkpython.fm/youtube to get notified about upcoming shows and be part of that episode.
This episode is brought to you by Cox Automotive.
Use your technical skills to transform the way the world buys, sells, and owns cars at talkpython.fm/cox and by Sentry.
Don't let those errors go unnoticed.
Use Sentry.
Get started at talkpython.fm/sentry.
Steve, Paul Ofeck, and Predian, welcome all to Talk Python to me.
Happy to have a year.
Thanks, Dennis.
Yeah, you bet.
New for some of you.
Welcome back for some others.
So either way, still great.
Let's just go around the video square here and have you all just do a quick introduction.
I know, like I said, some of you have been here before, but it may have been a while.
So, Steve, you want to kick us off?
My name is Steve Dower.
Zuba on Twitter and GitHub in various places.
I'm CPython core developer.
And I actually got involved in Python in the first place to help with packaging.
And while I'm not kind of officially closely involved with packaging as much now, I still
help contribute.
Yeah, awesome.
And you're also pretty notable for helping step up Python's game on Windows.
Yeah, along with some of the others in this panel, actually.
We've got a few of the Windows contributors here.
Yeah.
But yeah, that's kind of my focus area.
Yeah, awesome.
Paul, welcome.
Happy to have you here.
Hi, nice to be here.
I'd say I'm Paul.
I'm a core Python developer and a pip maintainer, two things I'm most involved in.
I'm also, for my sins, the PEP delegate for packaging standards, if you like.
So basically anything that's a PEP around interoperability between packaging tools comes to me ultimately
for the decision on how it's going.
I've been around in packaging for years now, so I've got quite a lot of the history behind me,
which is also useful in this server discussion.
Yeah, absolutely.
Very much involved with pip.
And that's at the heart of this, right?
That's probably the earliest tool there, yeah.
It's a venerable one.
Yeah, welcome.
Hey, yeah.
I'm the primary maintainer of Hatch, which has been around for a few years.
But more recently, I rewrote it from scratch to better satisfy kind of what I wanted and what more users wanted the UX to look like.
It comes with a build back end hatchling, too, that is also a bit new.
So yeah, my primary focus is the user experience, making things as easy and less prone to errors as possible with perspective and fade and stuff like that.
Excellent.
Yeah.
So Hatch is in the general category of these higher level tools that work on top of the lower level Python ones to provide more consistent workflows for doing things.
And that's kind of the heart of this discussion, honestly, is like, what should those workflows be?
What tools should be responsible for it?
And so on.
We're not quite there yet because Pravyan still has to introduce himself.
Indeed.
Hi, I'm Pravyan.
I am a maintainer on PIP, FLIT, and a few more Python packaging stuff.
I'm also the maintainer of Tomo, as well as, well, I guess I'm a new C-Python code developer as of.
So yeah, that's me.
Yeah, welcome.
You're doing a lot of cool stuff.
So we're all here together because, let me pull this up my screen really quick.
Because of this discussion over on discuss.python.org, it's multi-part, which is notable for how long just a part of it is, Python packaging strategy discussion.
And part one, if you scroll down just a little bit, it says that there are 272 replies and 150 minutes of reading time.
And that's before we get to the related blogs, the GitHub issues, part two, the survey results, all of these things.
So this is quite a discussion, and a lot of people seem to care a lot about it.
I don't think you've brought your screen up there for us, Michael.
Oh, I have not, have I?
There we go.
Thank you.
Yeah.
So let's start the discussion with maybe a summary of what's going on here.
This was posted by Shamika, who unfortunately couldn't be here today, was going to be here, but can't make it.
So I'm going to have to let whoever feels most qualified to jump in on this.
Who wants to sort of set the stage for what this discussion was about?
Paul, you look like you might be willing to fight.
Paul looked like everybody else was backing off there.
Yeah, one of the things that we've wanted to do for some time now is sort of get a better feel for how the user community views packaging.
Shamika joined the packaging community as the project manager for the packaging effort as a whole.
And one of the things she initiated in that was getting a survey done to effectively try and answer those questions.
What do the users think of the packaging ecosystem?
What do they think of how things are going?
What do they want from Python packaging?
There was a fair bit.
There was a, I don't honestly know how big the response was, but it was quite, we got quite a decent response from it,
which basically got summarized up in a couple of feedback documents.
Yeah, I think, here we go.
There's a PDF that I'll link to that has the actual survey responses.
Yeah, and it turns out that putting a banner on PyPI.org seems to be the winner in terms of reaching out to people who care.
We have almost 8.7k responses and 7.9k out of those are from PyPI.
So that's more than 90%.
Yeah, absolutely.
Basically, from that, the discussions on Python discourse are following on from that,
taking a number of the messages that came out of the survey,
and essentially getting everybody in the packaging community together to talk about, you know,
what does this mean?
What do we expect we can do about this?
How do we address the comments that have been made?
Where do we take it?
There are a number of discussions planned.
I don't know how many.
The first one, Pradian's either waving at me or suggesting it's five.
The first one is the one that we've had already, the sort of main strategy.
There are a number of follow-ups to that, one of which has just started, but most of which haven't taken place yet.
So where we're at now, the initial discussion, which was the thread that you showed previously,
that went on for about a month on discourse, generated quite a lot of discussion.
And we now need to sort of digest that and understand where that leaves us and what actions we can take from it,
what conclusions we can draw, how we pull that together into something that we can actually do something with, I guess.
Yeah.
And I think it's worth adding that this is not kind of an unusual thing for our packaging kind of participants.
We have quite a significant history of a few comments kicking off a huge discussion that flows and fragments and drags on for hundreds of posts.
And this one actually feels a bit different.
This one feels like there's a real sort of commitment from certainly some of the main players who are involved in it.
You know, if you look at the regular posters in that other thread, then, you know, you'll see a lot of us up near the top.
But there's also a number of other people involved who are, it feels more serious this time.
It feels like we really not just feeling or recognizing pain that we've always kind of seen and known is out there for a lot of people using it.
But it feels like we're kind of at a place where something has to give.
And I feel like we're getting closer and closer to being able to change whatever it is that needs to change to make that give.
So I think it's an exciting set of discussions, though it is long and meandering and drawn out.
And occasionally a little frustrating.
I've taken a few breaks during it just to cool off.
And I suspect some of the others in here have as well.
But it is a lot of it's nothing new.
It's nothing that we haven't heard or come across before.
Having it laid out the way the survey did gave us a real kind of strong starting point.
And there's just a lot of honestly discussion.
A lot of things that have to be talked through because we're all different people with different backgrounds, different areas and trying to get aligned.
Well enough to then align the random group of volunteers who make up this group.
It's like we jokingly call it a packaging authority, but that's the biggest joke in the world.
And so to actually align the volunteers working on independent projects takes a huge, you know, we've got to build up that momentum and that alignment before we can even start, you know, changing projects.
Yeah, there it is.
There's a couple of levels of this, right?
I mean, as a broad Python community, we've got to get enough alignment that people will back it.
But there's a bunch of people who would have to build whatever variant of this you might pick.
And you've got to agree on that as well.
And many of them are working on different tools.
Pradion mentioned Flit and Pip.
In fact, it's Hatch and Hatchling.
Paul is Pip.
Like, in some sense, the discussion might be, well, should pip take on the responsibilities of Flit?
Or should it do less?
And Hatch takes on, you know, there's this give and take, which I think is going to be an interesting thing to see play out.
We've had a thousand flowers bloom sort of moment, I think, with the packaging.
We've seen a bunch of different tools come along.
But that's also led to, I think, confusion with people who are like, well, one blog post said use poetry.
Now this one says use Hatch.
This other one said don't use any of them.
What do I do?
I'm new.
I'm confused.
Yeah.
Well, before we move on, just sort of summarizing your thoughts of this overall discussion, just kicking it off.
You know, Ofec and Pradion, you haven't got a chance to weigh in.
Ofec, what do you think?
Yeah, I will say, although the main sentiment about the takeaway from the survey was that people wanted more unification and sort of guidance,
I think the thread itself was not as much about that, but just like a myriad issues.
So only one of the issues was actually about tools and user experience.
Other people brought up other longstanding issues.
Like we want more integration with Conda.
That's a large topic there.
Some other people want better support for essential modules and detection of like GPU, stuff like that.
So there's lots of needs from various communities that also have to be worked out.
It's not all just about user experience and things like that.
Sure.
That makes sense.
Pradion, you wrote a huge, great long blog post on this, which we're going to get to a little bit, but, you know, higher level first.
It's been productive.
One of the things that Steve gave me the word for is level setting.
There's a lot of sort of bringing everyone up to context on or bringing everyone up to the same amount of information and sort of understanding other use cases that you don't have yourself,
even though you're right that supports that and things like that.
Having all of the discussion happen has helped bring everyone up to the same page on these things.
One thing I want to push back and what Steve just said, which is sort of the Python packaging authority does not have authority, is probably not true.
We do have four here who gets the authority to decide on things directly delegated from the steering council.
I heard the cats.
That's about as far as it goes.
There is a level of authority involved, but it's limited because we'll get onto the structure of the PyPA, I guess.
But there's a lot of independent projects, a lot of independent people.
And one of the things that this discussion did was bring everybody together and get us interacting maybe more than we had done.
I think historically, it's probably worth also saying that historically, packaging started off very much one or two tools that did everything, things like disto tools and setup tools.
They were it.
And there were all sorts of issues at that time, which meant that we consciously tried to take a view that we were going to enable diversity, allow other tools to get into the mix.
We started by looking at how we could make alternatives to setup tools work, how we could give people choice there.
And from there, it's grown.
And we've now got choice in a lot of areas that we never used to have choice in.
That wasn't an accident.
That was a conscious decision that we made to try to give some level of competition, some level of innovation that hadn't been there beforehand.
One of the things that this discussion has done, well, one of the things the survey did has brought home to us the downside of that is that everybody's confused as heck, that nobody knows what to do now because we've just given them 100 million choices.
And that's a very fair comment.
It wasn't the intention, but it was an obvious consequence of that diversity that we promoted.
Now what we need to do and what we're trying to do on the back of the discussion, on the back of what we've learned is try and pull that back together again.
We've got all these tools now.
We want to try and, if not exactly unify them, but certainly give a clearer picture, a more this is how you do things story.
And part of the problem with that, one of the things that Getting Everybody Talking has done, it's made it clearer that we do need to work together.
We can't keep competing because the users of the tools are just lost knowing what to do.
So we need to bring things together, but nobody is, certainly I don't think at this point anybody is saying that we're going to shut down all the other tools, all the people working on them have wasted their time.
That's not the idea at all.
But we still need to navigate how we get a more unified approach within the context that we've got, which is a lot of people working on their own vision of how they are serving a subset of the overall group of users.
Like Steve said, I think it's been really useful getting everybody together and everybody getting each other's perspectives.
We now need to work out what to do with that, frankly.
This portion of Talk Python to Me is brought to you by Cox Automotive.
Cox Automotive isn't a car company.
It's a technology company that's transforming the automotive industry.
The team at Cox Automotive understands the future of car buying and ownership,
and they're looking for software developers, data engineers, scrum masters, and other experts to help make that happen.
If you're interested in innovating with brands like Kelly Blue Book, Auto Traders, and others, then you should check out Cox Automotive.
Just visit talkpython.fm/cox to find out more.
Thank you to Cox Automotive for sponsoring the show.
One thing that stood out to me from reading the survey, and we can poke through some of the interesting questions and responses there.
I feel like there's two users that almost need two approaches.
There are people who are creating libraries and shipping them to PyPI, and they're kind of core Python developer folks.
Not core developers, but they live and breathe Python, and they build Python things, and stuff like Pydantic or FastAPI and so on.
They might need the flexibility and the diversity.
Sarah, the new grad student in the biology department that needs to get pandas to work, and she knows that Python is her path forward.
She shouldn't have to decide whether to use Flit or Hatch or straight pip plus maybe pip-tools.
These are two very different use cases, and almost like bringing them together to, well, what's the best of those two solutions together seems almost maybe the wrong.
You might make both groups unhappy going down that path.
If we bring together the current 8,000 tools, it's going to make 7,999 groups unhappy.
I mean, this is part of the challenge.
Though I think an interesting thing there, and probably about halfway through this mega thread, it kind of clicked, at least for me.
I think some people had mentioned it earlier, that there's really two big categories of tools.
Kind of as you say, there's the tools for packaging and the tools for using packages, which includes what seems to be the biggest issue is the environment managers.
It's the virtual environment creation, which is kind of half of poetry, but not the other half.
A big part of Hatch, but not the other half.
It's none of Flit.
It's none of setup tools.
It's like those are purely about building packages.
And it's on this side, the building packages, where we've invested in kind of creating and driving that diversity.
And I think that's worked really well.
We've got a range of standards that make them interoperable at the right places so that pip can take kind of any of these backends and trigger them correctly.
Source code written to provide metadata for any of these backends can be easily transferred between a lot of them.
That seems to mostly work.
And it's a situation where, again, as you say, the deep in Python maintainers have a choice in what backend they want to use.
And what kind of clicked is people were saying, you know, we want less diversity.
And a lot of us were going, well, the diversity is in the backend.
So if you want less, then we have to combine the backends.
But I think what clicked is that, no, that's not what they're wanting because it is the newcomer to Python who just wants it to work, who's trying to choose between all of these environment managers.
And especially when you throw a condor in there as well, which is just so fundamentally different in how it behaves from the ones that kind of rely on PyPI directly.
We already have that divide and the diversity has shown up on this side uncontrolled.
Uncontrolled.
We didn't set out to see poetry created or see Pip-Enf created or any of these, but it's there.
And how do we rein in something that has grown up all by itself completely outside of anything that we've ever tried to control?
One thing that struck me in that discussion was I'm really quite happy with a lot of the, like Steve says, the backend tools, all that sort of stuff.
But it occurred to me that when I'm just writing little hobby programs and things like that for myself, I'm with everybody else.
Packaging is horrible.
I just want to say, start a project, start up a notebook, do something.
And it's really hard.
And it hadn't occurred to me until we had this discussion that that's very much the two sides of the user equation.
We've really not put as much effort into the just wants to use Python to do their job side of the user base than we should.
And tools like Hatch and PDM is another one.
Poetry is another one.
They are addressing that.
And I actually went off and started exploring them.
I thought, hey, there's cool stuff going on here that I really wasn't as conscious of as I could have been.
So, yeah, absolutely.
We need to look at that side as well now, I think.
I agree.
The Italian behavior we're talking about is like libraries versus applications.
So, as people have mentioned, it is very easy now to build the library and test it.
And that's due in large part to the standards that we made to allow diversity for the build back end.
So, that's very good.
But, yeah, it's where the applications are.
That's like the hard part now.
And I think at least one of the missing features that I think we should devote resources to, I know Brett isn't here, but locked files is something that we desperately need.
And poetry has their own implementation of locked files and dependency resolution.
So does PDM.
But there's nothing like standard for that.
And that should be the next step, I think, for applications.
While we're talking about the future and sort of where we are, I will point out part of the reason we're seeing a bunch of this is because we've solved some of the harder problems already.
We are at a point where, oh, I'm having difficulties installing pandas and figuring out how to work for that.
And not, I can't install pandas.
That's a good point.
Or I can't publish pandas or whatever.
So, we have been solving problems as we go.
It's just we're going to keep seeing more and more problems, especially in a user base this large.
There's always going to be more interesting and really difficult problems to solve.
I think a lot of the people who are now just trying to get on with using Python for their day job,
probably when we were starting the process of moving away from setup tools, they didn't even exist.
Python wasn't that popular in those days.
There's a new set of users who are coming along with a new set of problems.
And if we don't keep our eye on what people are trying to do with Python, we'll get left behind, I guess.
We won't be relevant.
They won't have any solutions for what they're trying to do.
And a lot of them came in because they believed Python was easy because we've got a reputation for being easy.
They wouldn't be frustrated if they thought it was going to be impossible and then found out that it's impossible.
They wouldn't be frustrated.
They wouldn't be happy, but they'd be satisfied.
It's because they've come in expecting this great experience that everyone's talking about.
And we're just not able to deliver it in enough cases that the frustration comes in.
And we get that.
We all get hit by it as well.
I am quite optimistic about it, though.
I think one person brought up a good point in one of the recent discourse threads that, despite the hardships with packaging and everything we're discussing here, Python has gained massively in popularity and usage despite all these obstacles.
So, yeah, I'm pretty optimistic that we can satisfy people's needs.
I'm too.
I think there's – I think Paddy didn't really hit on it.
I remember long ago that certain things wouldn't install.
Sorry, you couldn't get this to compile or this other thing wouldn't work right.
And it hadn't really occurred to me explicitly, but I haven't seen those errors for a real long time.
Yeah, and there's a lot of work that's gone into build backends to make that possible.
Certainly for Linux users, the huge amount of effort that went into defining the many Linux standard, which is kind of the base layout of system libraries
and where they're expected to be on a system so that people can build a binary package for Linux that can assume that those libraries are there and distribute those has meant that, yeah, a lot of the time when you go to install something, you'll get already built, already compiled packages that are just ready to go.
And kind of the problem that that's raised up is we've taken the really obvious problem of you don't have a compiled package yet up to the point where you have a compiled package that is subtly incompatible with some other compiled package,
which can be really subtle because it can be one of those 99% of the times it works fine and then the other time it just segfaults and everything dies.
Or maybe subtle data corruption, like there's a million little things that can subtly go wrong there and we're starting to see some of those come up.
Certainly the people in the data science side of things saw them come up quicker because they use a lot more of these complex packages and they do interact with each other and they do check things like numerical stability.
A lot of the rest of us don't worry about that kind of stuff most of the time.
And so we're like, yeah, this works.
This works.
Put it out there.
Maybe if wheel existed before conda, people would have just pushed harder on wheel potentially and conda might not exist.
Not saying it shouldn't exist, but that might, it might not have been a bad enough problem to make it.
I agree.
Like conda came into existence because the solutions that were there weren't able to satisfy it.
And it was so far, like just the distance from where we were at that point.
Because at that point, like eggs, probably no one watching even remembers eggs.
I'm sure Paul does.
At that point, it was, OFEC may as well.
I'm not sure how long you've been involved, mate.
But yeah, it was like, it was a very different world.
And the distance to get there just looks so impossible.
But yeah, if we'd been at wheels, then they may have said, well, this little tweak to wheels will make it work for us.
And who knows where we might have been then.
It's quite possible.
I can't judge, honestly, but it's quite possible.
But conda is where wheels will be in a number of years.
I think there are fundamental reasons why that might not be the case.
And we may have to find different ways of dealing with the problems.
But yeah, these sort of really difficult, really basically not solved technical problems.
It's not that Python is struggling with something that's easy.
There are no languages or environments anywhere that have really solved these problems.
So we're trying to find solutions as we go along.
And I think in spite of what Steve is saying, I think having an 80%, 90% solution often is plenty good enough.
I don't want to say that we should abandon the users who really need that because they are on the forefront of things like AI research and data science.
And they're doing incredible work, which they can't do if Python falls apart on them.
But at the same time, I think we're now in a position where we have to balance the general solution with the specialist solution and try and understand that.
And for a lot of us, certainly for me, that's quite new.
I'm not entirely comfortable yet with the idea of saying we need a different solution for this than we have for that.
It's something we're all getting to grips with, I think.
One aspect of this is also sort of kind of related to the Konda and Python success aspects of this is Python is a famously glue language.
So when you're trying to package or use Python, you're not just using Python.
You're using a whole stack of other languages and tech stacks along with it.
Photography uses Rots under the hood.
And there's Fortran code in NumPy.
There's all sorts of diverse tooling underneath what just looks like a Python package.
And that works.
And you are able to use these.
And it also introduces all the challenges that come with all of those themselves.
So we're in a good spot.
There's also a long way ahead.
But we're also quite a ways from where we were.
And I think one of the things to bring it around that the strategy discussion is doing is helping us understand where the gaps are right now and what the most painful points are right now, which is where the user survey was really helpful in telling us these are the things that at least the users that we follow and who did fill the survey think the problem and pain points are.
I would say just quick estimate looking at the source of the respondents from the survey.
that even these results lean more towards the highly committed software developer side and data science side of Python and not the super casual user.
There's a huge bias.
Yeah.
My example of Sarah in the biology department, she's not going to PyPI and going through surveys.
She might see the banner, which is, whatever, I care by biology or I care by economics.
Right.
So I think even this should be taken with a bit of a bit of a bias.
I think one of the useful pieces of data that we did collect was user experience, like experience level.
One of the things that's not a bit true but not done is sort of split this survey data that we have across various axes and see if we see other pieces of transparency here.
I don't think any of the people who have acted in this space have had the time to be into the data.
I, for one, don't have the expertise or skill set to do so.
So like one of the things that would be really useful is having people look through this data and come up with new insights and flag things, which is an unangering amount of work.
It is.
That's very much a common problem we have is so many people use Python who we just have no way of getting in touch with.
We have no way of knowing what their experience is because why would they talk to us?
It's like you don't go and talk to the engineers who design your car.
You just drive the flipping thing.
And there's an awful lot of people who treat Python like that.
And we can ask.
We can put surveys up.
But at the end of the day, like you say, the sort of people who would really, really like to get feedback from simply don't look at these sort of things.
They aren't involved in going on to PyPI.
You know, they type pip install something that the guy across the desk from them told them would work and they never see PyPI.
In my workplace, I was very conscious that we had some people who were dabbling in Python who didn't interact at all with the community, never even contemplated doing so.
And that's with me sitting next to them and saying, hey, Python's cool.
And that's the norm.
That's the actual Python user.
Anyone who's looking at a survey and responding to it is already in the top 5%.
This portion of Talk Python To Me is brought to you by Sentry.
How would you like to remove a little stress from your life?
Do you worry that users may be encountering errors, slowdowns, or crashes with your app right now?
Would you even know it until they sent you that support email?
How much better would it be to have the error or performance details immediately sent to you, including the call stack and values of local variables and the active user recorded in the report?
With Sentry, this is not only possible, it's simple.
In fact, we use Sentry on all the Talk Python web properties.
We've actually fixed a bug triggered by a user and had the upgrade ready to roll out as we got the support email.
And that was a great email to write back.
Hey, we already saw your error and have already rolled out the fix.
Imagine their surprise.
Surprise and delight your users.
Create your Sentry account at talkpython.fm/sentry.
And if you sign up with the code Talk Python, all one word, it's good for two free months of Sentry's business plan, which will give you up to 20 times as many monthly events as well as other features.
Create better software.
Delight your users and support the podcast.
Visit talkpython.fm/sentry and use the coupon code Talk Python.
There's a really interesting term that Scott Hanselman came up with called the dark matter developer.
The unseen 99%.
And it's exactly what you're describing here, Paul, is you can't reach them because they don't come to the meetups.
They don't come to the conferences.
They don't subscribe to the blog.
They just use it as a tool and go home.
And they shouldn't.
They don't, you know, it's not what they're doing.
Some of the best feedback that we do get in these discussions comes from, as well as kind of people who get actual issues reported to them.
So every time the pip maintainers are like, people are reporting this problem all the time.
Okay, we know that's a problem because it's getting to the developers.
But we also get feedback from people who do training and tutorials and people who kind of manage Python's presence in a workplace and in an organization.
Because in that position, and that's kind of the position that I do as well at my work, we get more of that feedback.
We get people complaining about things that they'd never think to take out in public, but they'll happily put on an internal list somewhere saying, hey, how come Python can't do this?
Right.
Or they'll ask for help because they actually have a job to do and they need to get it done.
And, you know, we're all getting paid to be there.
So there's no kind of fear or shame in saying, hey, can someone just tell me how to do this?
And so by being kind of that central point in that place, just the same as when you're teaching a class, students are going to say, this didn't work.
And now you see a problem.
And when you start seeing the same things over and over again, that becomes kind of useful additional feedback to factor into these kind of surveys.
And I don't think we've put a lot of weight in kind of the quantitative response here.
Like it's quotes.
It's stuff that people have put in the open spaces that, you know, the ones that have really resonated or been repeated a lot are the ones that we've pulled out into the discussion and have been working from.
And kind of the actual numbers is like, yeah, they could mean anything realistically.
And we can slice them to make them mean whatever we want.
Exactly.
So there's a careful balance there of drawing the right insights from this, knowing the limitations of what we've done.
As is probably the case with every survey.
Let me read out some of the, oh, sorry, go ahead, Nofick.
And then I'll read off some of the comments that actually some of the respondents actually made.
But go ahead.
Oh, yeah, no, I was going to say, I agree with Steve that I think since we have no access to these, you know, 99% of actual developers, I think what maps closest to them would be users and industry.
I got companies building applications, because if you're a user of Python, like kind of by definition, you're writing an app and not really building a library.
So I think if we hear feedback from, you know, people at companies trying to build apps facing hardships, I think that would reflect the main, main chunk of users.
That is a good point.
I made the distinction that was almost like beginner versus expert, but really, I guess how I should have phrased it is closer to what you said, Ofick, is people building applications and presentation type things that they never will share with anybody through PyPI or something.
They just want to get it to run.
Maybe they'll deploy it, but they won't publish it.
Versus people building Flask and Pydantic and SQLAlchemy and so on.
These are really different use cases.
So the person building that may be extremely talented and experienced, but they also have different constraints and different goals.
So that's a really good point.
All right.
So I'm quick respondent thoughts here, just from this discussion thread.
So one person says, unify multiple tools.
It's good to have new ideas and new implementation, but it has to converge after a while.
That's pretty interesting.
Number two, there should be one and preferably only one obvious way to do it.
Get rid of the fragmentation straight out of a Xenopython there.
Number three, I definitely want Python to introduce the one true packaging tool.
Ideally, both as easy as Rust's cargo and extensible package.
Installing is easy.
Package building is the wild west.
So that kind of speaks to potentially the other side of creating the libraries.
And then person forward said, blow it all away.
Just everything goes away.
Start over from scratch.
Paul, you had actually a comment here in this discussion about the historical perspective.
I think I even potentially pulled it up here saying, you know, having pip be exactly this tool might be really hard because pip has been built to do certain things and people now rely on it.
Right.
PIP is in a very odd position here.
It is shipped with Python and it's shipped with Python for a very specific reason.
You've got to have something to start the whole process off.
You've got to be able to bootstrap.
If you use Hatch, how do you get Hatch on your PC?
You need something.
And pip was incorporated into the Python.
It's not technically part of the standard library.
It's installed with the standard library.
But let's not go there.
But it was incorporated to give us that bootstrapping capability.
At the time, that's really all pip was, was an installer.
It had build capabilities because you needed to build things from source because that's how you installed a lot of things.
I predated wheels and all that.
Yeah.
Wheels were nowhere near as common at the time.
Since then, things have changed.
But pip is still the one thing that it's where people get into the whole packaging ecosystem.
They have to start by saying pip install.
And there's a very good point which was made.
I mean, this is January.
My opinions change every 15 minutes.
So that was a long time ago now.
But there was a good point made, which is that pip is in the position to be that unified tool.
But it's not what it is now.
Other tools like Hatch or PDM or Poetry are better at being the workflow tool that people talk about when they make analogies with Rust and Cargo, for example.
But they don't come with Python.
And to balance that problem out and come up with a solution there, we can't just look at packaging in isolation.
One of the things Condor does, which is what allows them to solve certain problems that they solve, but at the same time is one of the reasons some people don't find Condor appropriate, is that it bundles Python.
You install Condor and then use that to install Python.
And that's a fundamentally different way of getting Python.
Rust has a similar thing.
You get rust up and that gives you rust and cargo.
The model is there.
The model is used in other places.
But a change like that is not something that the packaging community can agree on by themselves.
That would involve the core developers, the steering council.
It's a very, very significant change to the whole model.
And I think one of the things that we struggle with and one of the things I was sort of trying to get at at this point in the discussion was that we're not in a position to do that at the moment.
Maybe we should be.
One of the things coming out of this discussion is a broader look at what can we achieve, what can't we achieve.
But we need to work out how to take that forward if we want to.
So, yeah, I think pip is in an odd position because a lot of people say, why can't we add this to Pip?
Because pip should be the thing to do.
But speaking as a pip maintainer, I'm not even sure if that's what pip should be doing because we've got a lot of history.
We've got a lot of legacy code in Pip.
It will be a big disruptive change to use as a pip to add workflow.
Whereas Hatch is doing a great job of it.
PDM is doing fine.
We do want to get into that area.
And that's where, in all honesty, that's where a lot of the discussion started to veer towards big grand philosophy questions.
And I think a lot of people got quite frustrated because they're hard questions and nobody's got an answer.
People wanted action.
I think one of the things that came out of the survey was a real sense of urgency.
People said, burn it all down and create something new now.
We want a unified solution now.
And that put everybody under a sense of pressure.
We ought to be doing better.
But the reality is some of these things will take a long time.
And thinking about them is the first step, which is what we're doing here.
The analogies that people make, I find very interesting because some people do come in saying, make it more like Condor, which, as Paul said, kind of sits outside of Python.
But then other people say, make it more like Cargo, make it more like NPM, which kind of have the virtual environment thing built into the packaging tool.
So rather, but it still lives inside it.
And we get people always coming in with these assumptions that because pip is part of the standard distributions of Python, I'm choosing those words carefully as a core developer.
Because it comes with the Python.org distributions.
They assume that because it's included, it's going to be like the ones that are included in other languages.
And that's simply not the case.
I mean, for starters, we existed well before those did.
So we couldn't have copied what Rust does or what Node does.
But having all those requests come in kind of just show that if we did burn it down, we don't even know what people actually want built back in its place.
Because they're all asking for different things.
I think part of the challenge, people are asking for you all to decide.
I got that sense from a lot of this conversation, from some of the feedback, the survey results, was nobody is deciding in the core developer space.
Tell us how to do it.
We'll go with that.
A lot of them would say.
Obviously, not everyone.
The C-Python co-developers, well, this isn't the most polite way of saying this, but they sort of don't care about packaging.
The Python streamer effectively delegates all of this and says, you figure it out.
And while there's a bunch of people here who are co-developers, they're wearing two hats.
It's not a single hat.
And to jump back in the conversation, I'm sorry, I've done that a few times already.
Please do.
Python is a very redistributor-driven distribution model.
Whereas with RustUp, for example, everyone's getting Rust as the Rust team built it and as the Rust team packaged it and it ships to them.
Many people are getting their Python from Homebrew or from PyEand and compiling it or from ASDF and doing the same thing.
Or from Debian who have patched it in a bazillion ways.
And a lot of the Python packaging problems that people keep hitting are actually these problems in a trench coat.
These are Python distribution problems that are showing up when they use the packaging tooling.
And that causes a lot of friction there as well.
And solving that as probably hinted at is the last problem.
And it's also tricky because problems mirror your organization.
And as we're organized, we aren't set to solve this.
Not easily.
To be fair to the distributors, we like distributing Python as source code.
Like the official release of CPython is a pile of source code that someone else should build and give to you.
Because that's the Linux model, whichever model it is from 30 years back, is you got your operating system with the software built for it by someone who picked up all those source bundles and built it for you if you didn't do it yourself.
And so it's never really been built around the core team, build the binaries and distribute those.
And it certainly does confuse people because we do do that for Windows and we do do that for macOS because we've been able to because we never had distributors pick those up.
I think with...
In the same way that the Linux distributors did.
With more Windows users nowadays than we used to have, I think that confusion is much more visible.
The people coming from a Windows background think, well, I get Python from Python.org.
People coming from a Linux background think Python.org has nothing.
I get it from Ubuntu or it's just there.
I don't even know where I get it from.
That's something that is changing.
I don't know if we will ever...
I think languages like Rust with things like RustUp, that's a new model and it comes from much more recent how people expect things to be delivered to them.
And Python's got a heck of a lot of history here that isn't as easy to change as people might like to think it is.
I'm not saying we don't.
I'm not saying this isn't a challenge.
I guess to draw an analogy, it's similar to the source distribution versus wheel problem that we solve in some sense, wherein you can still build your own NumPy, but the NumPy developers ship a single NumPy and that has certain choices made that you can make differently.
I guess I wasn't trying to be combative here.
This is how packaging discussions always go.
This is how packaging discussions.
We always get combative.
We sound like we're arguing and we're actually agreeing with each other.
We're still just arguing together.
But a big difference...
Oh, sorry.
In future, I would imagine what would be best for users would be not to download a Python executable that installs, but rather you would download the workflow tool.
So whatever our version of cargo ends up being, that's what you would actually download and install on Windows or Mac.
And that would manage your Python.
In that case, then that would be easier to install for users and you wouldn't have the conflict of, you know, like, should pip do everything?
Because then it wouldn't be pip we're talking about.
Because right now, if you were to add workflow features to pip, that's a bit awkward because pip is in every Python.
So you have like multiple workflow tools on your path, which is a bit odd.
Yeah, then you're tied to figuring out how do I get to the right version of Python to then ask it the workflow questions?
And what if I get that wrong?
And if 3.10 is not in the path, it's installed, but why doesn't this work?
So on and so on.
Yeah, so a couple of the interesting tools that have been growing a bit in more recent times.
We've had the PY launcher on Windows for a while.
And Brett, unfortunately not here, is maintaining a PY launcher for other platforms as well.
And so there's some suggestion, I think Brett's actually experimenting a bit with adding some of this functionality into that tool.
So kind of the primary function of the PY tool is you have that one command to launch Python, and it takes an option to select which version you actually want to run.
So you don't end up with multiple copies on path.
You don't worry about which order they're in.
You just say PY and you'll get the latest version, whatever the latest version is, because it can do a more intelligent sort.
Or you say PY-3.10-3.11.
Or it has shebangs on Windows even, or you say the version in there?
Yeah.
The Windows one has a lot of extra functionality.
I briefly looked at merging the two and kind of adopting Brett's one for both platforms.
But honestly, the Windows one, like 5% of the functionality is launching Python, and the other 95% does not exist in the cross-platform one because it exists in the platform itself.
So there's a lot of other stuff that I don't even want to bring up in the Windows one.
But we do already have this extra tool that's getting installed everywhere, that's independently installable, that might be a suitable place to take on some of that workload.
I think the big challenge here, and I don't want to get into the Pip-Conda discussion again, but we have at this point 10 years worth of evidence of what happens when you put out a workflow tool that isn't strictly Python, but will give you Python.
And it hasn't beaten all the other workflow tools.
People still don't want to use the tool that does that.
And so I don't know if we can simply assume that providing that tool or mandating that kind of tool is going to be a winner because it exists.
It's been around for a long time, and it's not won.
I think it's proven to be a fantastic experience if it suits you.
That's what Condor...
You listen to a Condor user, and they are massively enthusiastic about it, but it's because it fits what they want to do.
You listen to somebody who doesn't like Condor, and they're equally frustrated with the choices it makes.
And I think Steve's right.
I think we have to learn all of the lessons, not just some of the lessons.
And one of the lessons here is that sort of everything in one bundle tool is a mixed blessing.
I'm going to call from January because that's right in front of me, and it seems very prudent.
Many of the respondents wanting a unified tool will have an implicit assumption that their preferred workflow will be supported.
There are many workflows in the queue, and trying to corral all of them into a single workflow is quite possibly a not-particle problem.
I don't think anybody responded to the survey saying, please give a unified workflow tool that doesn't do what I currently do.
Exactly.
Please make what I do not work.
Yes.
Or make it hard.
Yeah.
Everyone thinks their own workflow is normal, and everyone else is the weird one.
Speaking of workflows, I was thinking through this process and thinking of, well, what might an option be?
What might some other tool look like?
You all talk a lot about in the surveys and in the responses about a user experience, right?
And we've got certainly notable people in the community who are well-known for creating APIs that just connect with folks, right?
So I put together this idea of, what if there was a few more commands in Python itself that you didn't even have to think about?
Do I have pip?
Does it use hatch under the covers, or does it not?
What if you had things like Python init, Python add requests, Python upgrade all, Python build?
I think you've just misspelled hatch here, haven't you?
I probably have.
You've spelled hatch with a P-Y-T-H-O-N.
I probably have.
Yeah, exactly.
Well, but I don't have to think if pip is installed.
I don't think if pip is there.
I'm almost afraid to put this up here as a proposal, because if it got adopted, then it might be the way, and I don't like it.
I don't know if I would like it, but have you thought to go this far to say, we're not even going to talk about the tools that make this happen?
This might be pip plus hatch making this happen behind the scenes.
You might set an environment variable that says, please use poetry when you do this stuff, but I don't want to talk or know about poetry.
I just want the output of it.
Just Python install, that's all you tell them, versus pip install-requirements.txt.
Oh, I meant pip 3.
Wait, pip 3 doesn't exist.
Why doesn't pip 3 exist?
On and on and on, right?
And then if you want to do more, you use hatch, or use pip-tools, or insane, not insane.
I'd use that.
I think there is a question, like Steve said, this is almost hatch.
MakeApp is the one I'm looking at and thinking, please give it to me now.
But it's almost hatch.
The question is whether hatch is where it is, or PDM, or poetry, or whether it's Python.
If you want it to be the Python command, then I think there's a whole, we're way too far through this now to talk about the role of the PyPA,
and how it links to the core developers.
But there's a whole disconnect that we struggle with, and we continue to struggle with, which is, what can we do in packaging, and what do we need the core to be involved with?
Pradyum mentioned earlier, Python core, defer packaging decisions to the PyPA and to the packaging people, which is great as long as it works.
But when it doesn't, when we need to integrate more, we're not really there yet in knowing how to address that sort of thing.
So I think a tool that does something like that, it's certainly what I'm looking for.
It's certainly what I think a lot of people see when they say workflow tool.
And as I say, we've got people like Hatch and PDM and Poetry making that a reality.
You just made tools into people.
Yeah, sorry.
I don't know all the names.
But yeah, we have people making that sort of thing happen in the different tools that are around.
Unifying is a question that I think we need to look at.
And there's a clear message that having 10 different tools that do this sort of workflow is not what people want.
But we don't know quite what the best model is yet.
So there's some work to do there.
The massive danger, Paul, is if you pick one and it turns out to not be really that great.
Yeah.
Which we've been burnt by before.
Many times.
So it makes us a lot more hesitant to pick something.
I think all I'll say on this is, yeah, there's tools out there doing a lot of this.
The best way to get it adopted into core Python is have a tool that is clearly the winner that we can integrate that tool directly.
And so the transition path becomes if you're using Python 3.36 or whatever version it makes it into, then you have Python that command.
If you want to work with a previous version, then first you install, let's say, Hatch and use Hatch that command.
This is the kind of thing that might get integrated into that PY launcher I mentioned before.
Because we have more ability to add more random commands to that.
All of these are valid Python commands today.
So people could theoretically be running these commands already and having it do something.
I'm clearly not doing what you intend here.
But they're all valid commands.
And so we can't just push out a minor update that breaks them.
The only thing we do need to watch with that is something that Pradian mentioned in his blog post, which is, we want to see a winner in one sense.
But we want to be very careful not to end up in a competitive situation where rather than working together to get to the ideal workflow, we're working against each other.
We do not want, it's not going to be good for users.
It's not going to be good for the tool developers.
It's not going to be good for the community if we're all trying to compete with each other on, I've got this whizzy new feature.
We want to work together.
And I think we want, I hesitate to use the word a winner, but we want a clear sort of best of breed that we can promote.
Because, as we've said, we've been so burned by saying, this is what we should use, having everything go horribly wrong, that we're very reluctant to do that without evidence.
So we want to see something become that tool that people want.
Which is going to get difficult as long as we have competing solutions where it's like, oh, now we're split 50-50.
And now what?
There were decent solutions.
Whichever you pick makes half the ecosystem angry.
Yeah, but I think it is important to eventually get help from Core Python.
I know we were just talking about how Conda has been around for like a decade and that workflow tool hasn't won.
But like, if a decade ago, you know, on python.org, you had that tool, I think that would have won.
It's just about advertising it on, you know, Core Python.
So eventually we'll need their assistance.
Yeah, that's a really good point.
Indeed.
And, you know, we definitely do want to make it work from the Core Python side.
I might be the least kind of conflicted core developer here.
So I can say that we do want to make this work.
It's just seen as kind of outside of the core runtime responsibilities.
One of the massive discussion threads actually kicked off because I mistakenly thought the steering council kind of owned responsibility for packaging and delegated it officially to the PyPA.
But it turns out I was wrong and they just don't cover packaging at all.
And so packaging is kind of outside of core focus entirely.
It's officially not cared for by the core developers, not unofficially not cared for, if that makes sense.
It's like we do care about it.
We do want it to work.
We do want it to be a good experience because we know it's critical to the overall Python experience.
But it's also just scoped out of being our job, which is why, you know, we don't hold up releases based on packaging.
And to get packaging features into the core runtime is it just feels like a huge amount of work to do because it's got to overcome that.
This is so important to the core runtime, you know, to the reference interpreter that it's got to be in there, even though it's a packaging thing.
So it's challenging, but there's definitely those of us who want to make it happen.
And one of the benefits of being outside of the language is that it can move faster.
Python has an annual release cycle compared to, to draw an analogy, the Rust plus cargo story of six weeks.
And also not having this be in the core language makes it possible for alternative platforms and implementations that don't exist, that CPython does not care about today, to support those things.
Wasm, which is a T3 support, PEP 11 for anyone who cares about where that word comes from.
Pryodive exists.
It runs things.
CPython compiles on Wasm and it runs things.
The packaging story for Python in the browser is going to be very different.
The development workflow of Python in the browser is going to be very different.
And if you try to shunt poetry and pip or those specific tools as differently shaped into those workflows, that's just not going to work.
And you also don't want to rebuild that avenue of innovation using these tools.
Or that's one of the pieces that is sort of a symptom of success or a problem of success, which is Hatch, Poetry, PDM, all of these exist.
Because the other problems have been solved well enough.
And they've been solved well enough that these are now the main main points.
They're innovating in this space.
And there's other aspects of Python getting innovated on in terms of where it runs, in terms of how you interact with it even.
And as long as we don't stifle those, we're doing fine.
And that's a really good point about it not being in the core distribution as well.
Like if the ability to install packages was considered a core feature of the runtime, we wouldn't be able to release the runtime for a new platform until we'd figured that out.
Because that would block the release.
Because we'd have to say Python is incomplete until it has a complete packaging story on this brand new platform.
So because that is separated, we can release Python.
And so we have WASM releases of the CPython runtime because packaging is not part of that.
And so we don't have to wait for that to come up.
And yeah, because it's independent, Anaconda can come along and build PyScript and build packaging around the runtime because it doesn't have to be tightly integrated into it.
So there's big advantages.
Like there's a reason we pulled distri-tools out of the core library because it was restricting things.
And so it opens up more things, but it does put more responsibility on distributors, essentially, to build a distribution of Python that includes the workflow tools, the packaging tools, the indexes, the repositories, whatever they need to give users of that distribution a good experience.
And ultimately, a lot of this comes down to our distributions from Python.org have a very, very basic story for this.
Like we have pip.
That's basically our entire story.
Linux distros have their own story, which again, is they keep a very narrow focus on what they want to care about.
And users want things outside of that.
Even condo users, very kind of narrow focus to what's in those repositories.
And when you try and go outside of that, then things start breaking down just the same as all the distributions do.
So it's got pluses and minuses.
Python gets into places where it otherwise couldn't if packaging was a core feature of the runtime.
But it does mean that packaging is determined by the distribution and not by the core team and not even by the core maintainers of the kind of satellite projects that are really, really close to the core runtime.
Because setup tools can't determine how a WASM build is going to work because they're not controlling that distribution.
So there's a separation of roles that is not really clear, even to most of us who are involved, if I'm honest, that we all have different jobs to do.
And someone has to pull it all together.
And unfortunately, a lot of the time, it's the end user has to connect the dots.
Well, I think, guys, we are out of time, I would say.
Although not out of discussion points, for sure.
This could just go on and on.
Super interesting conversation.
It's really great to see it getting this focus.
But yeah, it's going to be interesting to see where it goes.
It's a challenge.
But, Arjan, I really like your idea.
It's that we're going to rise to it.
We've now come, we've solved the hard enough problems now that this new thing is a problem.
Ofak, go ahead.
I have one quick question because I'm sure listeners would be curious, too.
What do we think the next steps either are or should be for this?
I know we split off into different discussions and we're trying to research the feedback that we got.
But what do we think the next steps are?
Or is that just the next step, just trying to understand what users want more?
I don't think we know yet.
Yeah, I mean, I've written far too many posts on where I think we've got to go next.
But I do think we still have to, as Prajian mentioned earlier, level set.
There's a lot of people involved.
We all have different backgrounds, different expectations, different experiences.
And we just need to talk and figure that out.
And it's the kind of thing that would be ideal for us all to fly to some remote island somewhere for a week and just hash it all out in person.
That's unfortunately not going to happen.
So long discourse threads.
We're not leaving Hawaii until we solve this.
We've got to stay here.
I'm okay with that.
I will do it.
Three months later, we're still there.
Yeah.
Absolutely.
All right.
Well, you all, thank you so much for being here.
Thanks for taking the time and participating in this first, the original discussion.
And then this here as well.
I think it's going to highlight a lot of interesting and unseen aspects for people.
But a word, listeners out there, they want to get maybe their feedback in.
We saw some folks in the audience asking how they take the survey.
The survey is closed.
I'll give you a chance to sort of say like, what next for people out there listening?
Steve, we'll go around the circle again.
You're the top of it.
Go first.
If you're still on Twitter, then you can mention me in a tweet at Zuba.
I do read those and I do collect a lot of kind of random information and ideas out of there.
Otherwise, discourse and start a discussion.
And don't be surprised if we point you at an existing one and say we've done this one to death already.
So I'm always happy to hear more.
And I guess just be aware that we do get very overloaded.
Sure.
Paul?
Yeah, I think that's probably about the situation.
Again, I'm not very active on social media.
You can probably ping me on Twitter or Mastodon and I might notice.
Certainly get involved.
I can't promise.
Certainly get involved on Discord.
I think a lot of people are put off joining the conversations because it feels quite a hostile environment.
There's a lot of, like Steve said, we've seen that before.
We do want new perspectives.
We do want people offering ideas.
And it's hard.
It's hard to speak up because there's so much history that people will assume you know and you won't.
But please do, you know, come with half-baked ideas.
We'll maybe tell you how to bake them.
We'll maybe tell you we've already covered them.
But we won't ignore them.
We'll see them.
And even if it looks like we're not picking up on things that you think are really important, they'll get in the pot.
We will be aware of them.
And that's the main thing.
What we want more than anything is to be aware of what people think.
Yep.
Effect?
Yeah, I agree with what's been said.
I'm always on the discourse forums, reading feedback.
And if any Twitter threads gain popularity, I think it's important to realize most people that work on this are volunteers at the end of the day.
So we might not have much time to iterate as fast as people want.
But we are trying our best, for sure.
Excellent.
And there was that big sponsorship to make major progress on PyPI.org.
And maybe we'll see something like that at some point.
Pradyan, you get the final word here.
That's literally what I was going to say.
Invest in Python, folks.
If you work somewhere that uses Python, tell them to invest in the language.
And part of why we're having these discussions is because the role that initiated the user service is a sponsored role from Bloomberg.
And these sorts of investments into the ecosystem are vital to sort of make things keep working.
Because there's only software we can go with a bunch of people doing this in their evenings.
When they're, you know, slightly sort of bored and kind of want to keep themselves busy.
And these tough problems are not going to solve themselves because someone had half an hour in their evening or an hour in their evening.
Yep.
All right.
Good point.
And thank you all for being here.
Thanks very much.
Thanks, Michael.
Bye.
This has been another episode of Talk Python to Me.
Thank you to our sponsors.
Be sure to check out what they're offering.
It really helps support the show.
Join Cox Automotive and use your technical skills
to transform the way the world buys,
sells, and owns cars.
Find an exciting position that's right for you
at talkpython.fm/cox.
Take some stress out of your life.
Get notified immediately about errors
and performance issues in your web
or mobile applications with Sentry.
Just visit talkpython.fm/sentry
and get started for free.
And be sure to use the promo code talkpython,
all one word.
Want to level up your Python?
We have one of the largest catalogs
of Python video courses over at Talk Python.
Our content ranges from true beginners
to deeply advanced topics like memory and async.
And best of all, there's not a subscription in sight.
Check it out for yourself at training.talkpython.fm.
Be sure to subscribe to the show,
open your favorite podcast app,
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.
We're live streaming most of our recordings these days.
If you want to be part of the show
and have your comments featured on the air,
be sure to subscribe to our YouTube channel
at talkpython.fm/youtube.
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.
Thank you.