WEBVTT

00:00:00.001 --> 00:00:04.240
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:00:04.240 --> 00:00:11.540
your earbuds. This is episode 163, recorded live on location here at the Portland West Python

00:00:11.540 --> 00:00:20.180
Meetup. Hello, everyone. And it was recorded January 7th, 2020. Brian, it's 2020. Yeah,

00:00:20.180 --> 00:00:24.240
was that difficult to remember? It's, you know, I'm really not used to it. I just got used to

00:00:24.240 --> 00:00:28.480
2019. So we're having problems, but we'll get there. Yeah, well, it's really great to be here

00:00:28.480 --> 00:00:32.420
with everyone. This is the first time we've done a live recording in a while. We do this at PyCon a

00:00:32.420 --> 00:00:36.880
lot, but PyCon's not that frequent. So here we are in Portland. It's great. Yeah, thanks. And thanks

00:00:36.880 --> 00:00:40.640
for everybody for coming out. This is wonderful. Yeah, absolutely. I've got the first one, right?

00:00:40.640 --> 00:00:46.840
You've got the first item. So some Zen. I think it's a new year. It's a new decade. Let's kick it

00:00:46.840 --> 00:00:51.660
off with a little Zen. Yeah, a little Zen. So we're going to take 20 minutes and just meditate. So the

00:00:51.660 --> 00:00:55.300
first one I want to talk about, there's probably going to get this name wrong. Why did I pick this?

00:00:55.960 --> 00:01:01.200
Zadka. It's a pretty cool name, though. I wrote an article called Meditations on the Zen of Python.

00:01:01.200 --> 00:01:05.920
And if you don't know about the Zen of Python, hopefully you do. We're going to put a link in

00:01:05.920 --> 00:01:12.180
the show notes. But there's also in any REPL, you can say import this and it will show you a whole bunch

00:01:12.180 --> 00:01:17.680
of little cones, a little snippets of the Zen of Python. One of the cooler things you can do in Python,

00:01:17.680 --> 00:01:23.680
second only to import anti-gravity. Yeah, that's good. So Moshe says that this is a,

00:01:23.680 --> 00:01:28.960
the Zen of Python is not the rules of Python or the guidelines of Python. It is full of contradictions

00:01:28.960 --> 00:01:36.120
and illusions. It is not intended to be followed. It is intended to be meditated upon. So you can read

00:01:36.120 --> 00:01:41.160
these and think about your code. And actually, I kind of like it, like that idea, because when I've read

00:01:41.160 --> 00:01:45.740
through them, there are some that contradict each other. I want to bring out a few of them that he

00:01:45.740 --> 00:01:51.600
points out. The first is beautiful is better than ugly. And one of his comments is that consistency

00:01:51.600 --> 00:01:57.060
helps. So things like Black and Flake 8 and PyLint are very useful in making consistent looking code.

00:01:57.060 --> 00:02:01.180
Right. But those are only table stakes, right? It's just not ugly. It's not beautiful because of that.

00:02:01.180 --> 00:02:06.980
Right. So even more important, only humans can judge what humans find beautiful. So code reviews and

00:02:06.980 --> 00:02:12.620
collaboration and a collaborative approach to writing code are the only realistic way to build

00:02:12.620 --> 00:02:17.400
beautiful code. So listening to other people is an important skill in software development. And also

00:02:17.400 --> 00:02:23.320
just looking at code and seeing if you think it looks nice. I think it's good. So a couple more.

00:02:23.320 --> 00:02:30.080
Complex is better than complicated. And that one always like threw me. I wasn't sure why that was in

00:02:30.080 --> 00:02:36.540
there. Moshe says, when solving a hard problem, it's often a case that no simple solution will do. In that

00:02:36.540 --> 00:02:43.240
case, the most Pythonic strategy is to go from the bottom up, build simple tools and combine them to solve

00:02:43.240 --> 00:02:48.260
the problem. That's kind of a Unix style. So is that how you view the complex is better than

00:02:48.260 --> 00:02:48.720
complicated?

00:02:48.720 --> 00:02:52.540
I don't know if I've ever thought of in these terms. And I do like this article because it did make me

00:02:52.540 --> 00:02:56.720
think like that. But I certainly think about software that way. I feel like so many people get caught

00:02:56.720 --> 00:03:00.200
trying to overthink it. And they're like, oh, I can't get started. I'm trying to like get the right,

00:03:00.200 --> 00:03:05.060
the exact right thing before I can write my first line of code. And it's like, no, you're never going to

00:03:05.060 --> 00:03:09.280
know until you work on it for two days. Then you're like, oh, I should have done this. But well,

00:03:09.840 --> 00:03:13.120
you didn't know what you knew now. So what are you going to do? Just get started. Yeah. It's my

00:03:13.120 --> 00:03:17.500
philosophy. And the last one I want to talk about is readability counts. So in the face of immense

00:03:17.500 --> 00:03:23.180
pressure to throw readability to the side and just solve a problem, the Xenopython reminds us that

00:03:23.180 --> 00:03:28.460
readability counts. Writing code so it can be read is a form of compassion for yourself and others.

00:03:28.460 --> 00:03:33.140
And one of the reasons why I highlighted this is we're going to talk about optimization and speed later

00:03:33.140 --> 00:03:39.440
on. And speed is great, but making sure that your program is readable and maintainable is very

00:03:39.440 --> 00:03:43.540
important. I really liked this article. Well done because we've all heard about the Xenopython.

00:03:43.540 --> 00:03:49.600
We've probably all typed import this, but it's a little vague. And this is not, here's what it

00:03:49.600 --> 00:03:54.440
means. This is, here's, here's me trying to think about it sort of philosophically. And, you know,

00:03:54.440 --> 00:03:57.740
I've never seen anyone write that way about it before. And I thought it was really cool.

00:03:57.740 --> 00:04:01.340
I'd love to other people to like come up with their ideas about it. So that'd be cool.

00:04:01.340 --> 00:04:07.920
Yeah, absolutely. So Python and the web doesn't usually have like a James Bond sort of

00:04:07.920 --> 00:04:16.080
places getting raided by the police, secret service, international angle to it. But this

00:04:16.080 --> 00:04:21.520
next item does. Really? Yeah, it does. So you know what the most popular web server is in the

00:04:21.520 --> 00:04:27.280
world? Used to be Apache. Now it's Nginx. Our stuff runs on Nginx, for example. However, there

00:04:27.280 --> 00:04:34.360
was some news a few weeks ago. The Nginx offices in Russia were raided by the Russian police and

00:04:34.360 --> 00:04:40.000
some of the core developers were detained. And the reason is, this is not as interesting as I made it

00:04:40.000 --> 00:04:45.200
out to be, I don't really think. But the reason was, the guy who created it, I have his name here,

00:04:45.200 --> 00:04:52.760
Sisyov, he created it. And he, at the time, he was working for Rambler.ru. And Rambler.ru is like a

00:04:52.760 --> 00:04:58.300
Google Yandex type of company search engine in Russia. And he worked on this in his spare time. And he

00:04:58.300 --> 00:05:03.960
open-sourced Nginx and then later turned it into a company. Well, Rambler came along and said, hey,

00:05:03.960 --> 00:05:10.240
you know what? You worked on that while we were employing you. Nginx is ours. We're taking it over.

00:05:10.240 --> 00:05:16.980
Meanwhile, Nginx has been bought by F5, an American company, and they own it. And so there's all this

00:05:16.980 --> 00:05:20.560
intrigue around it. And yeah, so that happened.

00:05:20.560 --> 00:05:25.800
So a bunch of my friends from Spokane that, when Agilent closed down there, went to work for F5,

00:05:25.800 --> 00:05:29.220
and I'd never even heard of them before. And then they show up in this news article.

00:05:29.220 --> 00:05:29.760
Yeah.

00:05:29.760 --> 00:05:30.260
It's pretty interesting.

00:05:30.260 --> 00:05:34.440
Yeah, they're all about the networks, but apparently servers. So I received an update,

00:05:34.440 --> 00:05:39.680
an email from Nginx a few days later. And I'll just read it so I get it right. They said,

00:05:39.680 --> 00:05:44.860
promptly following this event that I just described, we took measures to ensure the security of our

00:05:44.860 --> 00:05:52.140
master software builds for Nginx, Nginx Plus, Nginx WAF, and Nginx Unit, all of which are stored on

00:05:52.140 --> 00:05:58.180
servers outside of Russia. No other products are developed in Russia. F5 remains committed to

00:05:58.180 --> 00:06:03.960
innovating with Nginx, Nginx Plus, et cetera, et cetera, all the products. And we continue to provide

00:06:03.960 --> 00:06:09.120
the best-in-class support. You can expect that to come. So who knows where this is going to go?

00:06:09.120 --> 00:06:09.860
That's pretty interesting.

00:06:09.860 --> 00:06:12.940
If you use Nginx, should you worry about this?

00:06:13.260 --> 00:06:17.160
That was why I brought it up. Because if it's the most popular web server in the world,

00:06:17.160 --> 00:06:21.760
some folks, their ears are going to perk up and say, wait a minute, what? I mean,

00:06:21.760 --> 00:06:26.980
I don't think this is like Russia trying to impose its will on the world. I think this is just a

00:06:26.980 --> 00:06:32.940
dispute between a Russian company and some Russian folks who created Nginx, but it could have knock-on

00:06:32.940 --> 00:06:37.480
effects quite far. So yeah, it's pretty interesting. I think just keep an eye on it, really.

00:06:37.480 --> 00:06:41.040
This episode is brought to you by, well, us.

00:06:41.040 --> 00:06:41.400
Really?

00:06:41.400 --> 00:06:44.640
Yeah, normally it's brought to you by other companies, but this time, you know, we both

00:06:44.640 --> 00:06:48.900
have interesting things to talk about and we have a gap. So I just want to tell you about

00:06:48.900 --> 00:06:53.400
some of our stuff. So if you want to check out the courses that I'm creating or, you know,

00:06:53.400 --> 00:06:59.260
set up the business stuff, just visit pythonbytes.fm/biz. And here there's something about

00:06:59.260 --> 00:07:04.040
testing over at pythonbytes.fm/pytest. And people can check that out there as well.

00:07:04.120 --> 00:07:07.820
Cool. Did you set up a URL redirect from there?

00:07:07.820 --> 00:07:11.600
I don't want to say the whole name of the whole domain name and URL. So yeah, that's yours.

00:07:11.600 --> 00:07:18.040
It points to Python testing with pytest, which I was published in 2017, but I still think is the

00:07:18.040 --> 00:07:20.620
very best way to get up to speed very quickly on pytest.

00:07:20.620 --> 00:07:23.840
Yeah, absolutely. And you also, we also have a Patreon that you set up at pythonbytes,

00:07:23.840 --> 00:07:28.800
at patreon.com slash pythonbytes. So I have some thoughts on this next one, but why don't you

00:07:28.800 --> 00:07:33.540
kick it off? This one's from the creator of Flask, but not the current maintainer of Flask.

00:07:33.540 --> 00:07:38.300
Oh, that's true. Right. So I brought this up because I was curious what your thoughts were.

00:07:38.300 --> 00:07:40.800
So the next one is from Armin...

00:07:40.800 --> 00:07:41.520
Armin...

00:07:41.520 --> 00:07:42.180
Armin Ronecker.

00:07:42.180 --> 00:07:44.900
Armin Ronecker. Thank you. He wrote an article called,

00:07:44.900 --> 00:07:50.760
I'm Not Feeling the Async Pressure. The idea is like, async is all the rage. We've actually talked

00:07:50.760 --> 00:07:55.760
about async quite a bit on the podcast. And I think a lot of people are concerned about it. And

00:07:55.760 --> 00:08:00.300
it's one of the reasons why it's going in place is because I think there's some pressure of people

00:08:00.300 --> 00:08:02.760
to leave Python to go to Go or other things.

00:08:02.760 --> 00:08:04.680
Node.js was an early example of that, yeah.

00:08:04.680 --> 00:08:10.920
Yeah. But before you go towards async, Armin is warning people to make sure you understand flow

00:08:10.920 --> 00:08:16.760
control and backpressure. And I had never heard of backpressure, but backpressure is the resistance

00:08:16.760 --> 00:08:23.580
that opposes the flow of data through a system. Backpressure sounds quite negative, but is here to

00:08:23.580 --> 00:08:29.600
save your day. If parts of your system are async, you have to make sure the entire flow through the

00:08:29.600 --> 00:08:35.160
system doesn't have overflow points. And then Armin goes through an example with a reader and writer,

00:08:35.160 --> 00:08:41.320
and it seemed like simple code, but it really got hairy really kind of fast. And the example,

00:08:41.320 --> 00:08:48.760
yeah, got hairier than I expected. And he says, async brings you new foot guns. Async and await are

00:08:48.760 --> 00:08:53.180
great ways to encourage writing stuff that will behave catastrophically when overloaded.

00:08:53.180 --> 00:08:58.680
For you developers of async libraries, here's a new year's resolution for you. Give backpressure and

00:08:58.680 --> 00:09:05.260
flow control the importance they deserve in documentation and API. And there's just some

00:09:05.260 --> 00:09:10.360
hidden things within buffers and things like that. So yeah, well, this is a pretty nuanced article

00:09:10.360 --> 00:09:15.080
and it's pretty interesting. It comes from someone who knows a thing or two about the network programming,

00:09:15.420 --> 00:09:21.700
Armin being the original creator of Flask. That said, my reaction to reading it,

00:09:21.700 --> 00:09:27.900
my reaction was there were a lot of examples of, and here's if you overpressure the system when you

00:09:27.900 --> 00:09:33.780
write an async system, it will fall down, right? Imagine you only allow 50 database connections and

00:09:33.780 --> 00:09:39.660
suddenly you get 10,000. My sort of reaction to this was, well, what is the response of the system

00:09:39.660 --> 00:09:44.900
going to be when it's single threaded and you give it 10,000 connections requests? They're all going to

00:09:44.900 --> 00:09:46.660
time out except for a call. It's just going to crash.

00:09:46.660 --> 00:09:46.860
Yeah.

00:09:46.940 --> 00:09:52.820
So does it crash in an async world or does it crash in a non-async world? With enough traffic,

00:09:52.820 --> 00:09:57.500
yes. But at the same time, if you can write basically the same code, put async and await in

00:09:57.500 --> 00:10:02.560
front of a few bits and you can get 10 or a hundred times the amount of performance out of a given piece

00:10:02.560 --> 00:10:08.860
of hardware before it crashes, that seems better to me. So I mean, I'm sympathetic to the problem,

00:10:08.860 --> 00:10:13.000
but at the same time, it's always like, well, if we give it way too much pressure,

00:10:13.000 --> 00:10:16.840
it's going to crash. Well, if it wasn't parallel, it would crash before then.

00:10:16.840 --> 00:10:21.700
My thoughts were like, can you, are there ways to throttle? Because I don't know enough about all

00:10:21.700 --> 00:10:27.240
the way to do network stuff. So if I'm setting up a web service, for instance, can I throttle the input

00:10:27.240 --> 00:10:32.000
to say to not allow 10,000 connections and just allow 5,000 or something?

00:10:32.000 --> 00:10:36.900
Right, right. Potentially. So maybe with something like UVicorn or something, you could set that up.

00:10:36.900 --> 00:10:43.320
I honestly don't know. It seems to me the danger that he's addressing is when the system itself is

00:10:43.320 --> 00:10:47.500
generating the input. Like we had this example of a guy who sent us a message and said, Hey,

00:10:47.500 --> 00:10:53.680
I had this web scraping thing. It was really slow. We turned async loose on it and it crashed the server

00:10:53.680 --> 00:10:57.920
because it ran out of memory because it processed it too quickly, right? Like there, you need to find

00:10:57.920 --> 00:11:01.320
a way to slow it down. But when you're running a web server, you don't control how many people want

00:11:01.320 --> 00:11:04.980
to get to it. There's just people want to get to it and they either can or they can't.

00:11:04.980 --> 00:11:09.020
And with async, more of them would be able to than otherwise. That's my thoughts.

00:11:09.020 --> 00:11:14.660
Okay. And I guess that my thoughts would be if you're going to throw async at a problem,

00:11:14.660 --> 00:11:18.420
make sure that you do capacity testing on it as well.

00:11:18.420 --> 00:11:22.000
Yeah. Well, it's going to fail somewhere else, right? And so you're going to,

00:11:22.000 --> 00:11:25.880
maybe your database isn't set up for it. Maybe your microservices can't handle all the traffic.

00:11:25.880 --> 00:11:29.060
Like there's going to be something, right? It's just going to show up somewhere else. But

00:11:29.060 --> 00:11:33.040
in general, I think you're going to get better scalability with it than without it. So

00:11:33.040 --> 00:11:37.300
if you're not generating that pressure, if you're not generating the traffic, then I don't know what

00:11:37.300 --> 00:11:39.780
choice you have. Okay. But that's my thought. It was an interesting read.

00:11:39.780 --> 00:11:44.980
Yeah, it definitely was. It definitely was. Let's go for something a lot simpler than like a deep

00:11:44.980 --> 00:11:49.820
thing on streaming and buffers and async. How about a new way to time your code?

00:11:49.820 --> 00:11:50.540
Yeah, that sounds good.

00:11:50.540 --> 00:11:56.460
Yeah. So this one comes to us from Doug Farrell, who works on the RealPython team. And as part of their

00:11:56.460 --> 00:12:01.300
work, they've got to time all sorts of things for their articles. You know, Dan Bader and crew over there.

00:12:01.880 --> 00:12:05.840
And so they came up with this thing. Either they came out of RealPython,

00:12:05.840 --> 00:12:11.800
I think, or possibly they were just using it a lot. But this thing called code timing.

00:12:11.800 --> 00:12:16.560
So if you've got some code and you want to know how long it takes to run, you could say, you know,

00:12:16.560 --> 00:12:23.000
create a time, like capture the daytime, do some work, capture dot now again and do a delta.

00:12:23.300 --> 00:12:27.400
Or you could even use performance counters and other things. But you can use this library.

00:12:27.400 --> 00:12:31.300
You just, there's a bunch of different things you can do. You create a timer class and you can call

00:12:31.300 --> 00:12:36.580
start, do some work, stop. And out comes the time. Or you can put it in a context manager,

00:12:36.580 --> 00:12:40.380
like a width block. Soon as it goes to the width block, when it's done, that bit is timed.

00:12:40.620 --> 00:12:45.180
Or you can use it as a decorator. And you can also wire up a logger, which is kind of cool.

00:12:45.180 --> 00:12:50.680
So you can see like, it'll just output standard Python logging with time information of when it's

00:12:50.680 --> 00:12:53.820
doing bits of its thing. Give it a name and it'll tell you how long it took.

00:12:53.820 --> 00:12:57.980
Cool. Well, they should add statistics too, so I can get min, max, and average, and standard deviation.

00:12:58.200 --> 00:13:02.000
Yeah, that would actually be cool. Well, it's, you know, open source, I bet they accept PRs.

00:13:02.000 --> 00:13:05.520
Actually, there's a bunch of features I want to add to it. And I started messing around with it.

00:13:05.520 --> 00:13:11.840
And I'm like, put it down. I have other things to do. I'm already too busy. I don't need this.

00:13:11.840 --> 00:13:15.200
I'm going to leave it alone. But yeah, it's a pretty cool little timer class. And I'm going to

00:13:15.200 --> 00:13:15.920
probably use that. I like it.

00:13:15.920 --> 00:13:21.740
Yeah. I thought this, a nice follow-on for this, the timer would be an article called

00:13:21.740 --> 00:13:24.420
Making Python Programs Blazingly Fast.

00:13:24.420 --> 00:13:25.600
That sounds good. We all want that.

00:13:25.600 --> 00:13:29.680
You need to time stuff. You should never, I mean, hopefully we've all learned that

00:13:29.680 --> 00:13:34.220
premature optimization is one of the most horrible things you can do as a programmer.

00:13:34.220 --> 00:13:38.920
What I've learned is it's incredibly hard to guess where something is slow. Even if you know,

00:13:38.920 --> 00:13:42.720
this takes a second, you look at the code, I'm like, oh, I bet it's there. Like, no, no, no. That's

00:13:42.720 --> 00:13:44.260
like 5%. It's over here.

00:13:44.260 --> 00:13:45.620
Yeah. Because it's super hard to know.

00:13:45.620 --> 00:13:52.080
You're throwing the first version of the rough draft of your code down and you write something down and

00:13:52.080 --> 00:13:55.520
you go like, I know I can do this better, but I'm going to just make it work.

00:13:55.520 --> 00:13:59.180
here. And you know, you're going to have to optimize that. And it turns out to not be the

00:13:59.180 --> 00:13:59.600
slow part.

00:13:59.600 --> 00:14:00.220
Right. Exactly.

00:14:00.220 --> 00:14:04.620
Yeah. So you need to find out where the slow part is. So this article called Making Python

00:14:04.620 --> 00:14:10.560
Programs Blazingly Fast by Martin Hines goes through a few things. He doesn't cover this timer,

00:14:10.560 --> 00:14:14.800
but there's a few other ways you can time it. There's a, you can use the command line time

00:14:14.800 --> 00:14:17.720
function to just time how long something runs.

00:14:17.720 --> 00:14:22.200
That might work. You might just go, I made a change. It was five seconds. Is it more or less?

00:14:22.340 --> 00:14:23.520
Yeah, exactly. That'll tell you.

00:14:23.520 --> 00:14:27.800
Python-mcprofile can tell you a whole bunch about your program.

00:14:27.800 --> 00:14:29.580
Do you use cprofile much?

00:14:29.580 --> 00:14:30.360
I don't really.

00:14:30.360 --> 00:14:32.940
Yeah. I've used it. So it's, it's pretty awesome actually.

00:14:32.940 --> 00:14:36.960
Yeah. And then he goes through an example of writing a wrapper function for a timer,

00:14:36.960 --> 00:14:40.620
which is similar to what this last article was.

00:14:40.620 --> 00:14:42.820
It's one facet of GoTimer.

00:14:42.920 --> 00:14:47.580
One of the things that he doesn't cover is the time it function within that's built into Python,

00:14:47.580 --> 00:14:52.940
which allows you to just run a single function a whole bunch of times and then tells you how,

00:14:52.940 --> 00:14:53.920
how long that takes.

00:14:53.920 --> 00:14:56.340
Yeah. Then you get your average and your deviation, all that.

00:14:56.340 --> 00:15:02.300
But then the article goes through how to make things faster. So once you've found the slow parts,

00:15:02.300 --> 00:15:08.020
how do you make it faster? And these are some good suggestions. Use built-in types over custom types.

00:15:08.620 --> 00:15:14.520
Use caching and memoization through LRU cache, which is a built-in thing into Python.

00:15:14.520 --> 00:15:20.940
Local variables and local aliases while, when looping. This is something I didn't expect. This

00:15:20.940 --> 00:15:26.920
is something like if you've got a multiple dot, dot, dot, dot, something into a function call,

00:15:26.920 --> 00:15:30.220
creating a local copy of that makes things run faster.

00:15:30.220 --> 00:15:35.480
Every traversal of that dot is expensive in Python, whereas like C++, not so much.

00:15:35.620 --> 00:15:41.380
Yeah. Especially if it's in a loop. So I use functions. I don't understand why this was there.

00:15:41.380 --> 00:15:43.060
Kind of duh, but you know.

00:15:43.060 --> 00:15:50.080
Well, apparently the variable lookup in a function scope is faster than a global variable lookup or

00:15:50.080 --> 00:15:55.060
something like that that he was talking about. So by forcing all the variables into the function

00:15:55.060 --> 00:15:58.260
scope, they actually come out faster. So there's all these like little weird edge cases.

00:15:58.440 --> 00:16:03.520
Yeah. I don't have any code that's not in a function. So don't repeatedly access attributes

00:16:03.520 --> 00:16:07.720
in loops. Okay. There's a similar sort of thing. One of the things I didn't realize is the F

00:16:07.720 --> 00:16:12.440
strings have been tuned to be very fast. So if you're doing string formatting, use f-strings over

00:16:12.440 --> 00:16:12.860
other things.

00:16:12.860 --> 00:16:14.820
How many of you out there are using f-strings these days?

00:16:14.820 --> 00:16:20.460
Right on. Like that's five, 10 times faster. I don't know. There was a thing by Raymond Hedinger

00:16:20.460 --> 00:16:21.900
that's mentioned in that article.

00:16:22.080 --> 00:16:25.220
Yeah. So it's way, way faster than the other ways that it was awesome.

00:16:25.220 --> 00:16:30.000
And then use generators because I added at least experiment with generators because generators

00:16:30.000 --> 00:16:36.300
are really about saving memory. But if you're really dealing with some large data, memory saving

00:16:36.300 --> 00:16:40.180
could result in speed up. So I would say throw those in and see if it's faster.

00:16:40.180 --> 00:16:42.260
As soon as you start hitting that page file, you're done.

00:16:42.260 --> 00:16:45.420
I love generators. I throw them everywhere.

00:16:45.420 --> 00:16:46.220
I do too.

00:16:46.220 --> 00:16:51.660
Anyway, I think this was an interesting article on speeding up Python. And I warned people against

00:16:51.660 --> 00:16:54.500
a premature optimization though. So, but it's fun.

00:16:54.500 --> 00:16:57.640
Perfect. Yeah. This is a really good one. I like it. And it's a good follow on to the

00:16:57.640 --> 00:17:04.480
other ones we have. Brian, yeah, you're here. So you spoke about CDK, the cloud development

00:17:04.480 --> 00:17:11.300
kit from AWS. One of the big gives I have with working with the cloud is I work from home.

00:17:11.300 --> 00:17:14.960
I want to go work in a coffee shop. Maybe I'm traveling. I want to work from the hotel and

00:17:14.960 --> 00:17:19.280
the internet's bad. I still want to be able to work on my code and know the internet is not

00:17:19.280 --> 00:17:26.020
available. Whoops. I guess my app won't run anymore. Right? Well, that is a problem, which

00:17:26.020 --> 00:17:31.400
I mostly solve by avoiding the cloud directly. But there's another cool project called local

00:17:31.400 --> 00:17:37.880
stack. Talked about Moto before, which is a way to like mock out AWS. And this is actually

00:17:37.880 --> 00:17:41.660
built on Moto, but it actually does quite a bit more. This comes to us from Graham Williamson

00:17:41.660 --> 00:17:47.280
and Jan Gazda. So thank you both for sending this in. And basically what it is, is it's

00:17:47.280 --> 00:17:56.120
like a local AWS, not just a little bit, like a lot of local AWS. It has S3. It has SES for

00:17:56.120 --> 00:18:02.780
simple email. It has EC2. It has DynamoDB as Lambda has elastic search, all of that stuff locally.

00:18:02.780 --> 00:18:06.700
He showed us like tons of a huge list though. They have all that stuff.

00:18:06.700 --> 00:18:11.540
It has a bunch. I don't know how many it has, but I would say it's somewhere on the order of,

00:18:11.540 --> 00:18:14.260
I don't know, 2025 different services.

00:18:14.260 --> 00:18:15.320
Probably the most common ones.

00:18:15.320 --> 00:18:18.720
Yeah. Yeah. Probably the most common ones. And then apparently there's also like some kind of pro

00:18:18.720 --> 00:18:24.080
thing I've not used, but then you get more services if you buy the pro version, but the lesser one,

00:18:24.080 --> 00:18:25.520
I guess is open source, which is pretty cool.

00:18:25.520 --> 00:18:28.480
That's neat. That's great. Like if you're on an airplane or something.

00:18:28.480 --> 00:18:31.320
Yeah. Or you just, you want to have like a little local dev environment.

00:18:31.320 --> 00:18:34.400
You don't have to pay for that, even though it's less than pennies, but yeah.

00:18:34.400 --> 00:18:38.860
It depends what you're doing, I guess. But yeah. So yeah, basically it brings together some of these

00:18:38.860 --> 00:18:43.980
tools. It brings together Modo. It brings together this thing called Dynalite and puts sort of a

00:18:43.980 --> 00:18:49.360
unifying layer on top of it. So it's pretty cool. A lot of it runs in Docker. It helps to kind of

00:18:49.360 --> 00:18:50.900
get a repeatable experience there.

00:18:50.900 --> 00:18:51.480
That sounds neat.

00:18:51.480 --> 00:18:56.260
Yeah, absolutely. All right. Well, that's it for our main items, everyone. Got any extras you want to

00:18:56.260 --> 00:18:56.680
share with folks?

00:18:56.680 --> 00:19:03.220
Well, I just, I don't know if we've covered this before. I saw an advert for the Python job board

00:19:03.220 --> 00:19:05.020
on python.org.

00:19:05.020 --> 00:19:10.920
Yeah. Yeah. I saw that. I hadn't seen it before, but yeah, apparently there's the, there's now,

00:19:10.920 --> 00:19:16.180
yeah, we're joking around. We're laughing because the internet's not quite cooperating. That's fine.

00:19:16.180 --> 00:19:19.980
We don't need it. Who needs the internet? What did I say about the cloud? What did I just say,

00:19:19.980 --> 00:19:25.340
Ryan? You better hope you're not trying to test something right now. Carry on. Yeah. So the job board is

00:19:25.340 --> 00:19:27.960
cool. Right. I hadn't noticed it either, but it's on python.org.

00:19:27.960 --> 00:19:31.580
I don't know if you have to pay for stuff, but you can just list jobs. So that's cool.

00:19:31.580 --> 00:19:36.860
Yeah. And Python's in demand. People want to have jobs writing code in Python, right? Like,

00:19:36.860 --> 00:19:37.360
you know.

00:19:37.360 --> 00:19:38.660
Do you have any extras for us?

00:19:38.660 --> 00:19:43.140
I do have a couple. Let me pull these up here for the audience as well. So I have pictures

00:19:43.140 --> 00:19:47.580
because some of these are very, very graphical. So there's this really cool one. You never asked him

00:19:47.580 --> 00:19:51.780
probably heard of the guy who created Python. So he was interviewed, he's Dutch. He was interviewed by this

00:19:51.780 --> 00:19:58.200
Dutch newspaper about programming. And the title, my Dutch is a little off, but it's like Python is

00:19:58.200 --> 00:20:02.900
half my life. Right. So I worked on a Python for half my life or something like this. And they said,

00:20:02.900 --> 00:20:07.000
we're going to, this is like a developer thing. Let's put some code and show some Python.

00:20:07.000 --> 00:20:07.500
Yeah.

00:20:07.500 --> 00:20:09.300
What code do we see there?

00:20:09.300 --> 00:20:10.420
I don't know. Is it JavaScript?

00:20:10.420 --> 00:20:17.020
Document.getElementByID. Yeah. Not so much. Not so much. That was a pretty interesting little

00:20:17.020 --> 00:20:21.660
thing that actually happened. The next one that's pretty interesting. I don't have a picture for it.

00:20:21.660 --> 00:20:24.980
It would just be like a bar that's rusting or something, but no, it's pretty cool.

00:20:24.980 --> 00:20:30.280
Though Microsoft, you know, they're all about C and C++, right? Like Windows is based on C and C++.

00:20:30.280 --> 00:20:35.320
They are actually been doing experimentations with Rust and they're coming out with a Rust

00:20:35.320 --> 00:20:41.860
based programming language for like rewriting things like Windows and Rust. That's a pretty big

00:20:41.860 --> 00:20:49.600
jump for Rust. And the reason is Rust is especially good at memory management and memory ownership. So

00:20:49.600 --> 00:20:55.040
things like buffer overflow vulnerabilities and stuff just go away in Rust, which is like,

00:20:55.040 --> 00:21:00.280
you know, every first Tuesday, here's the seven buffer overflows. They're going to like lose all

00:21:00.280 --> 00:21:04.540
your data if you don't patch by the next two days that you get. And like, they're trying to avoid that,

00:21:04.540 --> 00:21:05.820
I'm guessing. So that sounds interesting.

00:21:05.820 --> 00:21:06.560
Do you know Rust yet?

00:21:06.560 --> 00:21:09.280
I've looked at Rust. It looked like C. I said, I'm going to go back to Python.

00:21:09.280 --> 00:21:12.500
I mean, not exactly, but it looked like C-ish.

00:21:12.500 --> 00:21:14.120
Maybe I should take a look at it.

00:21:14.120 --> 00:21:18.900
Yeah, it's pretty interesting. Two more quick things. So I'm doing a webcast of Python for

00:21:18.900 --> 00:21:23.560
the .NET developer, kind of interactive one hour thing at Crowdcast on the Crowdcast platform. I

00:21:23.560 --> 00:21:27.380
think that'll be fun. So links in there. It's free to sign up. People can check that out. And then

00:21:27.380 --> 00:21:32.700
Reuven Lerner was talking to him today and he has a new free course that he released called

00:21:32.700 --> 00:21:38.720
Ace Python Interviews. So people are out there looking for a Python job. Here's like 50

00:21:38.720 --> 00:21:46.320
little exercises and questions answered live and like live coding responses to 50 interview questions

00:21:46.320 --> 00:21:47.360
that are explained.

00:21:47.360 --> 00:21:50.640
Reuven's a really cool guy. So I think that'd be cool to look at.

00:21:50.640 --> 00:21:54.040
Yeah, yeah, absolutely. It looks really good. And that was also free. So no harm, no foul there.

00:21:54.040 --> 00:21:54.740
People can check that out.

00:21:54.740 --> 00:22:01.300
And I've got a job opening. So if anybody's looking, I'm mostly, last time I interviewed was for Python

00:22:01.300 --> 00:22:05.800
person. So I'm probably just going to take some of these things and convert them to C++.

00:22:07.000 --> 00:22:11.440
So, you know. So if you want to pass Brian's interview, it may be a good idea to take this

00:22:11.440 --> 00:22:12.720
course. Don't tell my boss.

00:22:12.720 --> 00:22:16.140
Yeah, yeah. All right. So are we ready for a joke? We always end up podcasts with a joke.

00:22:16.140 --> 00:22:16.360
Yeah.

00:22:16.360 --> 00:22:19.400
This one's very visual. So I'm going to put this up on the screen for you as well.

00:22:19.400 --> 00:22:24.260
And this is really like a sort of infographic. I'm a fan of infographics. And this one helps you

00:22:24.260 --> 00:22:28.520
understand like the different types of jobs in software development, which can be very tricky,

00:22:28.520 --> 00:22:33.300
right? Like what is the difference between a lead developer and a full stack developer and a coder?

00:22:33.300 --> 00:22:37.780
Well, here we go. So it says, there's this person and pretty much it's the same looking

00:22:37.780 --> 00:22:43.360
person for every job description. And it says there's a coder. There's a little caption that

00:22:43.360 --> 00:22:49.540
says he writes. Software engineer, he writes code. Lead developer, he writes code. DevOps,

00:22:49.860 --> 00:22:56.040
well, he writes code. Infrastructure is code, right? Data engineer, actually, what does he do?

00:22:56.040 --> 00:22:56.720
He writes code.

00:22:56.720 --> 00:22:59.460
He writes code. Full stack developer, he writes code alone.

00:22:59.460 --> 00:23:07.720
Computer programmer, he writes code too. Sysadmin, he writes, this is actually a guy eating donuts

00:23:07.720 --> 00:23:12.160
with a big beard and looking very disheveled. It says he writes, in fact, we don't really know

00:23:12.160 --> 00:23:17.840
what he does. All right. Well, that's the joke for Dave. I guess that's the podcast for today as

00:23:17.840 --> 00:23:20.240
well. So thanks a lot. Yeah. Thanks a bunch. And thank you everyone.

00:23:20.240 --> 00:23:24.740
Bye.

00:23:24.740 --> 00:23:28.360
Thank you for listening to Python Bytes. Follow the show on Twitter via

00:23:28.360 --> 00:23:34.440
at Python Bytes. That's Python Bytes as in B-Y-T-E-S. And get the full show notes at

00:23:34.440 --> 00:23:39.580
Pythonbytes.fm. If you have a news item you want featured, just visit Pythonbytes.fm and send it our

00:23:39.580 --> 00:23:44.400
way. We're always on the lookout for sharing something cool. On behalf of myself and Brian Okken,

00:23:44.600 --> 00:23:49.040
This is Michael Kennedy. Thank you for listening and sharing this podcast with your friends and colleagues.

