If you run into a problem with some API or Python code, what do you do to solve it?
Well, personally, I throw a few keywords into Google, sometimes before even checking the full
docs. It works great. But why does it work so well? Because invariably, an excellent conversation
and answer from Stack Overflow comes back as the top result, and it's usually just what I needed.
This week, you'll meet Martin Peters, one of the top Python contributors at Stack Overflow,
with over 16,500 questions answered and a reputation of over half a million.
This is Talk Python to Me, episode 86, recorded November 2nd, 2016.
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 @mkennedy. Keep up with the show and listen to past episodes at talkpython.fm,
and follow the show on Twitter via at talkpython. This episode has been sponsored by Rollbar and
GoCD. Thank them both for supporting the podcast by checking out what they're offering during their
segments. Martin, welcome to Talk Python. Hi there. This is exciting. Yeah, it's an honor to have you
here. You've done some really amazing work in the Python space on Stack Overflow, and we're going to
spend a lot of time talking about what you've done there, what your experiences were, but also kind of a
survey. Some really cool questions that you've pulled out for us to talk about that are representative
of good work and basically the Python community at Stack Overflow. But of course, before we get to
any of that, let's start with your story. How did you get into Python and programming? I started
programming quite early on. My father was a computer engineer. He fixed computers the way you fix a bike.
You find the part that breaks and solder a new one in back in the 70s. So in the 80s, I finally got my own
computer. I was given a MSX. And I basically haven't looked back since. Python. I started Python in 1999, I think,
when I was a web developer and I found a new platform called Zope. It lets you think of web pages as components
and as objects, which was interesting. And that called me into Python at the same time. My first project, I gave a time estimate
and beat my own time estimate, which blew away my manager because that never happened before. I always go over time.
That's all engineers do. And I haven't... That was my start with Python. It really was a love at first sight, I think.
Yeah, that's great. And what kind of project was that? That Zope project?
It was for a befriended company that was doing software on the web. And when you sell software on the web, you need a web shop.
So I built a web shop. I see. And because their software was already built in Python, it was very easy to incorporate their license generator into it too.
Oh, of course. Yeah. So they were selling Python software. You needed to run their license thing. It's just like, yeah, we'll just, you know, import that right here.
Just plug it in?
Yeah, yeah. Beautiful. That's great that it was quick and easy. But I think building e-commerce sites today, quite a bit easier than it was back in 1999.
What do you think? Have you built one recently?
I tend to stay away from shop. I've mostly done, in my career, I've mostly done content management.
So I think an intranet website where everybody has to be able to give their input as to what the company is doing or whatever. Share between teams, that kind of stuff.
All right. So mostly content management stuff, which is really, really valuable and helpful. What do you do today? You work at Facebook, right?
Today I work at Facebook and I do very different things. I don't so much work on the website anymore. As you know, Facebook does use PHP for that. Strange language.
I work on the backend side, on the source control side where I hack on Mercurial, an open source project that lets you do development distributed source control.
Oh, that's cool. Yeah. So Mercurial is kind of a cousin to Git, similar type of source control. What's Mercurial written in?
Mercurial is written in Python.
Interesting.
Mercurial is a Python project. And because it's a Python project, we were able to make it scale. So Facebook, everything is turned to 11. Everything is crazy.
Everything is just over the top high numbers and skills over the chart. And to be able to follow all the developers and all the changes they make every day, we couldn't actually make Git scale there. We couldn't make Git follow. And Mercurial did follow.
So we can, because Mercurial is so written in Python and highly extensible and highly tweakable, we can make it work at the crazy levels that Facebook is at.
That's really, I'm sure that's so exciting to work at Facebook.
Absolutely. It's a great place to be.
Do you work remote or is there a place there in Cambridge?
I work in London. So I commute four days a week up to London to work and one day a week I stay at home.
How much source code does Facebook have? Is it like, so when you talk about scaling it, is it the number of people using the system? Is it the amount of data? What's the scale look like?
It's everything. So we put everything into one monorepo. Repo means that we try and put everything into one place, one repository, so that you can facilitate all the sharing and moving. And that really helps speed things up.
But at the same time, you can easily come into the file counts of six figures. So trying to get a full check out of that is not always the best thing you want to do.
So we have issues with the number of files, the number of directories, the number of commits each day, the number of developers that work on it. All those things play.
Yeah, I can imagine that. Wow. Yeah. And Google also does this monorepo thing.
This is a really interesting idea to me when you have that many files. Have you open sourced any of these tweaks or anything written about them?
Lots of this stuff is open sourced. So Facebook has a repository with their own extensions in there. They are not perhaps immediately something you can use, but there is a lot of inspiration there.
We also contribute straight back to the Mercurial project itself. Until recently, the founder of Mercurial, Matt McEll, worked at Facebook. He recently decided that after 11 years of Mercurial work, he wanted to do something different. So he moved on to other things. And the Mercurial project is now trying to make its way without him.
Wow. Yeah. So you had the guy there to help you build this up. That's really interesting. Let's talk about Stack Overflow. Maybe tell the world what Stack Overflow is. The one person who doesn't know it.
Stack Overflow is a site for programmers. And the goal here is to help programmers find answers to their common problems. It was born from frustration with forums. You know, the general forum where someone says that they had a problem with this code and can someone help them and 20 people pipe in, but that they have the problem too and they don't know the solution. And then maybe on page 15, someone has got the solution.
And then it disappears into a huge pile of posts about different things and you never find it back again. Stack Overflow is very much aimed at trying to surface the question and the answers. So you have just a question.
And people, they use gamification to get the best answers on the top. So the general idea is that people vote. This was a question that is worth, that is well asked, that is complete. And these are the answers. And this answer is the best because that gets the most votes on it. That's the idea is that you get an encyclopedia of knowledge, of programming knowledge.
And they, you know, Jeff Atwood and Joel Spolsky, the two founders, they have nailed that in some special way, right?
They found a secret sauce.
They found, they definitely found a secret sauce and it's working really, really well. Like pretty much any programming question you have, if it has technical detail to it, there's probably a Stack Overflow result in the top five Google results.
Exactly. For the most common programming problems, you will find a solution there.
Yeah. And it's not just, well, you should put this curly brace here or whatever. It's also, it's much deeper than that, right? I think, I think there's a lot of really interesting questions as we'll see.
Absolutely. Absolutely. There's such a wide range of things that answer there, provided you stay on topic, which is sometimes a little harder.
Yeah, it can be. But yeah, it's, and they're very, very much careful about making sure things stay on target and focused and don't rant and basically become the forum that they're trying to escape from.
So let's start.
Exactly.
Yeah. So let's start with what makes a good question on Stack Overflow. So I guess before you answer that, tell us, I was looking at your, your user profile and there's some pretty astounding statistics there.
So for people who know you have about 500,000, a little over 500,000 for reputation, but you have 16,000 plus answers. And it says you've reached 22.9 million people. That's really amazing.
The numbers, they keep on growing because I like answering. I like finding solutions to problems. It's, it is kind of addictive. It is addictive with the fact that the feedback that you get and the, the, you learn so much yourself from this.
I love finding the key to the problem. So if someone has a particular view on the problem, they have a certain idea about how things should work or not work. And they clearly don't understand something. And I love finding the key that helps them suddenly see, oh, that's why this is how it works. So I'd prefer not just to give you the solution. I also prefer to tell you why.
Yeah. I noticed that from your answers. Yeah.
In doing that, you learn yourself whether or not, you know why. And that helps me grow as a programmer as well.
Yeah. I think that's a really good point because it's one thing to say, this code doesn't run as I expected. You could say, well, change it to this and it would. It's another to say, well, the reason your code doesn't work is if you really look inside, like say the CPython interpreter, it's doing this. And when it does that, here's what it means. And so here's how you fix it. Like that, that both enriches the person's understanding, but yours as well, like you say.
Exactly. I get to learn and apply it elsewhere.
I can use this in my own daily life. My own work is informed by what I learned from answering on Stack Overflow.
Yeah, absolutely. I'm sure it is. I'm sure it is. Let's start with what makes a good question on Stack Overflow.
So Stack Overflow is very strict about what it accepts for questions. Over the years, we've learned certain things don't work. So certain things are not on the topic. Stay away from those certain things, like asking what is the best web framework?
What is the best is very subjective and it's very hard to answer without a lot more detail about what you're doing. Most people don't give that detail. And what then also happens is that the spammers come along, the people that have something to sell and they say, ours is the best.
So those kinds of things are off topic. The same thing for opinion-based things. And we don't want to go on. We don't want to end up writing books either.
So if you want to know about the best practices for using object-oriented programming and when to use one technique or another technique, that would rapidly be closed as too broad.
Now, once you narrow it down to very specific programming problems, then you already start being on topic.
And then what you definitely need to do is, first of all, realize that these questions are not just for you. We want them to be there for everybody. So someone else coming Googling later on, need to be able to recognize that they have the same problem.
And the other thing is that if you want answers, you need to help the people that answer you. So you want to show the context of research that you've done.
And you want to narrow down your program to the essentials. So if you come in and say, I have this XML document that I want to parse and get this information out and write it to a file, but I want to transform this information this way and that way.
How do I do this? You're going to end up disappointed.
Yeah. And the XML file is like a thousand lines long with all sorts of complicated stuff. And they haven't focused in on just the essence of the problem. They're basically like, solve this problem for me, right?
Exactly. So solve this problem for me. What you can do at such a point is you need to break this down into separate issues. Perhaps you already succeeded in loading the XML file and parsing it. You've already maybe made choices there. Tell us about those.
So now you've narrowed it down to perhaps only finding specific information in that file. Leave out the part where you're going to transform it and write it to something else. Those are separate problems. Those are separate steps.
And once you narrowed it down to one of these steps and show us what you put in there, what you expected to come out and what have it instead with all the error message and all the full traceback and everything that you can, that you see, then we can see it too.
And often you will come to a very quick answer.
Or it might be, again, I cannot emphasize this enough. You have to have done your research because it could be that the question was already asked before and answered before and your question will be closer to duplicates.
Yeah. So Stack Overflow is actually pretty good at helping with you find answers as you're kind of ignoring the fact that they might exist. I guess is the way to think of it.
We don't hate duplicates either. We don't dislike duplicates. The internet is, of course, very impersonal. You can't see the other person's smile or feel any warmth. So people often see this as a personal putting their question down thing.
And duplicates, sometimes people actually go, I'm sorry, I asked the duplicates. And to that I say, it's all right. Duplicates happen. You can't always know exactly what you're searching for. We can help with that.
And duplicates actually are valuable to Stack Overflow as well because what happens is that you now added more keywords for people to search on.
So when you created the duplicate, you asked the question. It was well asked, but it was a duplicate. Google still has indexed your question.
And when someone clicks on it on Google, we actually redirect new visitors straight to the canonical question that you were a duplicate of.
So at that moment, you have helped someone else find the same solution.
Oh, that's interesting. I didn't really think of it that way.
So the research part is really important. I suspect it really affects the way that you feel about answering the question.
If like somebody has just put zero effort or what appears to be zero effort into finding their solution and they're just like, I don't know, let's put it on Stack Overflow, see if somebody will do this for me.
Probably your willingness to give a good solid answer goes down, right?
There's a certain type, certain classes of questions that we've seen so many times now, so often asked, and there's so many times that there's a duplicate, these common errors, that some people may lose patience a little bit.
And then you get, haven't you done your research?
You could have found this in the first five results on Google.
Right. I took your title.
I put it into Google.
And here's the Stack Overflow answer that actually has 10 answers and 100 upvotes and whatnot.
Exactly.
Interesting.
So it is the same kind of thing.
I think there was a funny video online, what if Google was an actual person, where you see someone in an office and people come in and ask, how is baby formed to this person's face?
The person behind the desk being a comedian does a great job of looking frustrated or can't ask this question 100 times already.
Yeah, exactly.
Nice.
Okay.
So I think everyone's got a good sense of more or less what makes a good question.
Let's talk about some of the ones that you found that are noteworthy or whatever.
First of all, how many Python questions are on Stack Overflow?
Do you know?
Oh, if I look it up very quickly, it's about 650,000.
650,000.
650,000 questions today that have been tagged with Python.
There can be more.
There are several version-specific sub-tags, so Python 2.7 or Python 3.5.
And not everybody uses the main tag when they ask about a specific version.
Right.
It might be just tagged Django, but it would also count as Python.
There might just be Django-specific library questions, so Django, Flask, or Pandas, or NumPy, those kinds of things.
They're all Python questions, too, but they might like the tag.
So there might be more.
All right.
There probably are.
Yeah, it's probably a subset.
Okay, cool.
So you've, out of the 650,000-plus questions, chose a few that are really good.
And you said that some of the questions that are really interesting are these what questions.
W-A-T.
I think W-A-T.
This comes from a talk by a man named Gary Bernard, who did a very short and very funny talk about wah moments.
He goes, wah, completely memes.
Those moments where you go, it really shouldn't be doing that.
That is such a crazy response to the code.
Yeah.
Usually it is.
It's bugs or very obscure corner cases of the language.
They are, for me personally, the most interesting ones because they definitely will cover areas that I know nothing about.
Or very little about it.
If they make me go wah, then it's definitely something interesting.
Yeah, absolutely.
And depending on the language you're working with, there's more or there's fewer.
Like the example that Gary chose was JavaScript, which is full of wonderful watts.
Exactly.
Python, on the whole, is a very, very low watt count.
But there are a few, and usually they are due to bugs.
So Python is a very consistent language.
The developers do an awesome job of making sure that Python is a consistent and predictable language, unlike JavaScript or even few Ruby examples as well.
But there are a few of those.
Recently, very recently, I think last week, there was one question that was asked where someone built a set contains unique elements.
But if they built a set from a list, they got a different result than when they built a set from a set literal.
So they had multiple elements in it.
And they listed the elements in the same order.
But if you used a set literal, they got a different result from building a list first and then passing that to the set callable.
That should not happen.
It shouldn't.
So if you say set, open parenthesis, and you pass an iterable thing, like a list or something, you get one result.
If you say curly brace, thing, comma, thing, comma, thing, comma, thing, close curly brace, and you put the same things in that you pass to your set initializer, you actually get different sets.
With the properly constructed inputs.
So at that moment, I definitely go, that shouldn't happen.
That is weird.
I'm intrigued.
I'm hooked.
And the next hour is going to be spent figuring out what's going on.
Where did it come from?
Why?
In this case, it was a bug.
It was a bug.
Okay.
And I'm looking at your answer here.
And of course, everybody who's listening, all these questions and answers will be added as links in the show notes.
So I'm looking at your answer here, and you're like, all right, so here I'm trying a few things, and we're trying to understand it.
And all right, let's just open up the disk module and do a straight disassembly on this thing.
Yeah, because at that point, you're going to have to dig in, what is the Python interpreter doing?
So you need the bytecode, and the bytecode is built from the source code, drives the interpreter.
And then you can start looking at the interpreter source code and see what is going on.
And for me, it was actually hard to figure out what was going on because I looked at the most recent version of Python from source control, so from the Mercurial repository.
And the bug had been fixed very recently as well.
So you used, if you do this with a release version of Python, you will not see the bug.
You will see the bug.
If you actually look at the source code as it is today, you won't see the bug.
I see.
And did you go to the source code to try to understand it?
Like, if I can do it?
I went to the source code.
It looks to me, my hypothesis is that the set literal is parsing these things in the wrong direction, in the wrong order.
That it's doing this in the wrong order.
But in the source code, I could see that it was parsing it in the right order.
So at that moment, I'm trying to figure out what is going on.
I could reproduce the issue.
It clearly wasn't matching what the code was.
So I actually went to search for issues in the bug tracker, found it, and then quickly realized that I was looking at a fixed version of the code because it already had been fixed.
So what was happening is that for all currently released Python versions, if you use a set literal, the stack is each element in that literal is pushed onto the stack.
And then the stack is taken in reverse to build the set.
So you always get the items from last to first added to the set.
Now, a set tests for equality.
So if two objects are test equal, even though they look different to you as a developer and there are different types, they still say that they are equal, then the first one in the set will win and will stay in the set.
And the other ones are rejected.
They were not added.
So in this specific case, someone was using zero and then the complex number zero, so zero j, and the instance of the decimal class from the decimal module, decimal zero.
And because the decimal module in Python 2 doesn't support equality tests with complex numbers, only with integers, it would test equal against zero but not against complex zero.
And so depending on the order in which they go in there, it would, yeah, change it.
Accept one or the other as being equal to what's already in there and rejected, and therefore you get different results.
Yeah.
Wow.
These are definitely corner cases.
These are obscure stuff, and most people won't come across these.
But that's the kind of question that I personally enjoy.
Well, one, really interesting to think about why that would even be possible and what's happening.
But also, you actually found a bug or the person found a bug, and you verified the bug, I guess.
In this case, I confirmed the bug.
Yes.
Exactly, exactly.
How often has that happened?
It doesn't happen that often.
And also for packages, there are bugs and corner cases.
Python is a pretty solid piece of software.
Usually, when I do find the bugs, they are usually very minor.
There might be documentation bugs, or one of the modules in the standard library might have some unexpected behavior that could be improved.
The fundamental issue, like the order of set literals being processed, that's pretty rare.
Yeah, I suspect most of the bugs that are found are up above the standard library.
They're in some external package or something like that, right?
Exactly.
So usually, if far fewer people look at it, it might be a different project that has a different standard for testing.
And so, more likely to find them there than I would find them in Core Python.
Yeah, absolutely.
Absolutely.
This portion of Talk Python to Me has been brought to you by Rollbar.
One of the frustrating things about being a developer is dealing with errors.
Ah, relying on users to report errors, digging through log files trying to debug issues, or a million alerts just flooding your inbox and ruining your day.
With Rollbar's full-stack error monitoring, you'll get the context, insights, and control that you need to find and fix bugs faster.
It's easy to install.
You can start tracking production errors and deployments in eight minutes or even less.
Rollbar works with all the major languages and frameworks, including the Python ones, such as Django, Flask, Pyramid, as well as Ruby, JavaScript, Node, iOS, and Android.
You could integrate Rollbar into your existing workflow, send error alerts to Slack or HipChat,
or even automatically create issues in Jira, Pivotal Tracker, and a whole bunch more.
Rollbar has put together a special offer for Talk Python to Me listeners.
Visit rollbar.com slash Talk Python to Me, sign up, and get the bootstrap plan free for 90 days.
That's 300,000 errors tracked all for free.
But hey, just between you and me, I really hope you don't encounter that many errors.
Loved by developers at awesome companies like Heroku, Twilio, Kayak, Instacart, Zendesk, Twitch, and more.
Give Rollbar a try today.
Go to rollbar.com slash Talk Python to Me.
The next one that you said was really interesting, and I agree, is it's so simple.
It's like eight or nine words, the question, but it has 3,200 upvotes.
And the question is, what is a metaclass in Python, and what do you use them for?
So this is, I think, is an example of a really awesome answer.
So I'm not talking about the one that's marked as accepted, but the one below it that has the most upvotes.
This is one user that has learned that for certain subjects, it is worth it to write an essay, to write a full answer.
And his name is Isetus, and his answer for metaclasses is absolutely epic.
This is why we have Stack Overflow.
This is what needs to flow to the top.
Metaclasses are an unfamiliar concept to most people.
Metaclasses are the type that creates classes.
So classes are a factory, a thing that you use to make instances.
But what makes classes?
Now, that's a metaclass.
Metaclass can produce a class.
It can be a mind-boggling and hard-to-grasp concept.
But Isetus does an absolute marvelous job of explaining this anyway.
So he starts with explaining what classes are, what objects are, and this goes deeper and deeper and deeper and includes not only what metaclasses are and how they work, but also includes excellent advice as to when you want to use them, which usually is not.
But when you do need them, when you do need them, metaclasses are a very powerful concept.
And he does, I think, one of the best jobs of explaining that.
Yeah, it's like a little book chapter almost that he wrote.
I think it's like 15 pages, you know, based on my screen size or whatever.
That's pretty impressive.
And I really do think it's a great answer.
Yeah, metaclasses are definitely interesting and useful.
But I think we mostly consume them, right?
More than create them as average, everyday programmers.
Average, everyday programmers, you mostly consume them.
Most people don't know that they even exist.
This is something that frameworks use.
The Django framework or the WT forms framework use metaclasses heavily because they get to have access to all the attributes you just set on a class and transform them and manipulate them and make them do something magic.
Yeah, I was thinking of SQLAlchemy's declarative base.
Yeah, SQLAlchemy is very similar to that.
Again, it's a model where each of the fields defines something about the model that is a little bit more than just the object you just put in there.
So define a class that also models the columns in a table.
You usually want those attributes to behave differently in different contexts.
Like when you are creating a new instance or you are just putting stuff in from the database, that moment, that class has to behave differently.
And that complexity, it can be neatly encapsulated and hidden by using a metaclass.
Yeah, it's really, really wonderful.
Awesome.
Okay.
How about accepting, next question.
Accepting the user input until you get a valid response.
Yeah.
I picked that one because it's a very good example of, again, what the Python community around Stack Overflow does.
So Stack Overflow itself is a site, but next to that we have a chat site as well.
So there's a chat.stackoverflow.com where there's various different rooms where people, members of the community come together to hang out or to chat about all sorts of weird things and sometimes even about Python.
And there's a Python chat room.
And because people talk about and are connected to Stack Overflow, that room sees lots of patterns happening.
So questions that keep coming up, certain problems that keep coming up.
And there's sometimes a class of them.
Like using raw input or input in your Python program to get a response from a user.
Most homework starts with take an integer from the user and put it into something.
And that is something many new programmers fall over and keep stumbling into.
So this particular question was written by a member of the Python chat room together with an answer based on their experience helping people again and again and again with the same issues, the same related issues.
What do you do to validate that input?
What do you do when the user has got it wrong and you want to repeat it?
All the pitfalls all collected into one place and as a self-answer.
So this was both the question and the answer have been written by one person at the start and then refined later on by the members of the community.
Interesting.
So this one, they made the answer, their own answer, a community wiki.
Exactly.
I've seen that you can make an answer a community wiki or you can sort of keep it to yourself and you get reputation if you keep it to yourself and you don't on a community wiki.
You want to talk about that?
Exactly.
Yeah.
The community wiki is definitely aimed to be able to lower the bar of improving a post.
So in this case, the community definitely felt this is something we as a community want to do because it's pretty much needed and it's too scattered around the site.
And we don't want it to be owned by one person specific.
So you should feel more, you should feel freer to actually edit this and improve it.
That's why it's made a community wiki.
And the moment you actually then invite more people to edit it, then you don't no longer know who can earn more than other people if there's upvotes on this.
So that's completely taken away.
Yeah, that makes sense.
Also see that it's protected.
The question is protected.
What does that mean?
Yes.
That is just something, a trick we use as moderators.
But high rep users can do the same thing.
When a post like this becomes so very popular, what can happen is that lots and lots of new people, so people with low reputation come in and go,
my solution is unique.
My solution is unique.
And they don't have the experience to actually see that their solution is perhaps not that unique.
Or they say, I don't quite understand.
They don't quite understand yet how Stack Overflow works and they don't understand the answer.
So they might post in an answer below it another question where they request that someone explains how the whole thing works.
Well, answers are not questions.
So that is the wrong place to post this.
So a question like this can attract lots of those kinds of answers.
So if I have enough reputation that I can see not only the answers that are posted, which currently says 10 at the top, but most people can only see the first three, four, six posts.
So there's four more on that same page that have been posted before that are either someone not having understood that their solution is not unique and that they have basically repeated the same thing or explained it wrong.
Or are questions.
This one doesn't work.
How does it?
Yeah, interesting.
So what kind of powers do you get as you go up in reputation there?
Full disclosure, my reputation is like 2,000.
I've answered some questions.
I've asked some questions, but nowhere near that I would have any of the exposure to the stuff that you get.
There's quite a wide range of things that we can do.
Mostly what we like to see is that people start, when you start getting invested in Stack Overflow and you start gaining reputation, you get experience with how things work and we trust you more and more.
And at that moment we can rope you in to help.
So a lot of these, once you get past the initial kind of points where you can start voting and start adding comments, which before to keep spammers out, don't give you to you immediately.
You start getting into what we call community moderation privileges.
So you can start helping the electric community moderators keep the site clean.
Most of the site is kept clean by the community.
So you can start doing like, you're allowed to edit posts at 2,000 points.
We allow you to edit posts without review.
So you can go to any other posts and start fixing things.
If you see a typo, fine.
You have 2,000 points or more.
We trust you that you can make that change.
At some point you can start helping gardening the tags.
The tags could be marked as synonyms of one another, say.
The Python tag has got several synonyms.
Like Pythonic was not seen as something that needed a separate tag.
It's made a synonym of the Python tag.
At 2,500 points you can start helping with that.
And then you can start helping close posts or put them on hold.
And also reopen them again if you feel that it shouldn't be, stay closed.
Maybe it was improved and fixed.
So now you can reopen it again.
Tag wikis, the things that we keep a bit of documentation about each tag.
Is it called a tag wiki and that's that?
At some point you're allowed to edit those without review as well.
Et cetera, et cetera, all the way to 20,000 points.
And that's the highest amount of, oh no, sorry, 25,000 points.
It's the highest level that you can get to.
And we give you access to internal data, site statistics.
Because then we think you're so invested into this, you really want to know how well we're doing.
That's really cool.
Yeah, and you're a little bit past 25,000 these days.
So you've had those privileges for a while.
But that's really great.
I think I might be a little past this, yeah.
Exactly, like 400, I don't know, hundreds of thousands past that.
That's awesome.
So another question that you put up here has to do with creating type level variables
and trying to initialize one of them with a list comprehension from another or something like this, right?
Yeah.
This is one of those wah moments, again, where I learned such a lot about the Python programming language,
about how scopes interact, but also a little bit about how the Python developers definitely see the language as something living
and will make changes if that makes sense.
So in this case, this is a weird interaction between scopes for classes and functions and list comprehensions.
Now, normally when you have a function, that's a scope, and we have the global scope.
So we have a local and a global scope.
The things are simple.
You just have functions.
But as soon as you start nesting functions or you start using functions in classes, you introduce more scopes,
and you have to start figuring out how you access names that exist outside of the function.
So normally in a function, if you use a global, it is available because it can be found in the global namespace,
and that's part of the normal search.
But as soon as you start using classes, a class object is also a scope.
So the class definition of building your class object has a separate scope of names,
and different rules apply there.
Let's say you have a class that defines a class attribute, and then you define a method in that.
The class attribute is not a parent scope, and it's not available to the function in the class
because you normally would bind that function as a method, and then you work with an instance over the class,
and there might be multiple of these.
And therefore, you need to separate out the lifetime of the instance in the class,
and defining it.
So the names in a class scope are not normally available to the functions that you define inside of the class.
That comes later.
You can access those via the class object that has been created.
How does it play with list comprehensions, you ask?
Well, the Python developer started with seeing list comprehensions as very simple constructs,
no different than a for loop.
If you put the for loop in a function, all the names you use in that for loop,
including the target for the iteration.
So the for name in an iterable, each time you iterate through the for loop, the name that you've used for that gets assigned the next value.
And it's in the sequence.
That name lives in the same scope everything else lives in for that function.
So this is the local name.
So after your for loop is done, you see that local name, and you can still access it.
So for i in range 10, you'll make your loop run from 0 to 9.
At the end of it, i equals 9 is still available to the rest of the code.
List comprehensions were seen exactly the same.
Just a local thing in your scope.
So the for loop target of that is available.
The Python developers then next created generator expressions.
A generator expression is evaluated lazily.
So you can sort of see it as a function.
You first create it.
It is an object that will behave in a certain way, but only when you make it to later on.
So you deferred execution.
Right.
So if you want to try to, say, access the iteration variable in a generator, a generator expression,
it may have been created, but it may not have been created, depending on whether you've actually executed the generator, right?
Exactly.
So you actually, at that point, you have executed your generator.
So these variables don't even exist yet.
So generators were given a hidden function scope.
They behave just like functions.
Everything inside it is local to a new function, and that's hidden.
So that you can execute it just like a function.
And then the local variables are part of the generator object, like a function would be, and are cleaned up separately once a generator object is done.
And the Python developers, as they built this, then realized that this also really applies to list comprehension.
This comprehension and generator expressions are just basically the same thing, except one of them is immediately executed.
The other one is deferred.
So in Python 3, list comprehensions were given in scope 2.
Now, why is this important?
I always talked about how classes have a scope, and then the methods in the class can't access the class scope.
They will have to go for the class.
This applies to generator expressions and list comprehensions too.
Well, at least.
So they do it in Python 3.
In Python 2, where list comprehensions are still sort of simple things without their own scope, that behaves differently.
So there was a discrepancy there between Python 2 and Python 3 where things changed.
And most of the time, people write simple classes and write class attributes and write their methods.
And they don't think about trying to access things that they just defined for class attributes.
But when you're writing, say, a list comprehension to make an attribute of your class, it's certainly very surprising that you can't access anything else you already defined for that class.
Because it's a scope that is not available to you.
I think this is a really interesting example of understanding why this was changed.
Do you know if the Python core developers are paying attention to Stack Overflow and possibly making changes to the next version of Python based on things that appear there?
Or does it have to bubble up farther through some other channel?
Stack Overflow is one of the inputs, one of the sources where you see there's a long tradition of the Python developers looking at how Python is used.
There's a longstanding mailing list called Python Tutors where you can ask questions and people will answer those.
It's like a mailing list forum that answers Python beginner questions.
And I have seen plenty of evidence that that source over the years has already informed the core developers on how they do things, that they see these common problems.
A lot of the core developers are themselves consultants that teach Python, teachers or consultants that help companies use Python better.
And they use those inputs too.
And Stack Overflow is just another input in that way.
So I definitely think that they're using it.
I know that several of the Python core developers are regularly answering on Stack Overflow as well.
So they definitely get that input too.
Yeah, that's great.
I'm sure they are.
But this type of question seems like it can really clearly pull out some of those decisions.
And maybe if it came earlier, before that was changed, maybe highlight some of the problems.
Exactly.
This portion of Talk Python to Me is brought to you by GoCD from ThoughtWorks.
GoCD is the on-premise, open-source, continuous delivery server.
With GoCD's comprehensive pipeline model, you can model complex workflows for multiple teams with ease.
And GoCD's value stream map lets you track changes from commit to deployment at a glance.
GoCD's real power is in the visibility it provides over your end-to-end workflow.
You get complete control of and visibility into your deployments across multiple teams.
Say goodbye to release day panic and hello to consistent, predictable deliveries.
Commercial support and enterprise add-ons, including disaster recovery, are available.
To learn more about GoCD, visit talkpython.fm/gocd for a free download.
That's talkpython.fm/gocd.
Check them out.
It helps support the show.
Speaking of newer versions of Python, the next question is, why is Python 3's super function magic or super method?
Yeah, but this definitely came also from feedback on how things work and don't work for Python.
So the super function, I'm going to introduce it real quick, is the way that you can access methods on parent classes.
So when you override in a subclass a method and you still want to use the functionality of the original, you can use super to access methods on classes in your method resolution order.
So the linearization of all your base classes.
The linearization means that we put all your classes in a specific order and that order is always fixed and predictable.
So when you create a subclass and you want to put an under-under init method in it and you want to initialize a few more attributes that your more specialized subclass uses,
but you still want to use the original init method that you use super to get there.
Now, the way Python inheritance works, I already mentioned the method resolution order.
You want to be able to find which class is next in line so you can call its init methods.
When you're using multiple inheritance and diamond patterns, it's not always that clear, but Python solves that for you.
And so you don't have to worry about it if you use the super method because it will take care of finding the next class for you.
Right, there's a predictable, well-known order in which it will search for the thing you're trying to call on the super, yeah.
Exactly.
So we call it the method resolution order.
That's the order in which the next one will come about.
But for a super to be able to know where it is, because your class could be subclass and subclass and subclass further,
for it to know where on the method resolution order for the current object,
because that matters, it's not just the current class, it's for the current instance that may use a subclass,
it has to know where on that line you are at this point, this method.
So if you have a foo.unit method and you want to call the next one in line,
you need to tell super, I am foo.
So you can search past that point.
You can find foo in the line of other classes in the whole method resolution order
and find the next one in line.
So just like your current type, the type of object you are, isn't enough because you could have called down into some intermediate level of inheritance,
which is then calling super or something that can get really complicated, right?
Exactly.
Foo could have been subclassed by bar and bar could have called foo.unit via the super trick.
And then self, the type of self is bar and therefore you can't use that.
You can't say type of self is bar and therefore I'm going to start searching from there.
Because you're no longer in the bar class, you're now in the foo class.
So you explicitly in Python 2 have to tell it, start searching here.
That's the first argument is the current class.
Second argument is the current instance.
So you can find the MRO from that.
That means you constantly are repeating yourself.
So you're writing a class foo.
And then in all the methods that need to use super, you keep saying, this is class foo.
This is class foo.
So that violates the do not repeat yourself principle, the drive principle.
Then there are other tricks in Python, like using a class decorator or simply storing your class in a different name.
Classes are objects, so you can use a new variable, a new global variable, call it spam and assign foo to it.
And then you can call spam and suddenly it is called spam.
So you cannot also at that moment guarantee that the old name still exists.
So what might happen if you have a class foo and you use super foo everywhere in there?
It may be that at the moment that you call foo on the internet, the class is no longer available under the name foo.
It might be called something different or something else might have been assigned to foo.
So now you have a problem because when you created the class, it was called one thing and now it's called something else and the names no longer match.
And then you have problems.
Yeah, absolutely.
So super, super, super, super tied to the class existing on underneath the same name.
And you have to constantly repeat yourself.
So the Python developers tried full, long and hard as to how they were going to solve this.
How can they avoid having to repeat yourself?
And how can they avoid record, somehow record the current class on which you just define this method so that it is no longer depending on the run, on runtime circumstances where the class still is available in the same name.
And that's where Python 3 super comes from, where you no longer have to pass in anything anymore.
You call super without arguments.
And that moment, something magic happens.
And that magic, some people feel, goes against the grain of certain Python principles.
Like there should be obvious things happening.
That Python is very explicit about what it does.
As Tim Peters once said in a very famous little recorded Python philosophy, there should be one obvious way to do it.
And explicit is better than implicit.
Super in Python 3 is implicit.
When you don't pass in arguments, it implicitly finds its arguments.
So that's why people call this magic.
But the reason why they're doing it is to avoid having to repeat yourself.
There's a lot of extra things going on in the hood in that when you create a method in a class, then a closure is created specifically for it.
So it is as if the function has been defined in a context where the name under class is available in a parent context.
Basically, it means it captures its setup when it gets created.
And then it can't really be influenced from the outside.
It can no longer be influenced from the outside.
And you no longer have to repeat yourself and passing it in.
It was also a common source of problems, a common source of errors where people misunderstood what needs to be passed in.
I already said you explicitly have to call, name foo and not take the current type of self because that may no longer be foo.
There might be a subclass.
And at the time, I did a search on code search engines and found tens of thousands of errors of people passing in either self.
On their class or passing in type self, thinking that's good enough.
I don't have to repeat myself here and type foo again.
I'll just take it from self.
And that leads to problems because when you have a subclass that also uses super, you get an infinite loop.
Because then you say foo is subclass to bar, bar calls foo, and then foo passes in bar each time.
And therefore, you go back up in the circle and we keep calling the same thing.
Do you actually get a stack overflow exception?
You get an infinite recursion error.
Okay.
It protects you from stack overflow.
Yeah, good.
Nice.
All right.
So that is really cool.
And, you know, I think what's really interesting is as you, you know, as you mentioned in the beginning, but as we go through these, it's really clear how it's what you learn by going through this exercise of reading the question, the answer or answering it yourself.
It's not just what is the question, what is the answer, but there's so many additional things and techniques and practices that come through.
I think it's great.
I really learned to understand what the decimal due does and how that works and how the Python evaluation loop works purely from answering on stack overflow.
Yeah, I can see that.
All right.
So another one is about Python 3's range objects.
Really two questions and sort of relative to Python 2's, which just turns them into a list of the things, a list of the integers.
Yeah, so Python 2, you have range, which is just a function that produces a list of integers and x range, which is a separate object that models the sequence, but it's quite simple and it's quite limited.
Python 3, they renamed x range to range because you don't really need that as a function.
You can just call list on the range object and then get the same results.
So range in Python 3 is a separate sequence object.
And I love the object.
I think it's a great idea.
I wonder why it took so long to make this such a first class object and to make it something that is part of Python core the way range is now in Python 3.
Ranges are very lightweight.
You just tell it, this is the start, this is the end, and this is the step size, how we get from start to end.
And that's all it records.
It doesn't need to know all the numbers in between because you can very quickly just calculate those.
If you know that you start at 1 and you end at 10 and your step size is 2, then you know that 3 and 5 and 7 and 9 are all part of that sequence.
You can just calculate that, right?
It's just math.
So why would you have to keep that in memory?
So most people still don't realize that range objects are smart like that.
So you do see lots of questions about them.
These are two example questions about someone being surprised, so surprised that if you make the range really large, you think that if you start at 1 and you put the endpoint at 10 million, that's numbers, right?
The human mind will see that that's 10 million numbers in that object.
That must take a lot of memory.
That must be really slow to figure out whether or not the number 10 million and 1 is part of that range.
But it isn't.
It's just math.
It's very easy to calculate.
Yeah, and it gives you a good look inside it because the person asking the question says, well, I could write one with generators and yields and so on.
But it takes it forever.
And so your answer to it was basically, well, let's look at the actual implementation.
And it's not just something that generates a sequence but can be smarter.
Like it can implement dunder contains and get item and lend and all these different things that have actual.
It behaves just like other sequences, just like lists and tuples and strings.
You can ask for any of the elements at any point in that range, but it doesn't have to keep them up front.
It can calculate them as you need them.
Yeah, yeah, that's cool.
It's really, again, a really nice look inside of things.
And I guess the last example we want to look at is about the order or lack thereof for sets and dictionaries, which is slightly changing, right?
That's exactly what's happening.
For many beginners, it is surprising that collections like dictionaries and sets don't have a set order.
There's an implementation detail of how Python has implemented dictionaries.
And that comes from – it usually happens to people also new to programming.
So they don't just come to Python as new and as the first thing that – it's also usually the first thing that they come to as a programmer, to programming in the whole.
Because if you, for example, have done systems programming in C or C++, most people that come from that kind of bank account already realize this.
But to make a dictionary efficient, so to be able to map a key to a value, you want to be able to store this efficiently and quickly find things.
So once you start working on this, you realize that it looks like there's an order, but the dictionary can't promise any order because the order that the keys are put in is just a property of the storage medium that we put things in.
Because we are putting a bunch of keys into a much smaller space and then quickly being able to find if a key exists or not in such a table.
Because we base this on what we call the hash, the property of any of these keys to be reduced to a simple number.
Explaining that is surprisingly often needed.
Once people understand it, they can – oh, okay, right, fine.
And we can go to another type and we can point to things like the order dict that also exists in Python.
Or tell them that in Python 3.6, the implementation changed.
So now dictionaries actually do remember order just because someone found a more efficient way of building the same kind of data type.
So Python 3.6 makes dictionaries ordered, not because everybody wants them to be ordered, but because it was a more efficient way of storing information.
Python 3.6 makes dictionaries an order of magnitude smaller in certain cases.
And that's actually super important because that's in some sense the backing store for all instances of objects.
Exactly.
Yeah.
Exactly.
Lots and lots and lots and lots and lots and lots of stuff in Python uses dictionaries.
So you can end up with quite a number of those.
So making them smaller is a very good idea.
Yeah.
So this question is really like you need to understand data structures to understand what is happening here because it doesn't make sense.
Like, well, why wouldn't I just want it to have the order?
But of course, you know, at least the older implementations, you want it to be fast more than you want it to be other order.
Exactly.
And it also helped implement a few other new things in Python 3.6 like the keyword argument order can be important in certain cases or the class attribute definition order can be important in certain cases.
And they are now as a property of this new dictionary implementation also implemented.
So suddenly when you create a class, all your attributes are kept in the same order that you define them, which can help form building libraries, for example.
Yeah.
Currently, you have to do crazy tricks to make keep it order.
Yeah, absolutely.
Absolutely.
And MongoDB, for example, has its own dictionary type thing because it doesn't want to reorder and entirely rewrite big parts of stuff.
And there's a lot of areas where this order actually would be kind of nice to have.
So very cool.
So those were some great questions.
And I feel like I've really learned a lot.
I hope people have as well just hearing you talk about them.
But why – like this is a lot of work.
Why do you contribute so much time and energy to Stack Overflow?
I already mentioned that I learned a lot from this.
I didn't start Stack Overflow because I wanted to learn so much.
I started because I was part of the Plone management community.
And we discovered Stack Overflow early on as a good idea to support people that wanted to learn about Plone and wanted to use Plone and then sort of fell into answering Python questions as well.
But I've since heard in an interview with another Stack Overflow numinary and creator of the C# compiler, Eric Lippert once had an interview, I think, with Stack Overflow actually, giving his reasoning as to why he started with Stack Overflow.
And answering questions.
And that a manager actually told him that he should become an expert in certain things.
It would be helpful for him to become an expert in a certain subject.
And that the best method of becoming an expert in anything was to find a source of questions and start answering them.
Because then you really discover all the things you don't know yet and start learning those yourself to try and be able to answer these things.
And that really resonates with me.
That's really why I'm answering on Stack Overflow so much.
It's because it keeps teaching me new things.
It keeps pushing me into new directions and new areas of expertise that I didn't know I could do before.
Yeah, that makes a really…
I really enjoy that.
Yeah, that makes a lot of sense to me, your answer there.
About the expert especially.
I think one of the things that makes somebody an expert is not that they've sat down and done programming for five years or ten years or whatever.
It's really how you spend that five or ten years.
If you just do the same thing over and over and don't run into many challenges and don't force yourself to continue to dig deeper, then you're not that much more of an expert than what you learned in the beginning.
But it's more the challenges and the problems and the edge cases that have hit you.
And I feel like Stack Overflow is that concentrated.
Yes, and it is a constant source of new challenges.
And in that way, it can be sort of addictive as well.
So you have to be careful.
I'm sure.
So speaking of addictive, what if I was really convinced that 2,000 for my reputation was insufficient and I decided the next week I'm going to take eight hours a day and just start answering questions and asking questions and just going crazy?
Obviously, my reputation would go up, but would there be other effects?
Would people start contacting me for jobs?
Like, hey, I saw you're doing great on Stack Overflow.
And answer these questions.
Do you want to come work for us or things like that?
People have used my Stack Overflow presence as a reason to contact me.
But I think that's not really the norm.
So I'm also looking at this from the point of view of hiring people.
How would I use Stack Overflow?
If I see someone that has a better reputation of Stack Overflow, that it works just like a blog.
It gives me a great insight into how you think and how you work and how you look at code and how proficient you are in those things.
Because you have this body of things out there that we can look at.
Or just like open source work, open source projects that you did.
A Stack Overflow profile with a good body of answers can be a real asset to let potential employers know that you know your stuff.
That you know a thing or two about what you're talking about because you can actually demonstrate this.
Which can give you a huge advantage because a lot of times people applying for jobs can't demonstrate their skills.
Exactly.
So Stack Overflow is actually really building on top of this because they give you ability to develop your CV or developer stories they call it now on the site.
And that they actually have a nice site business or actually their main business next to it to get employers connected with those people that have filled in a profile there.
Right.
The whole Stack Overflow careers thing, right?
The whole Stack Overflow careers thing.
And that does give you a lot, can give you a lot of insight into people how they work and how they think and see code.
So up to a certain level, getting answers on Stack Overflow, provided you, of course, know your stuff a bit, can help you there.
If I see someone with my level of reputation, I would start asking, are they spending too much time there?
Will they actually do work for me or will they just come to work and answer Stack Overflow questions?
Interesting.
I said, keep people interested, right?
Yeah.
You would learn a lot, I think.
If you seek out questions, there is such a thing, it's the fastest gun in the West where someone already knows the answer, can type faster than you and gets the first answer in and then that gets upvoted.
So if you're in it for the reputation and the upvotes, you're going to have to wait a little while because you're going to probably be a little slower than the experienced hands, the people that can type out the answer quickly.
Sure.
But at the same time, at that moment, you can compare your answer to theirs and see, did I miss something?
Did I miss a detail?
Did I miss a trick?
Did I use something interesting out of the standard library that I didn't know about yet?
So next to that, you're having to figure out how I'm answering this.
Do I know the answer?
You also get to see how other people are answering.
So that's something different than you're trying to find the solution to a problem you have.
You are actually looking at new questions as they come in and see how other people are answering them at that moment.
It's a slightly different angle.
You get to see how other people think about their problem.
And you might learn a thing or two about that.
Okay.
Very interesting.
I probably won't take a week and go work on Stack Overflow, but it's interesting to think about what would happen if I did.
It is certainly an interesting thing you can do for half an hour when you're maybe waiting for the bus or something like that.
Yep.
Absolutely.
All right.
So let me ask you one final Stack Overflow question.
And I've seen a couple of articles lately that felt like Stack Overflow was unfriendly to beginners or to newcomers.
And you had an interesting thought on that.
There's two angles here.
First of all, there's often a mismatch of expectations what Stack Overflow is for.
Stack Overflow is often seen as a personal help desk, something you can quickly put a question on and they'll help me fix my problem.
And then get upset because their question might get put on hold or downvoted because they didn't meet the expectations of what Stack Overflow has, which is to build a knowledge base, to build a repository of good questions and even better answers that help future visitors.
So if you forgot to explain what inputs came out of it or what the full error message is or you show a clear lack of having actually done the research about how to solve your problem, then you might actually find Stack Overflow very disappointing.
And then there's the other thing is that people say that Stack Overflow is only for professionals and not for newcomers and for new people, newbies new to programming or new to our programming language.
Again, that's not true.
It's usually what happens at the same time is that people are new to asking questions and they don't know how to ask a good question.
And that then really fires back on them.
So, and then there's, of course, the fact that because we are trying to, Stack Overflow is so hugely popular, we get maybe a few thousand of such people come in every day and asking questions.
So the community, on the other hand, is running out of steam and running out of power to keep helping each and every one of those learn about Stack Overflow.
So a lot of people don't get the hand-holding that they might expect.
Well, I'm new to this site.
Why didn't you tell me?
Well, Stack Overflow tries to automate this, tries to give you the help up front.
You get a lot of information about how to ask a good question.
There's lots of information in the help center.
But when you have a programming problem and your homework is due tomorrow, not everybody will reach that.
And then they skip by that very quickly.
And then what they see is what...
Yeah.
I feel a huge difference based on whether or not the person is legitimately trying to solve the problem and needs help or if they're just being lazy.
You know?
I do want to avoid the term lazy.
It is often just a misunderstanding.
And a certain sense of urgency can...
Because you have this problem and you're so into this problem and trying to solve it that you can forget to see the larger picture around it.
It's not necessary that you're being lazy always.
Sometimes there are lazy people that do post their homework on the site or even their exam questions as they sit in the exam.
I have literally seen posts where that consists of nothing more than a photograph of a paper that's clearly taken underneath the desk.
No, no, this is not an exam.
This is a trial question.
But can you give it to me in the next 10 minutes?
I'm going to need that before 9 o'clock because I've got to turn this in.
I'm going to turn this in.
Some people are lazy but most people just don't understand what makes a good question and why Stack Overflow is there.
And that clash can lead to frustration.
Yeah.
So I think this conversation has definitely helped everyone who's listened to it understand what makes a good question and so on.
So hopefully we've done a small part to reduce the frustration on both sides, the people answering the questions, being frustrated with the unprepared homework folks coming in.
I guess we'll leave it there for Stack Overflow.
But, Martin, that was very, very interesting.
And I think reading through your answers and other people's answers and questions is definitely enlightening.
Thanks for the work on that.
That's cool.
Before I let you go, two final questions I'd always ask my guests.
First of all, favorite PyPI package?
What would you recommend to people out there that they might not know about?
This is one I discovered.
Someone else used it in an answer and I love it.
I have been using it ever since.
It's called FTFY or Fix This For Me, For You.
Fix This For You.
It is a library to fix Mojibaki or text encoding errors.
So if you ever try to make sense of UTF-8 encoding text decoded as Latin 1 and then re-encoded as something else,
the Fix This For You library, FTFY library, will do it for you.
It automatically detects when an encoding was misapplied and fixes it for you,
as well as some other common noise in incoming text.
I love this for content management.
I love it for handling badly decoded webpages, anything like that.
Fix This For You has saved my backside a couple of times already.
That's fantastic.
All right, favorite editor?
If you're going to write some Python code, what do you open up?
If I'm on a terminal, Vim.
And generally on my desktop, it's Sublime Text 3.
Nice.
Yeah, I was just using Sublime Text earlier.
I like it a lot.
All right, how about a final call to action?
What should people do to get more involved with Stack Overflow?
Common and try and answer stuff.
There are always niche tags that need more people answering.
Things like Python may be overflown with people that know their things.
But if you have a specific expertise in programming, there usually is a tag for you.
And finding more answers to these questions are always helpful.
All right, excellent.
Well, thank you for all the work you've done on Stack Overflow around Python.
It's really amazing.
And thanks for being on the show.
Great to talk to you.
Cool.
Great.
Thanks.
Bye.
This has been another episode of Talk Python to Me.
The guest today has been Martin Peters.
This episode has been sponsored by Rollbar and GoCD.
Thank you both for supporting the show.
Rollbar takes the pain out of errors.
They give you the context and insight you need to quickly locate and fix errors that might have gone unnoticed until your users complain, of course.
As Talk Python to Me listeners, track a ridiculous number of errors for free at rollbar.com slash Talk Python to Me.
GoCD is the on-premise, open-source, continuous delivery server.
Want to improve your deployment workflow but keep your code and builds in-house?
Check out GoCD at talkpython.fm/G-O-C-D and take control over your process.
Are you or a colleague trying to learn Python?
Have you tried books and videos that just left you bored by covering topics point by point?
Well, check out my online course, Python Jumpstart, by building 10 apps at talkpython.fm/course to experience a more engaging way to learn Python.
And if you're looking for something a little more advanced, try my Write Pythonic Code course at talkpython.fm/Pythonic.
You can find the links from this episode at talkpython.fm/episodes slash show slash 86.
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, Google Play feed at /play, and direct RSS feed at /rss on talkpython.fm.
Our theme music is Developers, Developers, Developers by Corey Smith, who goes by Smix.
Corey just recently started selling his tracks on iTunes.
So I recommend you check it out at talkpython.fm/music.
You can browse his tracks he has for sale on iTunes and listen to the full-length version of the theme song.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Smix, let's get out of here.
I'll see you next time.
Bye.