WEBVTT 00:00:00.080 --> 00:00:05.200 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. 00:00:05.200 --> 00:00:10.380 This is episode 111, recorded January 4th, 2019. 00:00:10.380 --> 00:00:11.800 I'm Michael Kennedy. 00:00:11.800 --> 00:00:12.720 I'm Brian Okken. 00:00:12.720 --> 00:00:14.260 Hey, Ryan. Can you believe it's 2019? 00:00:14.260 --> 00:00:16.780 Yeah, it's kind of hard to remember to say that. 00:00:16.780 --> 00:00:18.020 Yeah, it's going to take a while. 00:00:18.020 --> 00:00:22.440 So before we get into the topics, I just want to say thank you to Datadog, 00:00:22.440 --> 00:00:23.520 they're sponsoring this episode. 00:00:23.520 --> 00:00:26.020 Check them out at pythonbytes.fm/datadog. 00:00:26.020 --> 00:00:27.360 More about that later. 00:00:28.020 --> 00:00:31.160 I never really enjoy the built-in logging in Python. 00:00:31.160 --> 00:00:33.760 It's never seemed like super, super clear to me. 00:00:33.760 --> 00:00:38.440 So I've ended up using other packages, something like logbook or something like that, 00:00:38.440 --> 00:00:39.800 or maybe just a print statement. 00:00:39.800 --> 00:00:43.460 But what you found today, Brian, is pretty sweet, actually. 00:00:43.460 --> 00:00:46.500 It might convince me to stop using logbook and use something else. 00:00:46.500 --> 00:00:48.420 You know, I was playing with this morning. 00:00:48.420 --> 00:00:51.240 So what we're talking about is, I think it's logguru. 00:00:51.240 --> 00:00:53.360 I think that's how you pronounce it. 00:00:53.360 --> 00:00:54.580 L-O-G-U-R-U. 00:00:54.580 --> 00:00:58.280 All right, like log and guru smushed together, joined by the G. 00:00:58.280 --> 00:00:58.600 Yeah. 00:00:58.600 --> 00:00:59.920 Or it could be logguru. 00:00:59.920 --> 00:01:00.740 Logguru. 00:01:00.740 --> 00:01:01.420 I don't think so. 00:01:01.420 --> 00:01:02.120 I'm going with logguru. 00:01:02.800 --> 00:01:06.360 And the tagline is, Python logging made stupidly simple. 00:01:06.360 --> 00:01:11.420 And I think this is, it's like a one API function for the most part. 00:01:11.420 --> 00:01:13.940 So the built-in logging for Python, it does a lot. 00:01:14.200 --> 00:01:21.240 And you can have like multiple, multiple logging entry points and multiple logging output points and everything. 00:01:21.240 --> 00:01:28.040 And logguru kind of took the model of everything gets logged to all the places. 00:01:28.040 --> 00:01:30.800 And there's a default place that's standard error. 00:01:31.220 --> 00:01:34.900 And that's better than print mucking up your standard output. 00:01:34.900 --> 00:01:39.220 And by default, it just, you know, just a few lines of code and it works just fine. 00:01:39.220 --> 00:01:42.320 You can just say from logguru, import logger. 00:01:42.320 --> 00:01:46.820 And just use the logger and say like debug or info or whatever. 00:01:47.440 --> 00:01:57.900 But then if you want to do more advanced things, like one of the things I had to play with because I couldn't believe it was this easy, was file logging and log rotation. 00:01:57.900 --> 00:02:02.820 So let's say you're logging some stuff and you want to be able to store it into, log it into a file. 00:02:02.820 --> 00:02:10.400 And then at some point, like make that a new file, like a date stamped file or time stamped or something. 00:02:10.400 --> 00:02:12.700 And it just has that really easy. 00:02:12.800 --> 00:02:19.580 And then you can give it different options for if your file gets to like 50 megabytes, at that point, start a new file. 00:02:19.580 --> 00:02:21.340 And there's even like compression. 00:02:21.340 --> 00:02:25.140 So when you're rolling over to the new one, take the old one and zip it. 00:02:25.140 --> 00:02:29.380 Or you can time it and just do a new log every hour or a new log every day. 00:02:29.380 --> 00:02:30.760 I love the zipping aspect. 00:02:30.760 --> 00:02:31.560 That's awesome. 00:02:31.560 --> 00:02:33.820 It just does that automatically or do you have to tell it to? 00:02:33.820 --> 00:02:35.000 You have to tell it to. 00:02:35.000 --> 00:02:37.240 It's a fairly simple, easy thing. 00:02:37.680 --> 00:02:44.800 And one of the bonuses of this package is the readme on GitHub is kind of a tour of all the features with examples. 00:02:44.800 --> 00:02:49.140 So it's really easy to pop through and see what's going on. 00:02:49.140 --> 00:02:53.920 I mean, I really spent like just a few minutes trying it out and I already love it. 00:02:53.920 --> 00:03:00.760 So I think of this as the logging API that fits in my brain and I can do things right off the bat. 00:03:00.760 --> 00:03:01.480 It's cool. 00:03:01.600 --> 00:03:02.240 Yeah, that's super cool. 00:03:02.240 --> 00:03:09.220 On one of my websites, I had like a bunch of logging happening and I went and checked it out, checked out the log directory. 00:03:09.220 --> 00:03:11.540 And it was like five gigs of text files. 00:03:11.540 --> 00:03:15.420 But they compressed down to like 200 megs or something totally manageable. 00:03:15.420 --> 00:03:19.900 So that's pretty awesome that you can have it kind of do that step for you in the background. 00:03:19.900 --> 00:03:22.780 A couple of things strike me really as nice here. 00:03:22.780 --> 00:03:24.140 One is the use of color. 00:03:24.840 --> 00:03:31.220 It'll print out like here's the time, here's the log level, like info or error or whatever, the message and so on. 00:03:31.220 --> 00:03:38.340 And it'll actually show those in different colors because by default it prints just to logs to the terminal, right? 00:03:38.340 --> 00:03:40.000 Standard out or something like that. 00:03:40.000 --> 00:03:40.280 Yeah. 00:03:40.280 --> 00:03:41.320 And it looks really nice. 00:03:41.320 --> 00:03:45.020 So I tried it both on it just to make sure it was cross compatible and stuff like that. 00:03:45.020 --> 00:03:48.000 I tried it both on a Mac and on a Windows machine. 00:03:48.300 --> 00:03:54.040 And then I also tried it if I'm logging stuff from and running it within PyCharm, how does that look? 00:03:54.040 --> 00:03:56.200 And all of this looks really good still. 00:03:56.200 --> 00:03:57.220 That's awesome. 00:03:57.220 --> 00:04:03.380 And it also has the ability to wrap functions and catch the unhandled errors. 00:04:03.380 --> 00:04:07.360 So the syntax is like log or dot catch all or something. 00:04:07.360 --> 00:04:08.240 It's a decorator. 00:04:08.240 --> 00:04:13.800 And if there's an error, it'll print a colorized, properly indented, formatted traceback. 00:04:13.800 --> 00:04:14.140 Yeah. 00:04:14.220 --> 00:04:16.420 And then it has some traceback options too. 00:04:16.420 --> 00:04:18.860 And the traceback options are even pretty cool. 00:04:18.860 --> 00:04:22.220 They like blow it up into these little mini graph. 00:04:22.220 --> 00:04:30.040 And you can specify how deep, how like just the traceback for the function that they got hit or its parent or how many parents. 00:04:30.040 --> 00:04:30.900 That's pretty cool. 00:04:30.900 --> 00:04:31.140 Yeah. 00:04:31.140 --> 00:04:36.840 One of the things I like about the honesty of here is the last feature is crossed out. 00:04:36.840 --> 00:04:40.400 The last feature says it's 10 times faster than built-in logging. 00:04:40.560 --> 00:04:44.300 No, that's crossed out because clearly adding all these features isn't free. 00:04:44.300 --> 00:04:47.080 It does cost a little bit of performance. 00:04:47.080 --> 00:04:54.120 But there are plans for some of these, some of the things to be critical functions to be implemented and see in the future. 00:04:54.120 --> 00:04:56.380 I think it's convenient right away. 00:04:56.520 --> 00:05:04.080 One of the things I was always interested about is to how to figure out how to get email notification in some cases. 00:05:04.080 --> 00:05:12.620 Like in particular, if you had a critical log error in a critical something, sending off an email to the right person. 00:05:12.620 --> 00:05:15.260 I wouldn't know how to do that right off the bat. 00:05:15.380 --> 00:05:21.300 But this one apparently works cleanly with the notifiers library to be able to send email. 00:05:21.300 --> 00:05:21.640 Yeah. 00:05:21.640 --> 00:05:23.280 Notifiers is nice as well. 00:05:23.280 --> 00:05:24.220 I think we've covered it before. 00:05:24.220 --> 00:05:29.960 One other final thing here is you can actually put color into your statements as well. 00:05:29.960 --> 00:05:35.780 So if I want to have like, they've got a little screencast-y GIF thing on the GitHub repo you can just watch. 00:05:35.780 --> 00:05:38.360 Like it says, there are several options available. 00:05:38.360 --> 00:05:43.060 If you want options to be blue, you put bracket blue, like HTML tags around it. 00:05:43.120 --> 00:05:44.300 And it colorizes it. 00:05:44.300 --> 00:05:47.000 So I think it's really nice for communicating back what's going on. 00:05:47.000 --> 00:05:47.320 Yeah. 00:05:47.320 --> 00:05:49.020 I'm sure it does a lot of cool features. 00:05:49.020 --> 00:05:57.120 One of the things I like about the API is once you've figured out something, other people will be able to tell what you're doing because it's not confusing to read. 00:05:57.120 --> 00:05:57.440 Yeah. 00:05:57.440 --> 00:05:58.520 It's very cool. 00:05:58.520 --> 00:06:00.560 This might be my new favorite logging library. 00:06:00.560 --> 00:06:06.060 Now I have to get over the inertia of actually having my other stuff already working and wanting to switch to it. 00:06:06.060 --> 00:06:06.700 That's going to take a while. 00:06:06.700 --> 00:06:07.260 But this is cool. 00:06:07.260 --> 00:06:07.640 I like it. 00:06:07.640 --> 00:06:08.040 Good find. 00:06:08.480 --> 00:06:13.240 So we had a pretty big episode back in July. 00:06:13.740 --> 00:06:25.620 We had Brett Cannon and Carol Willing on to talk about how Gita Van Rossum had stepped down as the BDFL, the overseer of the Python project. 00:06:25.620 --> 00:06:30.200 Still involved as a core developer, but not making all the decisions and taking all the weight. 00:06:30.200 --> 00:06:30.420 Right? 00:06:30.420 --> 00:06:30.840 Remember that? 00:06:30.840 --> 00:06:31.100 Yeah. 00:06:31.220 --> 00:06:41.380 Well, things have more or less been on hold, stalled out until they can somehow come up with a group of core developers can come up with a way to govern themselves. 00:06:41.380 --> 00:06:51.340 So, for example, Lucas Lange was looking at maybe moving the releases of Python from every 18 months to yearly, which has a bunch of advantages. 00:06:51.720 --> 00:06:54.000 But that's a change that has to be decided on. 00:06:54.000 --> 00:06:55.700 They had no way to decide things. 00:06:55.700 --> 00:06:58.400 So all sorts of stuff like that had just been put on hold. 00:06:58.400 --> 00:07:03.700 Well, we've covered the different governance models that were being considered. 00:07:03.700 --> 00:07:12.180 The big news this week is Python now has decided that it has a new governance model, and they have decided on which one it's going to be. 00:07:12.180 --> 00:07:12.520 Yes. 00:07:12.520 --> 00:07:13.860 It's a, yeah. 00:07:13.860 --> 00:07:14.300 Finally. 00:07:14.300 --> 00:07:16.240 Finally, things can start going. 00:07:16.240 --> 00:07:18.080 Now, don't get too excited. 00:07:18.080 --> 00:07:18.580 Yeah. 00:07:18.580 --> 00:07:20.200 There's a lot of holes left. 00:07:20.200 --> 00:07:21.200 There are a lot of holes. 00:07:21.480 --> 00:07:24.220 So what has been decided is the governance model. 00:07:24.220 --> 00:07:30.500 They still need to decide how the new governance model actually drives Python the project itself. 00:07:30.500 --> 00:07:32.580 So there's like a two-step process. 00:07:32.580 --> 00:07:39.040 Find out how we're going to make decisions, and then the first decision is how does that new organization manage Python. 00:07:39.040 --> 00:07:40.500 So we're like halfway there. 00:07:40.500 --> 00:07:40.960 All right. 00:07:40.960 --> 00:07:43.860 I think also there's still elections to be who's going to be part of this thing. 00:07:43.860 --> 00:07:46.240 So let me give you the rundown by way of Brett Cannon. 00:07:46.240 --> 00:07:51.460 So Brett Cannon, also a core developer, has been on the show a couple times, and it's including the one that I mentioned. 00:07:51.460 --> 00:07:59.460 And so he did a really nice write-up of what was the problem, where have we been, what were the options, and how did they decide. 00:07:59.620 --> 00:08:03.880 So we covered before, like we said, there were seven governance proposals. 00:08:04.680 --> 00:08:15.120 One from like, we'll elect a new dictator, a new BDFL, maybe without the FL for life part, down to maybe we'll have like a panel or something like that. 00:08:15.120 --> 00:08:16.780 So there's some votes. 00:08:16.780 --> 00:08:27.760 The votes were open to all core developers, and they decided we're not going to have other people vote who are not core developers, because this is about the core developers governing themselves. 00:08:27.920 --> 00:08:31.640 And why should other people decide how they get governed, basically, right? 00:08:31.640 --> 00:08:33.000 They don't have as much skin in the game. 00:08:33.000 --> 00:08:33.380 Yeah. 00:08:33.380 --> 00:08:35.920 So people who are deciding sort of their own fate voted. 00:08:35.920 --> 00:08:43.000 And in the end, the winning one was PEP 8016, which is called the Steering Council. 00:08:44.000 --> 00:08:53.160 So from now on, Python will be driven or controlled or led by a steering council, which is very similar to what Django's project organization actually looks like. 00:08:53.160 --> 00:08:59.740 They said, Brett said even that some of the language of the PEP here was copied and pasted directly from Django. 00:08:59.740 --> 00:09:00.780 Interesting. 00:09:00.920 --> 00:09:01.040 Yeah. 00:09:01.040 --> 00:09:05.580 So this is a council of five people who will determine how to run the Python project. 00:09:05.580 --> 00:09:14.540 So the only thing that they can't decide, they basically have absolute power, this group of five developers. 00:09:14.540 --> 00:09:18.820 However, the one thing they cannot decide is how the council is elected. 00:09:18.820 --> 00:09:24.060 So they can't go, you know, this council thing in elections, we don't like them. 00:09:24.060 --> 00:09:25.440 We're going to get rid of those. 00:09:25.440 --> 00:09:25.720 Right. 00:09:25.720 --> 00:09:29.180 Other than that, though, they basically have BDFL like powers. 00:09:29.180 --> 00:09:29.800 Right. 00:09:29.800 --> 00:09:30.520 That's good. 00:09:30.620 --> 00:09:41.660 It means basically that Python will not, project will not be leaderless, but it doesn't directly solve how to get the design and things like do we change the release cycle and things like that. 00:09:41.660 --> 00:09:42.500 Cool, right? 00:09:42.500 --> 00:09:42.800 Yeah. 00:09:42.800 --> 00:09:43.760 Right. 00:09:43.760 --> 00:09:46.120 So now we got to figure out who the council is. 00:09:46.120 --> 00:09:46.320 Yeah. 00:09:46.320 --> 00:09:48.120 So the next step is to elect the council. 00:09:48.120 --> 00:09:50.100 That'll be done Monday. 00:09:50.100 --> 00:09:52.720 So three, three, four days from now, three days. 00:09:52.720 --> 00:09:56.680 And that starts on Monday and then goes to January 20th. 00:09:56.680 --> 00:10:00.140 And then somewhere around there we'll know. 00:10:00.320 --> 00:10:01.760 Actually, no, that's nominations. 00:10:01.760 --> 00:10:04.140 The voting starts on Monday, January 21st. 00:10:04.140 --> 00:10:08.320 So sometime in February we'll know who, which five people are on the steering council. 00:10:08.320 --> 00:10:09.400 How do you feel about this? 00:10:09.400 --> 00:10:14.640 I think it's the right, well, not that nobody asked my opinion, but this seems reasonable to me. 00:10:14.640 --> 00:10:15.260 Yeah, I agree. 00:10:15.260 --> 00:10:15.900 You have a mic. 00:10:15.900 --> 00:10:19.520 You get a, that's the power of the mic is you get to just state your opinion, right? 00:10:19.520 --> 00:10:20.620 Yeah. 00:10:21.900 --> 00:10:24.200 No, I think it's, I think this is totally reasonable. 00:10:24.200 --> 00:10:26.600 I think there's a couple of things. 00:10:26.600 --> 00:10:34.400 I thought it was really interesting the discussion between having an even or an odd number of people on the council, right? 00:10:34.460 --> 00:10:37.460 Because this way there's always going to be a majority. 00:10:37.460 --> 00:10:39.680 There could never be a deadlock, right? 00:10:39.780 --> 00:10:45.480 Whereas if they had been even, you could have to have like a definitely win over a majority, right? 00:10:45.480 --> 00:10:50.380 If there were six instead of five, you always got to get that little extra vote to go through. 00:10:50.380 --> 00:10:53.320 But yeah, I think it's, you know, this seems totally reasonable to me. 00:10:53.560 --> 00:11:00.300 I think there would have been a lot of value in finding the next BDFL without the FL part, right? 00:11:00.300 --> 00:11:02.480 The next leader dictator type. 00:11:02.480 --> 00:11:09.140 I think that kind of might've been my favorite, but it's such, it's just such a risky proposition. 00:11:09.140 --> 00:11:13.720 Because on one hand, if you get the right person, they can just move quick and it could be awesome. 00:11:13.720 --> 00:11:20.700 But if you get somebody who doesn't take it in the right direction or a direction that you think is the wrong direction, like it could really go off the rails. 00:11:20.700 --> 00:11:27.600 So this certainly seems like a safe path forward and it's definitely more community driven than it has been in the past. 00:11:27.600 --> 00:11:28.000 Yeah. 00:11:28.000 --> 00:11:29.500 I don't know if this will slow down. 00:11:29.500 --> 00:11:38.320 So one of the things that Brett brought up is they still haven't figured out really how to, how to guide the language itself for language design. 00:11:38.320 --> 00:11:42.500 And so, yeah, it'll be interesting to watch how that. 00:11:42.500 --> 00:11:42.760 Yep. 00:11:42.760 --> 00:11:43.400 And sure will. 00:11:43.400 --> 00:11:47.240 So there's a lot of detail in Brett's article, so you should all go check it out. 00:11:47.240 --> 00:11:50.640 But it's, it looks like things are starting to move again. 00:11:51.080 --> 00:11:53.580 Just that six short months later. 00:11:53.580 --> 00:11:53.920 Yeah. 00:11:53.920 --> 00:11:54.260 Perfect. 00:11:54.260 --> 00:11:59.140 So one of the things you often have to do is work with files and paths and all this kind of stuff. 00:11:59.140 --> 00:12:01.700 And I don't know, you tell me, Brian, am I living in the path? 00:12:01.700 --> 00:12:08.520 I still, if I got to work with files, import OS, OS.path, I still probably do that just out of habit. 00:12:08.520 --> 00:12:09.760 Am I doing it wrong? 00:12:09.760 --> 00:12:10.660 You're doing it wrong. 00:12:10.660 --> 00:12:12.120 At least according to Trey. 00:12:12.460 --> 00:12:13.500 And I agree. 00:12:13.500 --> 00:12:15.500 Now, I am with Trey. 00:12:15.500 --> 00:12:19.780 So Trey Hunter wrote a blog post called Why You Should Be Using Pathlib. 00:12:19.780 --> 00:12:30.100 And it's basically just a fairly convincing argument talking about some of the different benefits of pathlib over OS.path and OS and glob and stuff. 00:12:30.520 --> 00:12:32.420 I actually didn't know before reading this. 00:12:32.420 --> 00:12:35.860 I didn't know that you could do glob-like stuff with the pathlib. 00:12:35.860 --> 00:12:36.980 And recursive globbing. 00:12:36.980 --> 00:12:37.980 Yeah, recursive. 00:12:37.980 --> 00:12:44.780 I had actually looked for that before because in some, some shells you can do star star to recursively look for stuff. 00:12:44.900 --> 00:12:51.060 And you can use star star for, for the glob library or the glob, whatever. 00:12:51.060 --> 00:12:52.540 But it's built in. 00:12:52.540 --> 00:12:55.140 You can do our glob with, with pathlib. 00:12:55.140 --> 00:12:55.780 It's pretty cool. 00:12:55.780 --> 00:12:56.520 That's pretty awesome. 00:12:56.520 --> 00:13:02.160 Some of the things that are nice about it, he's comparing it to OS path and OS.path. 00:13:02.160 --> 00:13:03.460 It's really working. 00:13:03.460 --> 00:13:04.480 It's a string library. 00:13:04.480 --> 00:13:07.860 It's passing it, figuring out strings that represent paths. 00:13:07.860 --> 00:13:12.960 But now we have a more functional, the pathlib uses the path object, 00:13:13.540 --> 00:13:20.660 which is a more functional thing that all of the path method, path object methods, return path objects. 00:13:20.660 --> 00:13:22.180 So you can chain them together. 00:13:22.180 --> 00:13:22.820 Right. 00:13:22.820 --> 00:13:24.200 I love the fluent API. 00:13:24.200 --> 00:13:28.040 Like you say path and then give it like a directory. 00:13:28.040 --> 00:13:33.220 You can say make dir and all nice options like parents equals true exists. 00:13:33.220 --> 00:13:33.580 Okay. 00:13:33.580 --> 00:13:35.420 So it'll create like the whole directory chain. 00:13:35.420 --> 00:13:36.900 It won't fail if it already exists. 00:13:36.900 --> 00:13:42.080 Like that is like that right there might convince me to like put my OS.path away. 00:13:42.280 --> 00:13:42.520 Yeah. 00:13:42.520 --> 00:13:48.780 And also like right off the batty, that shows an example where how do you import OS path and OS? 00:13:48.780 --> 00:13:56.400 Do you, do you import all the, all the little pieces from there so that you can have shorter methods? 00:13:56.400 --> 00:14:00.060 Or do you just say OS path and you have to say OS path everywhere? 00:14:00.280 --> 00:14:02.820 And it makes for kind of unwieldy code. 00:14:02.820 --> 00:14:07.200 I copied some of the examples that he had into our show notes. 00:14:07.520 --> 00:14:10.160 It's just really kind of a cool thing. 00:14:10.160 --> 00:14:21.540 One of the things I didn't realize is that like the, like if you're opening a file, you can say like with open file name as some file object, then you work with it. 00:14:21.540 --> 00:14:22.620 It closes automatically. 00:14:22.980 --> 00:14:26.680 That all works with a path lib objects now too. 00:14:26.680 --> 00:14:31.820 So you can use a lot of the other standard library things just with path lib objects. 00:14:31.820 --> 00:14:32.080 Right. 00:14:32.080 --> 00:14:33.740 Long as you're on Python three, six or above. 00:14:33.740 --> 00:14:34.340 Yes. 00:14:34.340 --> 00:14:34.820 Yeah. 00:14:34.820 --> 00:14:36.220 Now this is really cool. 00:14:36.220 --> 00:14:36.700 I like it. 00:14:36.700 --> 00:14:37.260 I definitely like it. 00:14:37.260 --> 00:14:38.080 Why wouldn't you be? 00:14:38.080 --> 00:14:38.700 Exactly. 00:14:38.700 --> 00:14:39.540 Why wouldn't you be? 00:14:39.540 --> 00:14:40.560 It would be wrong. 00:14:40.560 --> 00:14:43.700 Not as wrong as using legacy Python, but you know, it's okay. 00:14:45.300 --> 00:14:49.100 I do know that some of the Linux distributions lag behind a ways. 00:14:49.100 --> 00:14:52.020 And you know, if you haven't upgraded that for a while, that could be a reason actually. 00:14:52.020 --> 00:14:55.620 But yeah, this is definitely something people should be checking out. 00:14:55.620 --> 00:14:58.780 I really like the fluent API, the chaining. 00:14:58.780 --> 00:14:59.440 That's cool. 00:14:59.440 --> 00:14:59.940 All right. 00:14:59.940 --> 00:15:03.460 Now, before we get to the next one, Brian, let me tell you about our sponsor, Datadog. 00:15:03.460 --> 00:15:06.000 They've sponsored many of the episodes and they're a big supporter of the show. 00:15:06.000 --> 00:15:08.920 So we're really happy to have them back this year. 00:15:09.340 --> 00:15:14.960 And they're a cloud scale monitoring platform that brings together metrics, logs, distributed 00:15:14.960 --> 00:15:16.280 traces all in one place. 00:15:16.280 --> 00:15:20.440 Like one of the big problems you have is, well, I made a request to my web server. 00:15:20.440 --> 00:15:22.240 The web server talked to this service. 00:15:22.240 --> 00:15:23.440 That server's talked to a database. 00:15:23.440 --> 00:15:25.760 Like those all seem like separate things, right? 00:15:25.760 --> 00:15:29.480 But if you want to track them all together, right, you can use Datadog for that. 00:15:29.480 --> 00:15:35.580 So you can trace clients, including support for auto instrumenting, like automatically tracking 00:15:35.580 --> 00:15:38.800 requests through things like Django, Flask, Postgres, and others. 00:15:39.020 --> 00:15:44.380 So you get all the tracking across service boundaries, which is pretty sweet for troubleshooting 00:15:44.380 --> 00:15:46.520 slow requests and optimizing your Python apps. 00:15:46.520 --> 00:15:52.840 So you can start monitoring your environment with a free trial and Datadog will send you a 00:15:52.840 --> 00:15:54.180 cool little Datadog t-shirt. 00:15:54.180 --> 00:15:57.240 Just go to pythonbytes.fm/Datadog and get started. 00:15:57.240 --> 00:15:57.720 Very cool. 00:15:57.720 --> 00:15:58.420 Yeah, for sure. 00:15:58.420 --> 00:15:59.160 Thank you, Datadog. 00:15:59.160 --> 00:16:06.120 Now, this next one is actually a two-in-one sort of thing because there's a new, new-ish, 00:16:06.200 --> 00:16:11.260 let's call it new-ish library for visualizing and stuff, mostly around data science and 00:16:11.260 --> 00:16:11.720 notebooks. 00:16:11.720 --> 00:16:17.160 So we've talked about things like people know about matplotlib and Seaborn and other stuff, 00:16:17.160 --> 00:16:19.380 but maybe they haven't heard about Altair. 00:16:19.380 --> 00:16:25.020 So Altair comes from Jake Vanderplass and Brian Granger, who are both really big in the data 00:16:25.020 --> 00:16:25.640 science space. 00:16:25.640 --> 00:16:29.900 And this is a really cool declarative way to visualize stuff in Python. 00:16:30.280 --> 00:16:34.300 Have you ever looked at matplotlib and you're like, why do I have to do all these things? 00:16:34.300 --> 00:16:36.100 I just want a line on the screen. 00:16:36.100 --> 00:16:38.160 There's so many steps, it seems like. 00:16:38.160 --> 00:16:41.240 Well, Altair seems to avoid that. 00:16:41.240 --> 00:16:45.820 So basically, it assumes that you're working with some sort of Pandas data frame, right? 00:16:45.820 --> 00:16:49.280 So it takes Pandas stuff and visualizes it really well. 00:16:49.500 --> 00:16:56.400 So for example, if I had a Pandas data frame called cars, I could say chart of cars, mark 00:16:56.400 --> 00:17:01.420 points, and just, you know, X in code, X equals horsepower, Y equals miles per hour, and it 00:17:01.420 --> 00:17:02.440 colors it based on the origin. 00:17:02.440 --> 00:17:03.700 Boom, you get a nice graph. 00:17:03.700 --> 00:17:05.040 Like really declarative. 00:17:05.040 --> 00:17:08.300 You just state what like your axes are and stuff and it does it. 00:17:08.300 --> 00:17:09.700 So that's really, really nice, right? 00:17:09.700 --> 00:17:11.520 You said you were actually using it a little bit. 00:17:11.520 --> 00:17:15.900 Yeah, actually, we had a project for visualizing our test result data. 00:17:15.900 --> 00:17:22.260 And since I knew about this and I get to make calls like that, I said, hey, let's try Altair. 00:17:22.260 --> 00:17:27.520 And one of the benefits of it is this data frame model. 00:17:27.520 --> 00:17:31.540 So the people working with it have had to learn data frames. 00:17:31.540 --> 00:17:38.080 And the result is they're like, hey, we actually working with data frames makes this easier because 00:17:38.080 --> 00:17:41.300 we can do a lot of manipulations within the data frame model. 00:17:41.300 --> 00:17:42.020 Yeah, that's pretty cool. 00:17:42.020 --> 00:17:43.680 They're like, wait, data frames are kind of awesome. 00:17:43.680 --> 00:17:44.320 We should use them. 00:17:44.320 --> 00:17:45.080 Yeah, definitely. 00:17:45.080 --> 00:17:46.300 Yeah, that's really cool. 00:17:46.300 --> 00:17:50.740 So that's Altair, which maybe we should spend more time talking about it. 00:17:50.740 --> 00:17:58.160 But the other item I want to talk about is Altair recipes from Antonio Piccolboni, who actually 00:17:58.160 --> 00:17:59.560 is the creator of Altair recipes. 00:17:59.560 --> 00:18:04.480 So the idea is you can create some of these charts, but not all the kinds of charts that 00:18:04.480 --> 00:18:09.760 you might want to create are easily one lineable in Altair. 00:18:10.140 --> 00:18:17.400 So what he's done is he's created a bunch of helper libraries that will take the data in 00:18:17.400 --> 00:18:22.920 the similar way I described before, easily generate the other types of things that you might want, 00:18:22.920 --> 00:18:26.900 like a box plot or histograms or things like that. 00:18:27.020 --> 00:18:35.840 So there's a whole bunch of different examples of different types of things, you know, auto correlation, box plots, heat maps, histograms, all kinds of stuff. 00:18:35.840 --> 00:18:40.900 That's down to just one line again using his code. 00:18:41.000 --> 00:18:42.080 So pretty cool. 00:18:42.080 --> 00:18:43.720 Yeah, very nice. 00:18:43.720 --> 00:18:44.260 Yeah. 00:18:44.260 --> 00:18:48.840 So basically, it's like a wrapper around more additional types of graphs. 00:18:48.840 --> 00:18:54.080 And I'm linking to a whole bunch of different examples in here. 00:18:54.080 --> 00:19:00.140 So in the little section on Altair recipes, just click on the examples and you can go see all the different graphs and whether or not they're helpful. 00:19:00.140 --> 00:19:01.440 Ooh, a layered histogram. 00:19:01.440 --> 00:19:02.400 A layered histogram. 00:19:02.400 --> 00:19:03.040 Isn't that cool? 00:19:03.220 --> 00:19:04.220 That's really cool. 00:19:04.220 --> 00:19:04.460 Yeah. 00:19:04.460 --> 00:19:12.620 And Antonio says it's fully documented, highly consistent API, 90% plus test coverage with a maintainability grade of A. 00:19:12.620 --> 00:19:14.020 So very nice stuff. 00:19:14.020 --> 00:19:16.620 Do you know how he computes the maintainability grade? 00:19:16.620 --> 00:19:17.260 Did you see that? 00:19:17.260 --> 00:19:17.860 No, I don't. 00:19:17.900 --> 00:19:22.180 I don't either, but I'm really fascinated to figure out what the maintainability grade of my other stuff is. 00:19:22.180 --> 00:19:23.460 Maintainability grade. 00:19:23.460 --> 00:19:24.440 Yeah, we should look into that. 00:19:24.440 --> 00:19:25.620 Yeah, we should definitely look into that. 00:19:25.620 --> 00:19:28.160 Antonio, send us a note about how you computed that. 00:19:28.160 --> 00:19:28.480 That's cool. 00:19:28.480 --> 00:19:33.500 But if you're using, if you're looking for visualization and especially if you're using Altair, check out Altair recipes. 00:19:33.500 --> 00:19:35.500 It's on GitHub and it looks pretty cool. 00:19:35.500 --> 00:19:35.940 Very cool. 00:19:35.940 --> 00:19:36.740 What do you got next for us? 00:19:36.740 --> 00:19:37.840 More testing? 00:19:37.840 --> 00:19:38.720 More coverage? 00:19:38.720 --> 00:19:42.640 Yeah, I've been thinking about testing and I kind of do that a lot. 00:19:42.960 --> 00:19:51.320 A couple of fun pytest plugins that were sent to me and I apologize for not remembering who sent these to me, but keep them coming. 00:19:51.320 --> 00:19:53.060 I love trying out new things. 00:19:53.060 --> 00:20:00.220 The first one I want to show is, talk about is called pytest-Picked, P-I-C-K-E-D. 00:20:00.220 --> 00:20:05.600 And the name confused me at first, but after you start using it, it sort of makes sense. 00:20:05.600 --> 00:20:06.840 Here's the idea. 00:20:06.840 --> 00:20:13.260 You've got a bunch of, you're using GitHub or not necessarily GitHub, any Git repo. 00:20:13.260 --> 00:20:14.020 Some Git repo, yeah. 00:20:14.020 --> 00:20:14.580 Yeah. 00:20:14.580 --> 00:20:22.680 And you're working with a test or something and you really, you know you're going to want to try to run the tests that you have modified. 00:20:22.680 --> 00:20:24.640 So Git knows this. 00:20:24.640 --> 00:20:27.200 With Git status, you can tell which files are modified. 00:20:27.200 --> 00:20:38.460 So this plugin utilizes Git status and allows you to run all of the modified test files in one test suite without having to like specify them or keyword them or anything. 00:20:38.460 --> 00:20:39.180 That's pretty cool. 00:20:39.180 --> 00:20:44.000 So if I have like a thousand test files, that may be a little excessive, but let's just roll with it. 00:20:44.000 --> 00:20:48.960 And I edit three of them since the last time I committed to Git. 00:20:48.960 --> 00:20:53.740 I can go run this and it'll say, well, these are the three changed test files. 00:20:53.740 --> 00:20:56.780 Therefore, we're going to run just the tests in those three files and pytest. 00:20:56.780 --> 00:20:57.100 Yeah. 00:20:57.100 --> 00:21:02.580 And you can run just those three or you can run those three first and then the rest of the suite. 00:21:02.580 --> 00:21:02.960 Okay. 00:21:02.960 --> 00:21:04.500 That's pretty sweet. 00:21:04.500 --> 00:21:16.240 You know what I would like, which is probably a much harder problem to solve, but would be awesome, is if you could combine code coverage along with this and sort of reverse it. 00:21:16.240 --> 00:21:20.200 Say like, well, these are all the source files and the test files that change. 00:21:20.200 --> 00:21:26.380 But the source files that change, what tests touch some line of code in these source files? 00:21:26.380 --> 00:21:30.220 So what do I need to run to get coverage on the changes that direction? 00:21:30.220 --> 00:21:31.220 That would be awesome. 00:21:31.220 --> 00:21:34.940 I think there is something like that, but it was last time I tried it. 00:21:34.940 --> 00:21:37.580 It was a little clunky to use, but I'll look it up again. 00:21:37.580 --> 00:21:37.800 Yeah. 00:21:37.800 --> 00:21:38.020 Okay. 00:21:38.020 --> 00:21:38.400 Cool. 00:21:38.460 --> 00:21:39.280 But this is really nice. 00:21:39.280 --> 00:21:45.160 I mean, certainly if the mode that you're in is I'm changing a bunch of the tests and I want to just run those. 00:21:45.160 --> 00:21:45.780 This is awesome. 00:21:45.780 --> 00:21:46.160 Yeah. 00:21:46.160 --> 00:21:55.400 Well, and the mode for a lot of people developing tests or maintaining software really all together is either writing new tests. 00:21:55.460 --> 00:21:59.440 When you're in that mode, you're definitely going to be having modified test files. 00:21:59.440 --> 00:21:59.700 Yeah. 00:21:59.700 --> 00:22:05.960 Or you're debugging something and you're like throwing some logging in it or something like that in a log in a test. 00:22:05.960 --> 00:22:06.840 Yeah. 00:22:06.840 --> 00:22:08.000 I definitely see a good use for this. 00:22:08.000 --> 00:22:09.040 And you have a two for us. 00:22:09.040 --> 00:22:09.680 That's just the one. 00:22:09.680 --> 00:22:10.060 Yeah. 00:22:10.060 --> 00:22:13.640 So the other one is a kind of a new project, but I thought it was fun. 00:22:14.040 --> 00:22:16.600 It's called the pytest Clarity. 00:22:16.600 --> 00:22:17.940 pytest dash clarity. 00:22:17.940 --> 00:22:20.040 It's just another colorizer. 00:22:20.040 --> 00:22:21.640 So it makes the diffs. 00:22:21.640 --> 00:22:29.540 So if you have a assert equals comparison that fails, the left and right comparison, sometimes it's a little hard to read. 00:22:29.540 --> 00:22:39.460 And this one is a colorizer that puts the changes from the left and right, right on top of each other and colorizes them differently. 00:22:39.460 --> 00:22:41.300 So that's nice and helpful. 00:22:41.300 --> 00:22:41.980 Yeah, that's cool. 00:22:41.980 --> 00:22:42.980 Definitely colors. 00:22:42.980 --> 00:22:43.940 Color is awesome. 00:22:44.300 --> 00:22:44.480 Right. 00:22:44.480 --> 00:22:46.200 It shows you what's different, what's the same. 00:22:46.200 --> 00:22:46.860 It's beautiful. 00:22:46.860 --> 00:22:47.820 You know, right away. 00:22:47.820 --> 00:22:48.140 Yeah. 00:22:48.140 --> 00:22:55.620 The one thing I'm in conversation with the person writing this, that it defaultly turns on verbose. 00:22:55.620 --> 00:23:01.580 And for small projects, having verbose on, which means that every test file is going to get listed. 00:23:01.580 --> 00:23:04.160 Actually, every test is going to get listed in the output. 00:23:04.160 --> 00:23:05.960 That's fine for small projects. 00:23:05.960 --> 00:23:10.180 But when you get into hundreds and thousands of tests, that can be unwieldy. 00:23:10.180 --> 00:23:11.580 Yeah, I can imagine. 00:23:12.100 --> 00:23:16.860 But you can turn that off with the dash QQ and the clarity still works. 00:23:16.860 --> 00:23:17.540 Cool. 00:23:17.540 --> 00:23:18.320 I've got... 00:23:18.320 --> 00:23:18.480 Yeah. 00:23:18.480 --> 00:23:21.160 Yeah, those are definitely nice testing additions. 00:23:21.160 --> 00:23:21.960 Quite cool. 00:23:22.840 --> 00:23:26.580 So the last one I want to close out with is a little bit of web security. 00:23:26.580 --> 00:23:32.100 And we've talked about web security before on the show, various things like the Django Hunter and stuff like that, for example. 00:23:32.100 --> 00:23:35.260 But this one has to do with headers. 00:23:35.680 --> 00:23:44.460 Now, did you know that when you have a web app, it obviously exchanges headers and cookies and stuff with the clients. 00:23:44.600 --> 00:23:51.600 But there's a whole bunch of things that you should send across, probably, to make your website more secure. 00:23:51.600 --> 00:23:52.260 Yeah. 00:23:52.260 --> 00:23:53.580 There's like a handful of them. 00:23:53.580 --> 00:23:58.940 And the OWASP organization has a place that talks about, these are the headers you should send. 00:23:59.280 --> 00:24:01.800 For example, about caching certain pages. 00:24:01.800 --> 00:24:07.180 Or if you're setting a cookie, that the cookie should only be exchanged over a secure connection. 00:24:07.620 --> 00:24:09.300 So imagine you've got like a site. 00:24:09.300 --> 00:24:10.800 Maybe it's a bank. 00:24:10.800 --> 00:24:12.260 You can log into it. 00:24:12.260 --> 00:24:19.860 If you go to hdpsbank.com or whatever the bank website is, right, it's going to set maybe a login cookie. 00:24:19.860 --> 00:24:26.860 But if you open up a browser and you type bank.com and just hit enter, maybe that goes over HTTP and then HTTPS. 00:24:26.860 --> 00:24:35.680 But if you don't set the right headers or flags, it could pass that login cookie over HTTP the first time before it goes over to HTTPS. 00:24:35.680 --> 00:24:36.240 Things like that. 00:24:36.260 --> 00:24:42.640 So you can say only exchange these cookies over secure connections and things like little details like this. 00:24:42.640 --> 00:24:44.640 But there's a bunch of them and they're hard to remember. 00:24:44.640 --> 00:24:52.440 One of the guys that was actually listening to Talk Python on Flask, where David Lord talked about this thing called FlaskTalesman, 00:24:52.440 --> 00:24:57.240 which is a plugin for Flask that will automatically do that kind of stuff. 00:24:57.240 --> 00:25:03.460 It'll just take the response, set those cookies, not the cookies, the headers that need to be set and things like that. 00:25:03.520 --> 00:25:06.820 So it's really nice that Flask has this option. 00:25:06.820 --> 00:25:08.380 He's like, well, but why don't the others? 00:25:08.380 --> 00:25:14.500 This security guy, pen tester, he's like, there should be something like this for all of the frameworks. 00:25:14.500 --> 00:25:18.720 So what he did was he created this thing, which I'll tell you the package name. 00:25:18.720 --> 00:25:20.800 And I can't believe that he got it on PyPI. 00:25:20.800 --> 00:25:22.540 The package name is secure. 00:25:23.900 --> 00:25:26.720 You think that would be taken by now. 00:25:26.720 --> 00:25:30.580 But the idea is it's secure headers and cookies for the Python web frameworks. 00:25:30.580 --> 00:25:32.120 It's pretty cool. 00:25:32.120 --> 00:25:40.560 It supports AIoHTP, Bottle, Cherry Pie, Django, Flask, Falcon, Hug, Basinite, Pyramid, Court, Responder, Sanix, Starlet, and Tornado. 00:25:40.560 --> 00:25:45.160 And if one of those is not on your list, you can actually just sort of feed it the response anyway. 00:25:45.160 --> 00:25:45.960 Isn't that cool? 00:25:46.060 --> 00:25:47.480 That's actually very cool. 00:25:47.480 --> 00:25:47.940 Wow. 00:25:48.100 --> 00:25:53.540 So it has built-in integration to those things like Pyramid Tweens or other types of stuff. 00:25:53.540 --> 00:25:56.000 You can plug it in so it automatically happens. 00:25:56.000 --> 00:26:01.020 But if you don't have it automatically doing it, you can just call the various bits as well. 00:26:01.020 --> 00:26:08.320 So it sends things like strict transport security, same origin iframes, cross-site protection, all that kind of stuff. 00:26:08.320 --> 00:26:09.820 It just does that automatically. 00:26:09.820 --> 00:26:11.820 And you can also create secure cookies. 00:26:12.700 --> 00:26:19.500 So you just go to the secure cookie thing and say, I'd like the secure cookie to have this name and this value. 00:26:19.500 --> 00:26:25.360 And it'll set that it's over HTTPS only, that it's over HTTP rather than JavaScript only, things like this. 00:26:25.360 --> 00:26:27.300 Same site origin, same site stuff. 00:26:27.300 --> 00:26:34.260 So all these little details about getting security right are wrapped up and then packaged in a way you can use it cross-framework. 00:26:34.260 --> 00:26:35.300 Check that out. 00:26:35.300 --> 00:26:36.460 Yeah, it's pretty sweet. 00:26:36.460 --> 00:26:38.460 Did you mention Pyramid Tweens? 00:26:38.460 --> 00:26:40.780 Is that a 12-year-old using Pyramid? 00:26:41.420 --> 00:26:44.840 Well, it's 11 to like early 13-year-old. 00:26:44.840 --> 00:26:49.500 No, it's like a layer that you can put in between request response. 00:26:49.500 --> 00:26:53.160 And it's like a thing that gets called before and after responses, I believe. 00:26:53.160 --> 00:26:53.520 Okay. 00:26:53.520 --> 00:26:55.740 Apparently it's not there in your Pyramid class. 00:26:55.740 --> 00:26:56.480 Yeah, I guess not. 00:26:56.480 --> 00:26:58.480 And I don't think I really talked about it there. 00:26:58.480 --> 00:27:03.620 But you can basically plug it in and say, anytime you send a response, call this function. 00:27:03.620 --> 00:27:11.080 And so you can just in that function say, upgrade the response to have the secure headers in the response without doing it all over the place. 00:27:11.080 --> 00:27:12.500 You just plug in this one little bit. 00:27:12.500 --> 00:27:13.160 Okay, cool. 00:27:13.160 --> 00:27:14.080 Yeah, it's pretty cool. 00:27:14.080 --> 00:27:19.280 So if you're doing a web map and you care about security, this is definitely worth checking out. 00:27:19.280 --> 00:27:23.380 All right, well, that's it for all of our items that we're officially covering. 00:27:23.380 --> 00:27:24.100 I have some extras. 00:27:24.100 --> 00:27:24.620 How about you? 00:27:24.700 --> 00:27:26.260 I don't, actually. 00:27:26.260 --> 00:27:33.340 Other than I've been podcasting away and I got like seven episodes of Test and Code in December. 00:27:33.340 --> 00:27:34.480 That's awesome. 00:27:34.480 --> 00:27:35.720 I've been listening to a lot of them. 00:27:35.720 --> 00:27:37.400 You've got some good stuff going on lately. 00:27:37.400 --> 00:27:38.240 And I'm going to keep it up. 00:27:38.320 --> 00:27:40.820 I'm not going to do seven in January, but there should be four. 00:27:40.820 --> 00:27:41.080 Yeah. 00:27:41.080 --> 00:27:41.860 Awesome. 00:27:41.860 --> 00:27:43.140 I'm really glad to see that coming along. 00:27:43.140 --> 00:27:46.140 So I have, it's good you don't have many because I have a bunch. 00:27:46.140 --> 00:27:47.240 So I'll go through them kind of quick. 00:27:47.240 --> 00:27:51.220 But there was this pretty big bug that came out about SQLite. 00:27:51.220 --> 00:27:53.900 SQLite is an embedded database that runs in process. 00:27:53.900 --> 00:27:56.440 That happens to be shipped and included in Python. 00:27:56.880 --> 00:28:08.160 So that got my attention, but it's also included in the browsers for like Web SQL stuff that JavaScript can use and it can be embedded in like Electron JS apps for the same reason. 00:28:08.160 --> 00:28:09.020 Stuff like that. 00:28:09.020 --> 00:28:09.200 Right. 00:28:09.200 --> 00:28:11.120 So it's really a lot of places. 00:28:11.120 --> 00:28:25.420 Now, the problem is it turns out that there is a bug in SQLite that with simple SQL select commands, you can do very bad things to anything that runs the SQLite that is vulnerable. 00:28:25.920 --> 00:28:27.180 And this was just really recently. 00:28:27.180 --> 00:28:28.540 All right. 00:28:28.540 --> 00:28:34.080 So it seemed like this could have been a really big problem in Python since Python has SQLite. 00:28:34.080 --> 00:28:35.760 SQLite has this problem. 00:28:35.760 --> 00:28:41.160 And it would have had to been the case that there was some SQL injection, right? 00:28:41.160 --> 00:28:44.500 Like you took user input and you fed it to SQLite directly. 00:28:44.500 --> 00:28:44.800 Yeah. 00:28:44.800 --> 00:28:45.080 Right. 00:28:45.080 --> 00:28:48.260 So that's already there have to be kind of a problem in your code for this to happen. 00:28:48.260 --> 00:28:57.120 But it turns out I threw this out on Twitter and some folks came out there and really like, you know, a lot of people shared it. 00:28:57.120 --> 00:28:58.160 A lot of people talked about it. 00:28:58.280 --> 00:29:02.280 And somebody said, you know, actually, that's an interesting thought. 00:29:02.280 --> 00:29:02.880 M. 00:29:02.880 --> 00:29:09.040 Boris on Twitter is like, you kind of got me curious that maybe this is a problem for Python. 00:29:09.040 --> 00:29:09.620 Let me check. 00:29:09.620 --> 00:29:14.600 So he took the proof of concept exploits and ran it against SQLite and Python. 00:29:14.600 --> 00:29:16.000 And it looks like it's not a problem. 00:29:16.000 --> 00:29:17.260 That's pretty good, right? 00:29:17.800 --> 00:29:21.920 So if you hear that there's this big problem with SQLite, it seems like it's not a problem with Python. 00:29:21.920 --> 00:29:23.460 But that's not for sure. 00:29:23.460 --> 00:29:24.420 But it seems that way. 00:29:24.420 --> 00:29:27.860 And also don't take user input and throw it into a query. 00:29:27.860 --> 00:29:29.120 Yeah, exactly. 00:29:29.120 --> 00:29:34.140 It's already like in order for this to be a problem for your Python app, you already have to have a problem. 00:29:34.140 --> 00:29:35.240 This just makes it worse. 00:29:35.240 --> 00:29:40.480 So if this was going to be a problem before, you should probably deal with that regardless. 00:29:40.480 --> 00:29:41.380 All right. 00:29:41.380 --> 00:29:42.220 So next one. 00:29:42.220 --> 00:29:44.460 This is a follow up on our AI and health care. 00:29:44.540 --> 00:29:52.640 We talked about AI and the AI analyzing cancerous mammograms and helping doctors get much better at that. 00:29:52.640 --> 00:29:57.040 And we were speculating, maybe I was speculating, that maybe there won't be a need for doctors. 00:29:57.040 --> 00:30:01.240 We'll just upload it to the cloud doctor and we get an answer, right? 00:30:01.240 --> 00:30:01.860 Things like that. 00:30:01.860 --> 00:30:02.940 Hey, Google, do I have cancer? 00:30:02.940 --> 00:30:03.720 Exactly. 00:30:03.720 --> 00:30:05.700 Send us three pictures. 00:30:05.700 --> 00:30:06.160 I'll tell you. 00:30:06.160 --> 00:30:09.920 Well, this guy named Bradley sent us feedback. 00:30:09.920 --> 00:30:11.560 He says, hey, I really found this interesting. 00:30:11.560 --> 00:30:14.160 I'm a data scientist at the National Oncology Program. 00:30:14.160 --> 00:30:16.880 And I work directly with clinicians. 00:30:16.880 --> 00:30:22.540 And it's my strong opinion that AI cannot take the job from the medical folks, the MDs. 00:30:22.540 --> 00:30:26.940 However, it will make it way more efficient for all the low hanging fruit. 00:30:26.940 --> 00:30:30.900 He says, you know, look, health care is both science and an art. 00:30:30.900 --> 00:30:35.240 And the AI is going to have a really hard time on the art side of things. 00:30:35.240 --> 00:30:37.200 Also probably the human interaction side of things. 00:30:37.200 --> 00:30:40.740 So really doesn't think that there's a big danger of that. 00:30:40.740 --> 00:30:46.760 Well, you know, I guess time will tell, but he's definitely got a lot more to go on than I do, right? 00:30:46.760 --> 00:30:48.760 He works as a data scientist with these folks. 00:30:48.760 --> 00:30:49.620 So that's cool. 00:30:49.620 --> 00:30:50.800 Got some inside feedback. 00:30:50.800 --> 00:30:52.920 Yeah, that's pretty much what we were speculating anyway. 00:30:52.920 --> 00:30:55.660 I mean, it's not something you can break down into an algorithm. 00:30:55.840 --> 00:30:56.480 Yeah, for sure. 00:30:56.480 --> 00:31:00.100 Next item really quick, Python 3.7.2 is out. 00:31:00.100 --> 00:31:05.420 So be sure to get the latest Python 3.7 if you're trying to run that. 00:31:05.420 --> 00:31:09.720 And if you're running homebrew, you can just do brew update and brew upgrade. 00:31:09.720 --> 00:31:12.140 And you'll have Python 3.7.2, which is pretty awesome. 00:31:12.140 --> 00:31:12.560 Neat. 00:31:12.560 --> 00:31:12.880 Yeah. 00:31:12.880 --> 00:31:17.320 So I'm already running that on my local machine, but not yet in production. 00:31:17.320 --> 00:31:19.260 It's not on the right Linux version yet. 00:31:19.880 --> 00:31:22.200 And then finally, I launched a new course, Brian. 00:31:22.200 --> 00:31:24.340 Yeah, I'm excited about this. 00:31:24.340 --> 00:31:30.900 Yeah, so this is one written by Matt Makai of Full Stack Python, and it's Introduction to Ansible. 00:31:30.900 --> 00:31:34.120 So that one's been coming along for a long time, and he finally got it out. 00:31:34.120 --> 00:31:39.380 It's really good, and I'm learning a lot about all sorts of things, also including Ansible. 00:31:39.380 --> 00:31:44.860 So if you're interested in Ansible, check it out over at training.talkpython.fm, or just click the link. 00:31:44.860 --> 00:31:45.300 Nice. 00:31:45.300 --> 00:31:47.180 Did you come with a joke this time? 00:31:47.180 --> 00:31:47.780 I did not. 00:31:47.780 --> 00:31:48.540 Do you have a joke for us? 00:31:49.460 --> 00:31:50.940 Well, luckily, I found a joke. 00:31:50.940 --> 00:31:57.400 And by found a joke, I mean Joachim sent us a joke, one of our listeners, and I'll tell it to you. 00:31:57.400 --> 00:31:58.260 Okay. 00:31:58.260 --> 00:32:00.820 Okay, so hold on. 00:32:00.820 --> 00:32:01.460 Got to zoom in. 00:32:01.460 --> 00:32:02.200 Fonds are small. 00:32:02.200 --> 00:32:02.920 Eyes are old. 00:32:02.920 --> 00:32:09.660 So an engineer, a physicist, and a programmer were discussing what was the oldest profession of the three. 00:32:09.660 --> 00:32:17.380 Engineers, look, all the matter engineered into amazing constructs like stars, galaxies, planets. 00:32:17.380 --> 00:32:18.800 So obviously engineering. 00:32:19.040 --> 00:32:24.200 The physicist says, before there were planets, the matter had to be made from chaos. 00:32:24.200 --> 00:32:28.360 Physics is responsible for all the quarks, gluons, photons, and electrons. 00:32:28.360 --> 00:32:30.080 Not to be outdone. 00:32:30.320 --> 00:32:33.220 The programmer says, aha, but where do you think the chaos came from? 00:32:33.220 --> 00:32:33.980 Yeah, that's good. 00:32:33.980 --> 00:32:34.580 Yeah, pretty good. 00:32:34.580 --> 00:32:41.340 So definitely, I'm sure we've all caused a little bit of chaos out in the world with our apps. 00:32:42.340 --> 00:32:43.100 That's a good one. 00:32:43.100 --> 00:32:45.100 Not to like, we should be done now. 00:32:45.100 --> 00:32:46.840 But I just remembered another thing. 00:32:46.840 --> 00:32:47.360 Okay. 00:32:47.360 --> 00:32:55.540 Speaking of chaos, is like, in 2019, more and more browsers were saying, let's just try to have all websites be secure. 00:32:55.920 --> 00:32:57.240 So I got hit by this. 00:32:57.240 --> 00:33:04.240 And Python testing.net is not, doesn't have SSL on it, but it's just warning everybody. 00:33:04.240 --> 00:33:07.520 By the way, like Brian might steal your information. 00:33:07.520 --> 00:33:09.720 I'm not going to do anything with your information. 00:33:09.720 --> 00:33:10.220 Let me see. 00:33:10.220 --> 00:33:10.680 I pull up. 00:33:11.100 --> 00:33:11.900 Oh my goodness. 00:33:11.900 --> 00:33:12.880 I got to get out of here, man. 00:33:12.880 --> 00:33:14.400 This is not secure on it. 00:33:14.400 --> 00:33:15.680 Yeah. 00:33:15.680 --> 00:33:16.760 What up? 00:33:16.760 --> 00:33:23.120 So I could just buy an SSL certificate or whatever, do the free one, and jump through that hoop. 00:33:23.120 --> 00:33:26.140 But I felt like it'd be a good time to change it anyway. 00:33:26.140 --> 00:33:31.980 So I'm going to start the process of turning this into a static site generated site. 00:33:31.980 --> 00:33:32.560 Oh, you are? 00:33:32.560 --> 00:33:32.920 Okay. 00:33:32.920 --> 00:33:33.300 Awesome. 00:33:33.300 --> 00:33:34.340 Well, that sounds really fun. 00:33:34.340 --> 00:33:38.640 And that'll be, I know some good sites that definitely run that way. 00:33:38.640 --> 00:33:39.600 So that'll be good. 00:33:39.600 --> 00:33:39.900 Yeah. 00:33:39.900 --> 00:33:40.460 Okay. 00:33:41.120 --> 00:33:41.860 That's all I got. 00:33:41.860 --> 00:33:44.700 Well, even though it says not secure, I'm still going to go there. 00:33:44.700 --> 00:33:45.040 It's okay. 00:33:45.040 --> 00:33:46.860 Okay. 00:33:46.860 --> 00:33:47.500 All right. 00:33:47.500 --> 00:33:49.420 Well, great to chat with you as always, Brian. 00:33:49.420 --> 00:33:50.120 Yeah, you too. 00:33:50.120 --> 00:33:50.380 Yep. 00:33:50.380 --> 00:33:50.600 Thanks. 00:33:50.600 --> 00:33:50.800 Bye. 00:33:50.800 --> 00:33:52.740 Thank you for listening to Python Bytes. 00:33:52.740 --> 00:33:55.260 Follow the show on Twitter via at Python Bytes. 00:33:55.260 --> 00:33:58.140 That's Python Bytes as in B-Y-T-E-S. 00:33:58.140 --> 00:34:01.560 And get the full show notes at pythonbytes.fm. 00:34:01.560 --> 00:34:05.920 If you have a news item you want featured, just visit pythonbytes.fm and send it our way. 00:34:05.920 --> 00:34:08.620 We're always on the lookout for sharing something cool. 00:34:09.100 --> 00:34:12.020 On behalf of myself and Brian Okken, this is Michael Kennedy. 00:34:12.020 --> 00:34:15.520 Thank you for listening and sharing this podcast with your friends and colleagues.