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


Transcript #336: We found one of your batteries

Return to episode page view on github
Recorded on Tuesday, May 16, 2023.

00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:04 your earbuds. This is episode 336, recorded May 16th, 2023. I'm Michael Kennedy.

00:11 And I'm Brian Okken.

00:13 And this episode is brought to you by InfluxDB from Influx Data. We'll tell you more about them

00:18 later. Be sure to connect with us over on Fostadon.org. I'm at M. Kennedy. Brian is

00:25 at Brian Okken. And the show is at Python Bytes. The rights and status of the show are still

00:31 undetermined, Brian, but I'm sure we'll figure that out someday. See the last show to get the joke.

00:36 And join us over at pythonbytes.fm/live, usually Tuesday at 11 a.m. Pacific time to be

00:43 part of the show. Or you can catch also the older episodes there. Or, of course, on your podcast

00:48 players. And with that, Brian, let's dig into some batteries.

00:53 Okay. Well, as we know, Python is the language of the batteries included. But there's, we also have

00:59 lots of cool, cool extra packages on PyPI. Actually, quite a few. And one of the things that I wanted

01:05 to highlight was a few, just a handful of utilities packages that are really kind of fun. And you

01:13 probably knew about them, but maybe forgot. And we've covered some of these in the past. So I wanted

01:18 to highlight this article from Martin Hines called Python's Missing Batteries, Essential

01:23 Libraries You're Missing Out On. And the first project he talks about is Bolt-ons, which is actually

01:30 an amazing, it's an amazing package, but it's so big. The comment here is he could, he could probably do

01:37 an entire article just on Bolt-ons. And I think that's wrong. I think you could do an entire book

01:42 on Bolt-ons and it would be a big book. I agree. There's a lot in there. But a few of the things

01:48 that he highlighted were pretty, pretty cool that I kind of didn't know about. Bolt-ons has a JSON

01:54 utils and a time utils and an iter utils that he's demoing. So with JSON utils, you can just iterate

02:02 with like a, for line and JSON utils, JSON iterator, you can iterate through JSON elements. That's pretty

02:10 amazing. That's pretty cool. I like that. The time utils example was, is a using a date range,

02:17 time utils date range and iterating through days, which is kind of neat. I didn't know you could do

02:23 that. Kind of a cool idea to let me walk through days and get different daytimes. But anyway, there's

02:29 a different step, a step size you can do. You can walk through each week or whatever.

02:32 And then iter utils has a, he's highlighting a couple of things in their utils. One of them is

02:39 get path, which isn't really like a file system path, but it's basically saying I've got a deeply

02:47 nested structure and I want to access it without having to do all the access functions. So it's a way

02:54 to get access to deeply nested things. And then a remap, which is neat. Remap takes a deeply nested

03:02 structure and just changes something inside of it, which is kind of cool. I don't want to go through

03:07 all of the details of this article, but a couple of quick highlights. There's highlighting the sh package

03:13 where you can do shell commands from Python in a fairly nice way. Data validation actually

03:22 is pretty neat. There's pedantic of course, but if that's for like, which is awesome. But there's also

03:30 this validators library, which is neat. And it can do things like validate, making sure that email,

03:35 like validating emails or visa card numbers or an IP address is all format, just validate strings are

03:42 formatted correctly and things. It's pretty neat. Cool. And then the fuzz is a fuzzy matching string,

03:51 fuzzy string matching library, which is kind of cool. I wanted to jump down debugging. There's a stack

03:57 printer that has a, it's basically a really nice stack trace that has, does the error messages, which is kind of

04:04 cool. What else for testing and you can freeze time with the freeze gun library. And then this, the last thing

04:13 is kind of cool. I write a lot of command line applications and there's a, I would not have thought to look for

04:19 this package called TQDM. I don't know what that stands for, but it does, it does like a, what are

04:28 these things? Progress bars would think for command line utilities.

04:31 So TQDM comes from tech quantum, which means progress in Arabic.

04:37 Of course.

04:39 That wouldn't have, I wouldn't have clued me in a good search for it. I love that package. There's a lot of cool

04:44 stuff here. I use like TQDM is just, it's my go-to for this stuff. You know,

04:49 there's a lot of things like, Oh, I need to go over, you know, millions of database records and make

04:55 some change and do a test. And then maybe, I don't know, update some of them. And that might take a

05:00 while. I just did something where I had to do like a report on a bunch of stuff on the talk Python

05:06 courses. And it took nine hours to like go do a bunch of computes for a bunch of courses for each,

05:13 you know, like an insane amount of stuff. And I ran that and you could just see, I saw

05:19 several things. One, it shows you the progress. You can see it doing progress, but it also tells

05:24 you the, the per object per time. So it'll say like processing, you know, 200 records per second.

05:32 For example, as it goes through the list and it also estimates the time, which is why after five

05:37 minutes, I'm like, Oh, this is going to take nine hours. I'm not going to wait for this. It's really

05:41 nice.

05:41 So can you use it if you don't really know how long something's going to take to begin with?

05:46 Yes. And do you have to like, I don't know, like, do you have to give it like it's 10% done or it's 20% done?

05:54 No, it does it all automatically. And I don't really know how I think some things it can figure out.

06:00 Okay.

06:00 And others. Yeah. I don't know how it can actually do that because for example, on the example, on the

06:07 screen, it has a range from zero to a hundred, right? And you can't ask the length of the range.

06:11 Okay. Right.

06:13 But it, it somehow knows.

06:15 Well, I might play with it because right now I've got a, I've got a application that command line thing

06:21 that reboots an instrument and then waits for it to finish. And I just have dots and, and it'd be

06:27 kind of nice to have like a, like a, something like this.

06:29 Yeah. My prior solution was, Oh, let's put out a little dot every so often. Oh, that's too many dots.

06:35 Let's, let's, let's mod it out a little bit higher to like it. Maybe every 20 records,

06:38 we'll put a dot or something like that. Exactly. Yeah. So this is nice. You can just

06:43 wrap an iterator in a TQDM and then loop over it and magic happens. Cool. We'll try it out.

06:49 Yep. All right. Well, that's pretty awesome. Want to hear about more awesome things, Brian?

06:52 Yeah. Let's do awesome. Let's do some awesome, some polars. So polars is as many things in Python

06:59 are these days is the, the rustification in a good way of Python things. So it's kind of

07:05 like pandas, but redone and rust with more of a fluent API that allows it to be more database

07:12 query engine like. And so what I have for us today is the awesome polars, a curated list of polars,

07:19 talks, tools, examples, and articles. Now, many of these awesome lists are extensions,

07:24 and there are a few things in here, like it talks about the Python library. And you may not know,

07:29 there's actually a rust library for polars that you can directly use if you're integrated with rust code,

07:34 but also one for R, one for node. It's got some things like cheat sheets. If people want to go and check out the cheat sheet,

07:42 it's got actually a really nice visualization to show you what reshaping data means with concat

07:49 concat or appending columns side by side from two data frames in a different, with a horizontal concat flag, which I think the visualization of these things is really nice. What do you think of this, Ryan?

08:02 I'm actually, the visualization is what I'm enjoying the most with this cheat sheet. That's nice.

08:09 Yeah, it's really, really nice. And it has a bunch of tutorials and workshops. So if you are trying to get into polars,

08:16 come over here. There's maybe six or seven different examples, a bunch of blog posts,

08:22 a whole bunch, how to integrate it with DuckDB, or how it compares to DuckDB, and then a bunch of videos,

08:29 as well as people in the polars community, right? Like Richie Vink, who created it, but also contributors,

08:38 if you can follow them and ask them questions.

08:41 That's kind of a nice addition of like, on social media, who do you follow? That's pretty cool.

08:46 Yeah. Yeah, it's super nice. So anyway, not a whole lot to go into it there, but yeah, really, really nice. People are into polars, put it here. Also, I kind of wanted to give it a shout out because polars is fairly new.

08:58 And if you've got something that integrates with polars or builds on top of polars in a way that itself is reasonable, you know, come over here and do a PR. I'm sure they're happy to accept it. It says contributions, welcome, exclamation point. So yeah, get in here and contribute.

09:13 They're so welcome.

09:15 You know what else is welcome? Our sponsor this week. So super happy to have a sponsor for the show. As we mentioned at the top, InfluxDB. So InfluxDB is all about the time series data. So this episode is brought to you by Python. This episode of Python Bytes is brought to you by InfluxData, the makers of InfluxDB. InfluxDB is a database purpose built for handling time series data at a massive scale

09:44 for real-time analytics. So developers can ingest, store, and analyze all types of time series data, metrics, events, traces in a single platform.

09:53 Let me ask you a question. How would boundless cardinality and lightning-fast SQL queries impact the way you develop real-time applications?

10:00 Maybe make them real-time, huh?

10:02 InfluxDB processes large time series data sets and provides low latency SQL queries, making it a go-to choice for developers building real-time applications and seeking crucial insights.

10:13 For developer efficiency, InfluxDB helps you create IoT analytics and cloud applications using timestamp data rapidly and at scale.

10:22 It's designed to ingest billions of data points in real-time with unlimited cardinality.

10:27 InfluxDB streamlines building once and deploying across various products and environments from the edge, on-premise, and to the cloud.

10:35 Try it for free at pythonbytes.fm/InfluxDB.

10:39 The link is in your podcast player show notes.

10:41 Thank you to InfluxData and InfluxDB for supporting the show.

10:46 All right, over to you, Brian. What's next?

10:48 Well, this is a pretty quick one, but I wanted to, I know that a lot of people test with Selenium.

10:54 It's a, I know there's lots of other stuff you can do, like Playwright and everything like that, but still Selenium's heavily used.

11:01 And I still have some tests in Selenium.

11:03 And there's a, there has been a change.

11:06 So I want to just make sure everybody is aware.

11:08 If you, there's a, there's, here's an article called running headless Selenium in Python in 2023.

11:16 And the, the catch is basically if you're, well, one, if you're not running headless already, why not?

11:24 The headless is awesome.

11:26 It can basically, you can run, run through a web browser, but don't actually load, don't open it.

11:33 It just, you run it behind, there's no wind anyway.

11:35 It's faster.

11:36 So use headless.

11:37 But if you are already using headless, there's been a change.

11:40 So the, the change is, let's go down, scrolling down.

11:45 There's an example, which is great.

11:47 So Selenium 4.8.0 came out in January.

11:51 And the old way to do things was to, to do, you set up your web driver and you mark headless equals true.

12:00 And you can do this with both Chrome and Firefox had a little different setting, but it also had a headless equals true setup.

12:07 And then you can run headless.

12:09 And it was awesome.

12:10 They took away this dot headless.

12:12 So don't do that anymore.

12:13 If you're using Selenium 4.8 or and above the new way is so for Chrome, you add an argument of headless equals new, dash, dash, headless equals new.

12:24 And it's really add argument.

12:26 If you're listening to this, there's a new options dot add argument.

12:29 And then the same sort of thing with Firefox.

12:32 You just, it isn't a equals new.

12:34 It's just dash, dash, headless.

12:36 But this, this shows you an example.

12:38 Why did they do this?

12:39 Well, it was, there's some description of why there was like an old way and a new way.

12:43 And then Chrome, Chromium had a new headless option that you can add.

12:49 So we want to be able to do the new way.

12:51 So they deprecated the old way to get people to use the new, more powerful.

12:55 And we're also linking to an article from Selenium, which is kind of a funny title.

13:00 So they wanted to get everybody's attention.

13:02 So they knew.

13:03 So they named the article headless is going away.

13:06 Yes.

13:07 Which is funny name.

13:09 And then subtitled it with, now that we have your attention, headless is not actually

13:13 going away.

13:13 Just the convenience method to set it in Selenium.

13:17 So I guess just a public service announcement.

13:19 If you're using Selenium, you got to change your code to use the new Selenium 4.8.

13:24 So that's it.

13:25 Oh, you're on mute.

13:26 So I am.

13:27 I do like it.

13:29 I wonder, though, why you have to pass the command line argument directly.

13:34 And it doesn't just look like, oh, you said headless.

13:36 That means in Chrome now pass --mode this verse.

13:40 Yeah.

13:40 Because it's almost the same, but not the same across the browser platforms.

13:44 Yeah.

13:45 I think it's because there's different.

13:49 I don't know.

13:50 I haven't looked through the explanation, but I think there's other options.

13:54 So it isn't necessarily just that they've changed the way you turn on headless, but there's

13:59 more headless options.

14:00 So they're just building it in so that you can pass in new flags.

14:04 And I think Chromium might end up getting more versions in later or something.

14:09 I don't know.

14:10 Yeah.

14:11 The browser space is an interesting time, isn't it?

14:15 Yeah.

14:15 We fought through the browser wars.

14:17 We've beaten back Internet Explorer 6, only to come back and have Chromium even more dominant

14:24 in certain ways.

14:26 It's interesting because for a usability thing, I'm usually using Vivaldi now, but I use probably

14:32 Vivaldi and Chrome for day-to-day use.

14:34 But for testing, yeah, it's still Chrome.

14:38 I use Chrome and Firefox.

14:41 That's what I use Firefox for is still testing with Firefox.

14:44 Yeah, absolutely.

14:45 Cool.

14:46 You know, just a bit of follow-up on the previous conversation about those different batteries

14:51 that you talked about.

14:52 I love our audience.

14:53 There's so much cool stuff going on over there.

14:55 So Blaze says, I wonder if Rich does anything with TQDM.

14:59 And if you want a definitive answer, how about Will McGugan in the audience says,

15:04 TQDM has a Rich output option.

15:06 Will obviously be in the creator of Rich and many other awesome, awesome things there.

15:12 So nice follow-up.

15:14 Awesome.

15:14 We've turned into the water cooler of Python.

15:16 We sure have.

15:18 All right.

15:19 I have one more thing to share with you all.

15:22 Let's jump into it.

15:22 And that is Gracie.

15:24 So Gracie's an interesting project.

15:28 It's a little bit like your first topic, Brian, in that it has a bunch of kind of utility

15:33 features.

15:34 And this one is around consuming APIs.

15:37 So not creating APIs, but writing clients that talk to them specifically around HTTPX,

15:43 which is one of the absolute go-to ACP libraries for doing sort of modern async style of APIs

15:53 in Python.

15:54 Right?

15:54 Yeah.

15:54 So Gracie, it says, Gracie, graciously manage your API interactions.

16:00 Gracie helps you handle failures, logging, retries, throttling, and tracking for all of your HTTP

16:07 interactions.

16:08 And it uses HTTPX under the hood.

16:10 And it lets you do the, like Gracie, do the boring stuff and you focus on your app is the

16:14 selling point here.

16:15 So this is pretty cool.

16:16 It's not super well-known.

16:18 It's got like 180 stars.

16:19 And it's an interesting library that has a lot of cool functionality.

16:23 It feels like it could use a little bit more polish, but it's still quite neat.

16:29 So let me give you some ideas here.

16:30 So what you do is it's basically you model your API interactions through a class structure.

16:39 It's not quite a hierarchy, but kind of use classes to come up with it.

16:43 So you can come up with an endpoint here.

16:45 And then you create something that derives from the API base class, right?

16:52 Give it a URL.

16:53 And then you give it a bunch of settings.

16:54 And the settings are where kind of the useful stuff is.

16:57 So for example, you can say, I would like to log the request as it's going out the door,

17:02 but only in debug.

17:04 I'd like to log the response and that one a little more frequently at the info level.

17:09 And then you can have a custom message that goes out there.

17:13 And you also can have a parser that will parse the response as a set of functions.

17:20 The first example you see here just says, by default, just given any object called .json on it.

17:27 All right.

17:27 Given the request called .json on it, right?

17:30 So that's kind of handy.

17:32 But what you can do if you go down a little bit, custom validators, is you can actually say, by default,

17:42 just try to convert it to a JSON response.

17:44 But if the status code is not found, then do something else.

17:48 And you can have a series of different status codes.

17:50 So if it, by default, use this parser.

17:53 But if it's like a 400 bad request, then we need to parse it as something else.

17:58 And that could even be like convert it from, you know, maybe in a success case, you get this particular, say,

18:04 pydantic model back.

18:05 But in an error case, you have a totally different structure.

18:08 And you might want to parse it differently into a different pydantic model, something along the line.

18:13 So you can do a lot of cool stuff like that there.

18:16 And yeah.

18:17 And then you just give it the functions that you call that basically invoke the API.

18:22 And of course, because it's based on HTTPX, you can await calling on those functions.

18:27 So yeah.

18:28 Anyway, it looks, it ends up with a pretty clean model for using it.

18:33 What do you think?

18:34 Well, yeah, it'll take some time to get your head around it because of the class thing.

18:38 But it's all stuff that you're going to have to develop anyway.

18:42 So having somebody else do the work.

18:44 So that's pretty good.

18:45 Yeah.

18:45 Yeah.

18:46 There's some nice examples of like throttling.

18:48 And this might be interesting to you, Brian, is it has the ability.

18:53 There's a bunch of different things.

18:54 It has the ability to replay certain data, right?

18:57 So you can also say we're only allowing certain, you know, by default, any 200 category status code is considered success.

19:05 You can say, no, for this one, it has to be a dot created, like HTTP status dot created, not 200 or something like that.

19:13 Or you can give it either okay or created, right?

19:16 You give it a set of options.

19:18 That's pretty cool.

19:19 You can add custom validation.

19:21 You talked about validators at your beginning as well.

19:24 And if you're not using Pydantic or something that kind of does its own custom validation, you can still even add more stuff.

19:32 Like not only does this have to be a string, but it has to be, I don't know, an email of this type or whatever, right?

19:39 Like of this, say the domain of our company, right?

19:42 Something like that.

19:43 So you can add these custom validators.

19:44 And it comes with a retry, built in retry for how do you handle the retries?

19:50 How many attempts?

19:51 What do you do in terms of logging?

19:54 You know, about retries and failures.

19:57 What do you do if, you know, you can say, I want to retry three times.

20:01 And if none of them work, I don't care.

20:04 Just keep going.

20:04 Don't break my application.

20:05 Or please do.

20:06 Don't, you know, raise an exception.

20:08 You might say, well, why would you ever not want to break it?

20:10 Like maybe you're trying to write to some sort of audit log to say this happened.

20:15 And if the server that just records what happened goes down, you don't want to start crashing your app, right?

20:19 There's like scenarios where you might not really care about that.

20:22 Also throttling, which is pretty neat.

20:24 You can say any time that the URL contains examples of Pokemon things.

20:29 So it has, you know, a regular expression for Pokemon.

20:31 I want maximum 10 requests for every one and a half minutes.

20:36 And then you could actually, it has a cool output too.

20:38 You know, if you print out just the rule it says, which is an object, it says 10 requests per 90 seconds for URLs matching this regular expression, which is kind of nice.

20:47 Oh, cool.

20:48 And yeah, the final thing.

20:50 Some, I don't really know where it is in here, but yeah, you can also have it throw certain exceptions.

20:55 So how, you know, how does that parser type scenario for different HTTP status codes I told you about?

21:01 So you can say, if it's a bad request, please throw, you know, some exception class that you come up with.

21:06 Right.

21:07 So instead of just saying bad request, it could potentially have more details.

21:11 You might build a parse information into it and then raise that exception.

21:14 There's, there's some pretty neat things.

21:17 And the final thing, by the way, rich integration right there, it requires you to install rich.

21:21 If you want fancy output on, it'll tell you sort of it's, it'll report on how it's interacted with the API endpoint.

21:32 So you've got to do like a bunch of processing, you know, I told you about like, I'm going to transform a bunch of things.

21:36 I use TQDM.

21:37 But if you're going to do that at the end, you could ask, well, how'd it go?

21:41 And it'll give you this like summary report of how much success and how much failure and what's the average latency and status codes and requests per seconds and all of these.

21:50 And it'll do that in text form or in rich style.

21:53 Final thing.

21:55 It will record and replay API interactions for testing purposes.

22:00 So if you want, you know, if it's really tricky to mock out some complex interaction, you'd say, well, I want it to be as exactly close to real as possible.

22:09 You could just one time do those API calls and then replay them back, put it either record mode or replay mode.

22:17 And the backend that stores that could be a SQLite database or a MongoDB database that's automatically integrated.

22:24 And you just give it that and say, when I talk to the server, remember what you did and store it over here.

22:29 And then you can play that back for testing.

22:31 Oh, wow.

22:31 Cool.

22:32 So, yeah.

22:33 Anyway, people can check this out and see what they think.

22:36 But I think it almost looks like it was a system pretty much designed.

22:41 Well, one of the obvious use cases is to build a custom thing to test your application.

22:49 Because there's a bunch like all the utilities there to really interrogate something.

22:54 Absolutely.

22:55 Yeah.

22:55 You get that report and you get the replay, record replayability, the logging.

23:00 Yeah.

23:00 A lot of that stuff is there.

23:01 It's pretty neat.

23:02 Yeah.

23:03 Cool.

23:03 Nice.

23:05 Well, that's it for that one.

23:06 Yeah.

23:07 I guess that's all of our items, isn't it?

23:09 It is.

23:10 And for extras, I don't have any extras.

23:13 Do you have any extras?

23:15 I do.

23:16 I just have one.

23:17 And then we'll get to our joke.

23:18 So, for the extras, do you know what, Brian?

23:20 Look at this.

23:21 Look at, here it is.

23:22 You got in the App Store.

23:23 Yay.

23:24 I got in the iOS App Store, too.

23:26 So, finally, finally, finally, the Talk Python mobile apps are out on all of the app stores.

23:32 So, go get them.

23:33 Just talkpython.fm/apps, I believe, will take you there.

23:37 Redirect over to the training site.

23:39 But, yeah.

23:40 They're available on iPhone, Android, tablets, iPad, Android tablets as well.

23:48 Maybe more coming.

23:49 We might have even desktop apps coming pretty soon, depending on how successful we are with all this.

23:55 But, yeah.

23:56 So, this is out.

23:57 People can check it out.

23:58 And as a way to celebrate finally getting this done after four months of work, first of all, wrote a blog post.

24:06 Maybe I'll add it, throw the link in the notes.

24:08 Yep.

24:08 I'll throw it in for people.

24:09 I talked about some of the design choices about how and why we chose things like Flutter and so on as the mobile app framework.

24:18 But the one thing for people to know out there, and this is a bit timely, is if you download and install the mobile app before, what day?

24:27 Today is Tuesday, May 16th.

24:30 If you do that before May 22nd, so download the app before May 22nd, inside the app only, the Up and Running with Git course, which is normally $39, is completely free to sort of celebrate the launch of the app.

24:44 So, you go in there, go find the courses, go to the free section, join the Git course, and you'll have it forever, not just for a little time.

24:51 But the only way to get it is to download and install the app, which is free, and then go put the Git course into your account.

24:58 I just downloaded it.

24:59 I'm opening it right now.

25:00 Awesome.

25:02 Awesome.

25:02 So, one of the things I'm excited about this is because, I mean, when I'm doing a course, like not giving a course, but learning from one, I do like to have it on my computer screen.

25:13 But there's often times where I've got like time to kill.

25:16 So, I'd like to sort of listen to some of the conversation and listen to it.

25:19 And yeah, I'm going to look at some of the stuff on my phone, but a lot of it is kind of following along, but I'm listening, and then I'll go through and watch the same stuff later on the computer and walk through it.

25:31 So, I really like this addition of having a mobile app.

25:34 This is pretty cool.

25:36 Thanks so much, Brian.

25:36 Yeah, there's a couple things why you might need it.

25:39 People are like, well, why don't you just watch it on the web?

25:40 Like, especially on iPhone, you can't get rid of that navigation section around the browser.

25:47 So, you end up watching like a postage stamp size thing, which is not ideal.

25:50 It won't auto-advance because ad companies are evil, and iOS blocked them from playing ads all the time, which, you know, gobbles up everyone else as well, unfortunately.

26:02 Okay, so on your app, it'll just jump to the next thing then?

26:07 Yeah, it just keeps playing smoothly, as you would imagine.

26:10 And then the other thing that's important is you can download content offline.

26:13 Like, if you're going on a trip or on the train, or some people even use it if they work at, you know, like government institutions that have high levels of security, and they want to, like, research labs and stuff.

26:27 If they want to be able to take the course at their work, but their work is super restrictive about what they can interact with, you could, you know, install, download a whole course onto your tablet, set it next to you, and watch it at your work.

26:39 Yeah, so those are the reasons why it exists.

26:43 But anyway, long time coming, super happy about it.

26:45 That's my extra.

26:46 Cool.

26:46 Download it, get the Git course.

26:49 All right.

26:50 Well, how about a joke?

26:51 Ah, this is a good one.

26:53 So, you may wonder, you may have friends who are like, Brian, you do Python, you do C++, you wrote a book on pytest.

27:01 Like, how did you get so good at this?

27:04 So, this kind of riffs on that theme.

27:06 There's two developers here.

27:09 First one, she says, how do you code so well?

27:13 The expert developer, she says, practice.

27:16 And the first person didn't really hear, like, it must be an innate gift, a gift from God.

27:22 It's practice.

27:22 I'll never understand how some people are so talented.

27:26 A mystery.

27:27 Practice.

27:27 Yeah.

27:29 Right?

27:30 Yeah.

27:30 What do you think?

27:31 Well, this is great.

27:33 And it applies to so many things, of course.

27:35 But one of my daughters is dealing with this right now.

27:39 She's been doing, for about a year, doing aerial silks, aerial arts.

27:44 And she's working on it and exercising and stuff every day.

27:48 And it was really hard at first.

27:52 And now she's pretty good.

27:53 And so many people have said, oh, you're just naturally talented at that.

27:57 It makes her mad because it's not natural.

28:01 I've had to work at it.

28:02 Coding as well.

28:03 So, obviously.

28:04 Obviously.

28:05 Yeah.

28:06 It's not just coding, but coding certainly.

28:09 Yeah.

28:09 Podcasting, writing blog posts, everything around what we do.

28:14 Practice.

28:15 Yeah.

28:15 Absolutely.

28:16 Practice.

28:16 Nice.

28:17 Nice way to end it.

28:18 So, good show.

28:19 Yeah.

28:20 Absolutely.

28:20 Very, very uplifting.

28:22 We'll end it on a growth mindset today, Brian.

28:24 Thanks for being here.

28:25 Thank you.

28:25 And thanks, everyone, for coming.

Back to show page