Brought to you by Michael and Brian - take a Talk Python course or get Brian's pytest book


Transcript #152: You have 35 million lines of Python 2, now what?

Return to episode page view on github
Recorded on Wednesday, Oct 9, 2019.

00:00 Hello and welcome to Python Bytes where we deliver Python news and headlines directly to your earbuds.

00:04 This is episode 152 recorded October 9th, 2019.

00:09 I'm Michael Kennedy.

00:10 And I'm Brian Okken.

00:10 And this episode is brought to you by DigitalOcean.

00:13 Check them out at pythonbytes.fm/digitalocean.

00:16 Get $50 credit for new users.

00:18 Now, we may have touched on this concept of legacy Python before, Brian.

00:22 Have we covered it?

00:23 Yeah, I think we have.

00:24 We definitely have.

00:25 So we know that there are companies out there that say it's really tricky for us to upgrade to Python 3 Because and sometimes that's because I don't know just they don't put the resources into it, right?

00:36 Like they would rather work on features rather than going back and rewriting old code to do the same thing But so it's not so old things like that other times it's because they have a ton of Python code and we're hearing more and more stories of these companies that have been like head in the sand waiting until the very very last minute to make those migrations and They're just like alright finally somebody is raised it to the level that like it has to be dealt with right?

01:03 Yeah well it turns out that banks use a lot of Python code as we know and I've heard of Bank of America using a ton of Code and having a lot of people working on some Python projects, but JP Morgan JP Morgan chase they use maybe even more they use a ton of Python So there's an article that's based on this presentation by Misha Selman, who is the executive director at JPMorgan Chase, about this.

01:27 It was given at PyData 2017.

01:29 So they've been working on it, but the problem is they have 35 million lines of Python 2 code.

01:35 Oh, that's a lot.

01:36 In terms of Python code, that's kind of ridiculous, right?

01:39 That's an insane amount.

01:41 So they've got a lot of Python code that has to be converted to Python 3.

01:45 And this is from their Athena trading platform, which is at the core of their business operations, right?

01:51 So they got a late start to migrating Python 3 and people were pointing out this could be a security risk for them, right?

01:57 Like we saw what happened with Equifax and some outdated things there.

02:02 Like who knows what the risks are?

02:05 I think it's probably less than something like the web frameworks that were out of date at other places.

02:10 But yeah, they have a lot of stuff that has to be migrated.

02:13 And internally they use Python for pricing, trading, risk management, analytics, and even machine learning.

02:19 So just to look at some stats from this project, the feature set utilizes 150,000 Python modules, over 500 open source packages, 35 million lines of Python code contributed by 1,500 developers.

02:36 - Okay, so they got a big team.

02:37 - That's a huge scale, and by the way, I wonder how much JPMorgan Chase is contributing back to those 500 open source projects.

02:44 - Hopefully some.

02:45 All right, now, it says they're gonna miss the deadline.

02:48 That most of the strategic elements are gonna be in place by Q1 2020, but they can't do it all.

02:55 And I know, it's probably a good roadmap for folks.

02:59 They don't have to upgrade it all and then release that new thing.

03:02 They can upgrade elements at a time.

03:04 And there's a lot of great stories on how folks have done that.

03:07 I think probably the Instagram project was the most awesome one I've seen where they didn't even branch.

03:13 They just found a way to seamlessly move from Python 2 to 3 while still running on 2 and then finally flipping the switch.

03:19 Here's another one I thought you would find interesting though.

03:21 They have some other stats.

03:24 You know, on your projects, how often do you commit code?

03:26 It's like once a week, once a day, once an hour.

03:29 You get several times a day.

03:30 I'm kind of the same.

03:31 I do that.

03:32 And you guys don't really release stuff, but like say the Python Bytes website or the Talk Python training site.

03:39 Those probably do some form of website release every other day, some sort of deploy, restart, like run through the whole deployment process.

03:48 So JP Morgan Chase uses continuous integration, continuous delivery with 10,000 to 15,000 production changes a week.

03:57 That's amazing.

03:58 It's like mind blowing, isn't it?

04:01 Yeah.

04:02 Yeah.

04:03 So they're on it, I guess, but it's just such a project of massive scale that it's hard to get your mind around and hard to find an analogy.

04:10 So I'm sure there's a few other projects like this in the world, but it can't be many.

04:13 - No, well, that's like one a second or faster.

04:17 - It's constantly deployed.

04:20 It's gotta be microservices and other stuff, right?

04:22 Otherwise, just like how would you go to the website?

04:24 How would you use the services?

04:25 Anyway, quite incredible.

04:27 All right, well, what you got for our next one?

04:28 - This is just kind of a cool little tool called Organize, and it was suggested from Ariel Barkin on Twitter.

04:36 And I took a look at this and I'm going to start using it right away.

04:40 So it's a Python-based file management automation tool.

04:44 And the idea is people are lazy with how they save files and download files and whatever.

04:50 And on my Mac, for example, all the screenshots just show up on the desktop.

04:55 And then, you know, occasionally I'll just take everything and lump them into a clutter folder or something.

05:00 But this is a tool where you can give it rules.

05:02 it's in a YAML file and say have it do things like move all your screenshots from the desktop into a screenshots folder or look through all your downloads to look at the incomplete downloads that you canceled or something they're still sitting there and just trash those if they're older than you know a few days old or something like doing things like removing empty files from certain folders like your download or desktop or other places. One of the examples is to organize your receipts and invoices into date-based folders, which is pretty cool because there's macros involved that you can look at the file touch time and and figure out what date and extrapolate the dates and stuff.

05:42 And yeah, I always when I'm paying bills or something I save the receipt to just wherever in the downloads folder or something. And having this just running this every once in a while could clean it up and put everything in its place.

05:55 It's pretty cool. -It's super cool. You could just put it on like a cron job that runs every five minutes or every minute or something, right, it just goes boop, it's gotta be super quick.

06:04 Just looks at the files, a few folders, and then does some text matching.

06:08 - It's one of those like, you know, automate the boring stuff sort of things that somebody thought, you know, everybody has this problem, so it's nice.

06:14 - Yeah, I like it, I have the same problem with receipts and stuff, I'll get them an email or as a PDF attachment or actually it's just an email that I'll print it to PDF so that I can save it for taxes and they just like clutter up, yeah, I could totally see just using that.

06:30 The rules seem like they're rich enough to do that.

06:32 So yeah, it looks really good.

06:33 Yeah.

06:33 Super cool.

06:33 All right.

06:34 Speaking of cool, let me just tell you about digital ocean.

06:36 So all of our services run on digital ocean audio or listen to now somehow flowed through the digital ocean servers to get to you and they've got all sorts of great options out there.

06:48 They're simple, but powerful.

06:50 There's not knobs to run.

06:51 Absolutely.

06:52 Every little edge case, right?

06:54 You set up the main.

06:55 servers that you want to work with, you have spaces, you have hosted databases, and MySQL and Postgres, and you even have caching like Redis and things like that.

07:05 So super nice.

07:06 Check them out at Python bytes.fm/digitalocean and get $50 credit for new users.

07:12 Highly recommended.

07:13 Now, this next one is a fun one, and it took me a minute to realize what this was about, Brian.

07:19 So I realized there's this new PEP, PEP 589, and it allows you to define typed dictionaries.

07:28 Like define a type that represents a dictionary.

07:31 Well, it turns out there was already a way to do that, which is why I was confused, 'cause there's PEP 484, which has been around for a while, which lets you create a dict of K comma V, which is like, here's a dictionary of arbitrary keys, and it has maybe integers, or it has user objects, or whatever, right?

07:48 So you can define these uniform dictionaries, which is kind of interesting.

07:54 But this new PEP, it lets you go much farther.

07:59 It's proposed by Jukka Letosalo, and it's actually sponsored by Guido van Rossum.

08:06 So remember recently we spoke about Guido and we had this philosophical debate of like, well, he's all about typing these days, but originally typing was like explicitly left out of the language.

08:16 What's the story?

08:18 So here's another typing thing that he's participating in, which I think is interesting.

08:21 So this is accepted.

08:23 It's scheduled for 3/8.

08:25 So all sorts of interesting stuff.

08:26 And it's, you know, it's coming down the line, right?

08:29 Soon, actually.

08:30 So what it lets you do is imagine you have an arbitrary JSON document or an arbitrary Python dictionary, really, but right, like, it's super easy to think of, like, well, somebody sends me a JSON request, and I want to treat it as if I know what's happening here.

08:43 It lets you actually specify the shape of those things, both the keys as well as the values and potentially nested documents, right?

08:53 So you might have a JSON object that's got like some values, one of those values might be a list of other JSON documents, you can describe that with this type dict thing.

09:02 So the way it works, kind of caught me off guard at first, but I think I like it.

09:05 So what you do is, instead of just saying, you know, there's a dictionary of like string, user, you actually create a class which derives from typed dict, okay?

09:16 >> Okay. >> And then it has fields.

09:17 It looks a lot like data classes a little bit.

09:19 So you might have like a name colon str and a year colon int.

09:24 In this thing, it is not actually the dictionary, but it is the type that validates the dictionary, all right?

09:31 >> Okay. >> And then you can say it is one of those, right?

09:33 So I say, the example they gave is there's a movie.

09:35 So you say movie colon capital M movie is the name of the class, and then it's just a dictionary.

09:39 But the dictionary has the name, which is a string value, and a year, which is an integer value, and so on.

09:45 And then you can actually validate it.

09:47 And the static type checker, like mypy and so on, will, if you say movie of director, it'll say, no, no, no.

09:55 You can't set this value into this dictionary because it doesn't have a key called director.

10:00 Or if you try to set the year to the string 1982, in quotes, it'll say, no, no, this is a string.

10:07 It expected an integer.

10:08 >> But the errors come at the type checking time, right?

10:11 >> This is a type checking time.

10:12 Although, it's totally reasonable that things like PyCharm and VS Code would add edit time checking for this as well.

10:19 Cuz they do for all the other type stuff.

10:20 >> Yeah, but it's not a run time.

10:21 >> It's not a run time thing.

10:23 Yeah, all the typing stuff.

10:24 >> Okay. >> And this is definitely that way.

10:26 So you're not re-implementing the dictionary.

10:28 You're not creating a dictionary type that is different.

10:32 you create a type which then talks about just a plain dictionary.

10:38 So quite interesting, actually.

10:39 >> Yeah, it does take a little while to look at it and go, does this make sense?

10:42 But yeah, it does.

10:43 >> Right, imagine you're running an API and somebody's submitting a JSON post to you, and you want to know is it valid, right?

10:51 You could use this basically to validate your schema, or at least describe the schema you expect.

10:55 >> Yeah, neat.

10:56 >> It is neat.

10:56 Speaking of APIs and new web things, your next one is one of those, right?

11:01 I got carried down that rabbit hole.

11:03 No, it's cool.

11:04 The next one, I was just enticed by the name.

11:07 So there's a package called Gospacho.

11:10 It's just great.

11:11 It's fun to say, it's fun to eat.

11:13 But anyway, Gospacho is a web scraping library.

11:18 And the goal of it is to replace requests and beautiful soup for most web scraping projects.

11:25 And I gotta tell you, I was gonna do, I have some web scraping projects that I wanted to do.

11:30 And I know that requests in BeautifulSoup are easy to use and are super powerful, but that one use case where you're just grabbing, like you're just doing a get, then you parse it, and then you find some stuff in it and separate it out, that's so common that this is, basically it's optimizing for that.

11:49 There's an example article that I'll link to also that uses Gazpacho to scrape hockey data for the use of fantasy sport use.

11:58 But it's just a really simple interface.

11:59 you import from Gospacho, you import get and soup as a class, and you can use those to grab some HTML and parse it, find some stuff in there.

12:10 It's just a handful of lines of code and you've got a web scraper on your hands.

12:15 So I like it.

12:16 I think I'll give it a shot.

12:18 But I tried it out and I wanted to bring this up because I tried it out and I ran into a problem that I was getting these certificate errors.

12:26 Have you ever gotten certificate errors when you're trying to parse things for pull things down?

12:30 - Yeah, just once or twice.

12:31 And it's the kind of thing where you bounce off the walls of Stack Overflow until you get it fixed and then you forget how to fix them.

12:38 But yeah, so what did you do?

12:40 - I did the same thing, went to Stack Overflow.

12:42 And apparently in within the, I don't know if this is just a Mac thing or not, but on Macs at least, when you install Python, you also in the install directory in applications, Python three, whatever, there's a file called install certificates.command and you just have to run that and then it has the list of certificates or something.

13:04 I don't know how certificates work, but it makes it so that you can access SSL stuff from Python.

13:11 So ran into that today.

13:13 - That's right.

13:13 I'm glad you're linking to it so now we'll have it for forever.

13:17 - Yeah.

13:18 - Yeah, that's cool.

13:18 It's nice, Gazpacho is like two to three times faster than Beautiful Soup, which is pretty sweet.

13:25 I like that.

13:25 It also does a lot less, so that makes sense.

13:28 Yeah, for sure.

13:28 It's a more focused thing.

13:29 And that's like the 80% case, though, right?

13:31 You just need to go do simple things.

13:33 That's what I'm going to use it for.

13:34 So the last thing I want to cover for our main items is PIP.

13:38 So remember, actually, we spoke about PyDist, P-Y-D-I-S-T?

13:42 Yeah.

13:42 Yeah, this is like a private PyPI as a service, I guess, is kind of the way I would describe it.

13:49 So right now, I think they-- before we had talked about this and I'm like, well, it just in beta, it doesn't seem to have any pricing or anything like that.

13:59 So they have pricing and a little bit more details.

14:02 They've more or less launched at this point.

14:04 And so this article is not about this, but it was written by the folks who run that.

14:09 Just that's the connection back to the previous thing.

14:12 And it talks about how pip install works.

14:15 So for this section, I just wanna talk to you real quick about when you say pip install certify, like it did in that previous article you just mentioned to fix your certificates.

14:25 What do you do?

14:26 How does it work?

14:27 All right.

14:28 So it walks you through all the steps and all the decisions and whatnot that pip has to make when you say pip install some package.

14:35 So the first thing it has to decide, well, first, I guess it does the package exist, right?

14:40 And then it needs to figure out which distribution of the package to install.

14:45 Because we have eggs, we have wheels, we have source, we have all these different types of distributions. There are seven different kinds of distributions, but the most commons are either source distributions or binary wheels. So focus on those, right? So source distribution is just, here's your Python code and maybe the C code that comes with it. And as part of the setup, we're going to like run a compiler against the C code to make sure that that's compiled in your machine, right? Super easy to write, not so easy to make sure it works on, you know, everywhere, not just works on my machine, right? Because You gotta have compilers on all the platforms.

15:22 And oh yeah, what about that old version of Windows that was a minimal install and doesn't have GCC or Visual Studio or whatever.

15:29 So, wheels are a little bit more safe and also faster, but that means they have compiled C code, which has to be, you have to have multiple ones for different platforms, right?

15:40 So, Windows versus macOS or something.

15:43 The benefit is, stuff installs fast, right?

15:46 So, like NumPy takes about four minutes to compile from source.

15:50 So if you did a source dist of NumPy, pip install might be slower than you would otherwise expect.

15:56 All right, so anyway.

15:58 - Yeah, the four minute pip install, yes, that's slower than I expected.

16:01 - Yeah, that's before you even hit the dependencies, right?

16:03 That's just the primary thing.

16:05 Yeah, okay, so it has to figure out which one of those are, and there's actually a known URL.

16:10 So like pypi.org/simple/packagename is where you would go.

16:16 So you can go to that slash request, for example.

16:20 And there's a huge, just flat, it's a weird API.

16:24 It's a HTML list of a bunch of wheels with platform names and tarballs and all sorts of stuff.

16:31 So it starts out by going there to figure out what is here.

16:35 What can I find?

16:36 So first it determines what system you're on and what's compatible with the thing.

16:43 So if you have a binary wheel, There's actually a path that talks about how you figure out which one that is.

16:48 And then if it's a source gist, like, well, you just assume it works.

16:53 So once it has that, then it'll try to get the best and it prefers wheels.

16:57 And then it has to figure out the dependencies.

16:59 So for binary wheels, there's a file called metadata that has a list of those.

17:02 So that's cool.

17:03 You can just look at that.

17:04 If it's a source distribution, it figures it out by running the setup.py.

17:09 So that's interesting.

17:11 So to run setup.py to actually figure out what dependencies it has to install, you know, go do that. And then you might have two dependencies, you might have a thing and you might depend on, let's say, beautiful soup, but you also have some other library that also depends on beautiful soup. If you follow the dependency tree, and they might even specify versions.

17:29 So you might wonder, well, what happens if one depends on one version, the other depends on the other. Turns out it just installs it anyway. Let's take the latest, that's going to be fine, right? That's different than like a requirements file that has like different dependency like pin versions like there's a slight difference there.

17:45 So finally gets it builds it installs it and then it has to figure out where's the path.

17:51 Is that I'm going to install it to a virtual environment?

17:53 Am I going to install it into the system or the user path, things like that.

17:58 So you can look at sys.prefix to figure out which one those are and there's some environment variables.

18:03 Ooh.

18:04 And finally it copies it over in the right place and your package installed.

18:08 Oh, before it considers your package installed also converts the source files into PYC bytecode files so they don't have to get parsed again.

18:15 Then your package is installed.

18:16 - Okay.

18:17 - Yeah, so anyway.

18:18 - Simple.

18:19 - Yeah, so if you're wondering what happens as part of the pip install stuff, there's a lot of details, and I didn't cover all of it, but as much as I thought made sense.

18:27 - I was just curious.

18:28 I was going to try to find one of those complicated packages that I knew had to be compiled because I went to a couple of mine and they're just Python code, so there's just one per version, wheel. But like NumPy, for instance, I know it's got some compiled code in it. It's got like, I lost count. It's like 15, 16, 17 different wheels for each version.

18:51 Yeah, request has got a ton as well. Yeah, it's interesting.

18:54 It is interesting how that works. I'm glad it all works. I don't have to think about it too much.

18:58 I'm glad I don't have to think about it either. But it turns out there's like a lot of conversation in there about some stuff that is not totally solved even today, right? About trying to resolve all of the dependencies in a totally predictable way before you start installing anything and stuff like that.

19:13 So it's worth checking out.

19:14 - It's a hard problem.

19:15 - Yep, for sure.

19:16 But wanna finish up with a cool trick, like a zoo trick, a zoo animal trick?

19:19 - Oh yeah, I'm just zoning today.

19:22 So Kevin Markham, he runs, what's the thing he runs?

19:26 - Data School, data school.io.

19:27 - Data School, plus he's a super nice guy.

19:30 Well, he's doing something neat that's, it's called Daily Pandas Tricks, or Tricks and Tips, or something like that.

19:36 But anyway, we got a link to it.

19:38 He's sending out a little tip or trick about pandas every day on Twitter.

19:44 And the page we're linking to has a whole bunch of them already built in.

19:48 And I like the notion of just trying to fit something.

19:52 Often they're little screenshots, but they're still pretty small.

19:55 A little lesson of how to do something cool.

19:58 I just picked out one, which is like, let's say you wanted to rename all of the columns in a data frame the same way, like to replace all the spaces with underscores or something.

20:09 And he just shows you how to do that in a little thing.

20:11 I think that's neat, especially for something--

20:14 for a package like pandas, there's a whole bunch of stuff you can do with it to have a way to just see a little extra new thing every day to say, that's something I might use.

20:24 I'll keep looking at that later or something.

20:26 So I don't think we've talked about it before.

20:28 And I think it's a cool thing he's doing.

20:30 So I wanted to highlight it.

20:31 Yeah, it's definitely a cool thing he's doing.

20:33 Pandas is one of those things where it's not always obvious, all the little magic that you can do, right?

20:39 Like if you want to go to the columns and do string operations, just dataframe.columns.str.

20:46 Apply your operation, right?

20:48 Like that's, after you use it for a while, it's obvious, but maybe not right away.

20:52 It definitely isn't to me.

20:53 Pandas feels a little like magic to me.

20:55 - I'm looking at this going, I would not have guessed that.

20:57 - Exactly.

20:58 It's not obvious, but once you know it, it's like, well, of course that's better than, Like, there's this saying that if you find yourself looping over things in like NumPy or Pandas, you're probably doing it wrong.

21:09 - One of the nice fun things I think is if you get really good at something, you'll start learning the things that you shouldn't do, but that are fun.

21:17 And some of Kevin's tips are, you can do this, it's sort of fun, but don't because it's confusing to other people.

21:25 But anyway, here's the trick.

21:27 - Nice.

21:28 - It's neat that he's including those.

21:29 - It's clever, but too clever sometimes.

21:31 All right, so do you have any extras to share?

21:33 - Oh, not only that we just got finished with our first Python West meetup last night, and it was both exhausting and really fun, so thanks for helping out with that.

21:44 - Yeah, you bet.

21:45 Good job putting it together.

21:46 It came out really well.

21:48 Everyone seemed to have a great time.

21:49 There was a totally good turnout.

21:51 I was blown away that it was actually, you know, basically sold out, not sold out, but booked out on its very first run, which is crazy.

21:58 And people out there listening, If you want to come and give a talk at the meetup and you're willing to find your way to Portland, shoot a message to Brian or me and let us know.

22:09 That'd be cool.

22:10 - Yeah, would be cool.

22:10 And then before anybody asks, it was not recorded.

22:12 So you have to be here.

22:15 How about you?

22:16 You got some news to share.

22:17 - I got all sorts of stuff.

22:18 A few really quick things.

22:20 One, I upgraded to macOS Catalina yesterday and so far so good.

22:25 No major problems.

22:26 All the Python things seem to be working.

22:27 So if you're wondering, I did hear that someone out there was having trouble with mini conda.

22:33 I don't use mini conda, so I have no idea about that.

22:35 Maybe do a Google search if that matters to you.

22:37 Also, Brian, I switched to working with Adobe audition.

22:40 I've been using audacity and garage band finally broke down and pay the $30 a month for Adobe audition and wow.

22:49 Is it worth it?

22:50 It is so good.

22:51 What has been wrong with me to not do that?

22:53 I just didn't want to learn new software.

22:54 It's not so much about the money.

22:55 It's just like, I don't want to learn new hotkeys.

22:57 I already know the hotkeys.

22:59 But it's so super good.

23:00 The reason I bring it up on the show instead of after is if you hear like weird artifacts or something odd in the audio, call our attention to it.

23:08 'Cause there's all these dials and knobs that can like do things like chop off the S's at the end of words if you turn them too far and stuff like that.

23:15 So hopefully things sound better if they don't, let us know.

23:18 And then the two Python related things, really quick.

23:21 Azure Databricks also is dropping support for Python 2.

23:25 So just one more brick to fall for a legacy Python.

23:28 The Python death clock continues to toll for those who hang on to their Python too.

23:34 And, the folks over on the VS Code team, wrong Lou in particular, just announced that at PyCon China, they just revealed a cool new Jupyter UI variable Explorer and Telesense stuff for basically running Jupyters inside of VS Code.

23:54 So if you're a VS Code user and you care about Jupyter, check that out.

23:57 Very cool.

23:57 Yeah, absolutely.

23:58 Absolutely.

23:58 Well, that's it for the stuff.

24:00 I got a story for you, a joke maybe.

24:02 Yes, please.

24:03 This one comes to us from maybe an unexpected space.

24:06 Comes to a person on Twitter, goes by the sarcastic pharmacist, sent us this actually really good joke and a nice comment, and the theme is that it's hard to distinguish between what is like super easy in programming and what is like nearly impossible for people who are not doing the programming themselves.

24:25 So this is actually an XKCD article 145.

24:28 It's got a programmer, a woman sitting there working at her desk.

24:33 And there's like a manager type who comes up and is issuing feature requests.

24:37 Okay.

24:37 Okay.

24:38 The manager, I'm going to think of one of the people from office space, maybe.

24:41 And it comes over and says, when the, when a user takes a photo with the app, it should check whether they're in a national park.

24:48 And the woman says, "Sure, easy.

24:50 "Easy GIS, look up, give me a few hours.

24:52 "Oh yeah, and it should also check "whether the photo's a bird." She says, "I'll need a research team in five years." (laughing)

24:59 But the subtitle is, "In CS it can be hard to explain the difference "between the easy and the virtually impossible." Yeah.

25:05 (laughing)

25:06 So there you go.

25:07 Yeah, I don't know, that resonates a lot with me at least.

25:10 - Yeah, we'll probably get a bunch of the image people telling us that it's like five minutes now with all the new image libraries to do a bird.

25:17 - Yeah, but that's now, right?

25:19 Like, we probably should, I should see if there's a date for this, just to be fair.

25:23 They don't have dates on these, that's kind of funky.

25:25 All right, anyway, well, there's probably some algorithm that figures out the number of the XKC and maps it back to a date, but yeah.

25:31 - Yeah, but that's funny.

25:33 - Cool, all right.

25:34 Well, great to chat with you as always.

25:36 - Thank you. - Yep.

25:36 - Bye. - Bye.

25:37 Thank you for listening to Python Bytes.

25:39 Follow the show on Twitter via @PythonBytes.

25:41 That's Python Bytes as in B-Y-T-E-S.

25:44 get the full show notes at pythonbytes.fm. If you have a news item you want featured, just visit pythonbytes.fm and send it our way. We're always on the lookout for sharing something cool. On behalf of myself and Brian Okken, this is Michael Kennedy. Thank you for listening and sharing this podcast with your friends and colleagues.

Back to show page