Python Bytes - #329 Creating very old Python code

Episode Date: March 30, 2023

Topics covered in this episode: Prefix-cache NiceGUI flask-ngrok No-async async with Python Extras Joke See the full show notes for this episode on the website at pythonbytes.fm/329...

Transcript
Discussion (0)
Starting point is 00:00:00 Hello and welcome to Python Bites, where we deliver Python news and headlines directly to your earbuds. This is episode 329, recorded March 30th, 2023. And I'm Brian Ocken. I'm Michael Kennedy. And before we get started, I want to do a couple things. I want to thank Microsoft for Startup Founders Hub for sponsoring this episode. Please listen to their spot. We've got a very special random guest appearance or voice for that that ad read so that'll be fun um i also if you're
Starting point is 00:00:31 listening to this um i'd like to encourage you to and you've never watched the live show i'd like to encourage you to watch our uh live show on youtube or streaming um it we usually work today is thursday but we usually record Tuesday at noon or 11. No, Tuesday at 11. Yeah, I should have practiced this. Anyway, but welcome. And the people that are here today are watching on YouTube. Thanks for watching. And why don't you kick us off, Michael? I got something. I think it'll resonate with you folks. Maybe you already are aware of this. This is news to me. Comes to us from Brandon Hannigan. So thanks for sending that in.
Starting point is 00:01:10 And it's an environment variable. And in and of itself, it's interesting in that it leads to many more environment variables you can play with is also pretty awesome. So this one is about the Dunder Pi cache folder. So I don't know how you feel about these, Brian. I'm glad they exist. I'm not necessarily super glad that they're spread out a bunch of random folders.
Starting point is 00:01:34 So a lot of my projects have many different modules and different folders, submodule type setup. And when I run them, they all get filled up with Dunder PyCache folders with startup PYC, you know, compiled Python. Like people might think, I think Python is compiled, but yes, Python is compiled. It's just then interpreted not, you know, all the way to machine instructions, right? So those files end up in the Dunder PyCache, which spread throughout your project structure.
Starting point is 00:02:00 Sometimes I want to make a copy of that. I want to move that around. I want to zip it up and share it. And I don't want those things in there. And so I'll have to go in and search for all those and remove them recursively, which is not at the end of the world. But I'd rather they are not there. Or if they were there, could they just go in a top level thing?
Starting point is 00:02:15 You know what I mean? Like, could they just go into a single DunderPy cache that understands the whole structure, not every file being treated as if it's unrelated? I mean, it's better than it used to be of having the PYCs right next to the Python files. Yes, it is an improvement. But this thing that Brendan said, you can set the Python PyCache prefix,
Starting point is 00:02:38 which is a path. Maybe it should be called Python Cache Folder. I don't know. Anyway, what you do is you set this in your environment variable, maybe in your user account, maybe in the activation of a virtual environment if you want it to be a one-off type thing.
Starting point is 00:02:53 I don't know. Then when Python goes to create these, it goes, oh, they don't want the DunderPy cache. They want it over in this directory over there. And so it'll make, you can isolate all of your Dunder PyCache stuff into a separate location on your user profile. You can go and just blast that away
Starting point is 00:03:10 whenever you feel like. But most importantly, it's not within your source code. If you like zip it up and hand it out or things like that. Oh, wow. Okay. That's great.
Starting point is 00:03:19 Yeah. It says, if this is set, Python will write star.pyc files in a mirror directory tree at this path instead of in dunderpy cache directories within the source tree. This is equivalent to specifying the dash x pycache prefix equals
Starting point is 00:03:34 path option. So pretty cool, right? Yeah, I also didn't know about the dash x though either, so that's pretty cool. Yeah, this page that I'm linking to is at the top, it has all the command line options and then almost all the command line options have an environment variable thing if you want it to just be the default all the time and you don't have to set it. So there's a bunch you can come look through here.
Starting point is 00:03:54 So Python path, you can set Python startup. So these are the Python commands that will execute whenever you start Python, which is kind of interesting. Optimize, breakpoint, debug, the one we talked about. You can set up a hash seed so you can get repeatable deterministic hashing. A bunch of stuff is here people can check out. How you look at warnings, how much warnings you want to see, whether or not there's buffering., you'll see sometimes things like the standard out will come after the standard error, but the standard error in time actually came after the out, right? Because the
Starting point is 00:04:32 buffering got out of, you know, they hit the buffer at different periods. So you can do things like turn that off, turn on malloc stats if you want to track that. So there's like a bunch of things you can come in here and play with. But that think the pyc one's an interesting one especially for people who hand out code you know like if you're doing like a training or a tutorial and you're like here i want to give everybody this you got the pyc file again i was just looking through there because i'm surprised that you can't you can't specify which xkcd comic don't link to but i know when i import anti-gravity which one don't worry we'll get there cool all right well that's what i got for this one um the the python pi cache prefix check it out nice yeah
Starting point is 00:05:12 um i wanted to talk about guis we haven't talked about guis for a while we were on such a kick we were on such a kick yeah but um uh several people have mentioned this to us so we thought we'd cover it um it's a package called nice gui and normally actually when i think about gui i think about like actual not web stuff but user interface stuff that's on the desktop but this is a this is a browser-based thing so this is a um this is a package that's it says it's easy to use python based ui framework which shows up in your web browser, buttons, dialogues, markdown, 3d plots and more. What what's cool is you can play with it all before you even try it. So the the documentation is really great.
Starting point is 00:05:56 And even just here, I thought this was just like a screenshot or something. Now you can just like this is part of it. You can move it and interact with it right here in the the first page it's pretty cool um the document full documentation is uh is really pretty pretty great too i actually want to try to play with this because the the uh the code really looks pretty easy to write um so for some quick uh maybe dashboards or some quick control stuff that you're okay with doing through a web browser why not try it it out? And some of these are pretty cool. I was playing with text input. So it's talking about validation and stuff.
Starting point is 00:06:31 So you can have some text and you can just start typing and it's saying, oh, that's too long. So you can, I mean, this validation is pretty simple of just checking length, but you can do all sorts of stuff like email validation or whatever you want it to do because it's just like a function that's calling so kind of neat uh you got a validation there uh knobs knobs are fun um i was playing with the knobs so drag knob and turning anyway uh
Starting point is 00:06:55 all sorts of easy context manager to put it into the page with knob what because with knob um interesting i wonder why i don't know oh to put the icon inside it so you basically it looks like you're focusing the the subsequent commands to be within the container of the knob because you the knob is like a like a circular progress bar type thing and you can put a volume up icon inside it okay um, just all sorts of cool stuff. Joystick. That's really, I don't have a joystick to play with this out, but some interesting naming there with the joystick.
Starting point is 00:07:33 But anyway, so moving on, date pickers and all sorts of things. Ooh, that's nice. Cool. But UI elements, if you're okay with trying something new, a nice GUI might be right for you. So that's nice cool but ui elements uh if you if you're okay with trying something new um a nice gui might be right for you so that's interesting isn't it uh you know i when i look at these types of frameworks that a lot of times i feel like what they say is um html is terrible the dom is terrible css is terrible let's create a parallel python or name your language equivalent where we put elements in the web page i'm like they may have their drawbacks but at least you have a ton of tools
Starting point is 00:08:11 and stuff that apply to html and css and all those things right but yeah this one i think there's a lot of cool widgets and stuff that are here and it looks more like the it's not like we don't like html so let's make a Python DOM that you create the HTML with. But rather, how do we make a cool interactive page based on these additional things like knobs and joysticks and sliders and stuff that's not easily part of HTML? Yeah, and the places where I would really use something like this are, I mean, this is some short code. So especially internal tools where or even just stuff for myself if i want to explore some data control like a database or uh got a bunch of you know controlling some system or something and i want to like quickly
Starting point is 00:08:57 throw something together something like this would be great for yeah just um doing a like a one pager something to try it out. I also think these types of frameworks would be pretty cool to bring into some kind of Electron JS type thing, where you're like, and here's how you make it an app that doesn't actually look like a web page
Starting point is 00:09:18 and give it to someone. Yeah, so one of the things they bring up is great for micro web apps, dashboards, robotics projects, like school robotics, stuff like that. Smart home solutions. That joystick thing,
Starting point is 00:09:30 right? Can drive you a little. And then the, one of the, one of the nice things that I noticed about the documentation is they've got a bunch of demos. Oh, these are the actual demos,
Starting point is 00:09:42 but there's examples. Where did I find those? Is it maybe under examples? Well, anyway, there's a whole bunch of like actual code. So there's repos around that you can try it out with, um, with the, with different repositories. Maybe it's just on the front page. Anyway. Um, I was impressed.
Starting point is 00:09:59 Oh yeah. Here we go. Down at the bottom of the front page, there's like slideshows. And even if you want to, will this work with fast api apparently there's a fast api uh example uh for just uh some some quick repositories so you can try it out yourself uh maybe like an admin page type of dashboard thing that you can play with um yeah there's some open cv webcam infinite scroll for galleries um and i the the the amount of like demos of components right there but then actually specific examples where you can uh you know with the code with repos that you can just copy and get started with that's pretty pretty impressive that they put all
Starting point is 00:10:38 that together right off the bat yeah so yeah it looks like it's definitely worth checking out do you know what else is worth checking out our sponsor yes microsoft for startups founders hub thank you for sponsoring this episode and what was the uh key that you what what how did you generate this code the text remember i don't recall who suggested it because i had the American football coach motivational speech version variant last time. And somebody said, well, what if it was like Ted Lasso? So I said, hey, open AI thing. Here's the Microsoft ad. Could you rewrite it this time in the style of Ted Lasso? Yeah. So it's an odd episode. So I get the honor of trying to be Ted Lasso, which I'm not going to get the voice, so apologies. And I did not grow up in the Midwest, so anyway, let's just get started. Hey there, team. Gather around, because I've got something real special to share with y'all.
Starting point is 00:11:35 Now, you know how much I believe in the power of teamwork and positivity, right? Well, this opportunity I'm about to tell you is just like the perfect assist to your startup goal. I'm talking about the Microsoft for Startups Founders Hub, folks. Now imagine, if you will, a locker room full of support for your startup, especially if you're keen on that there artificial intelligence stuff. We're talking over six figures of benefits that'll change the game for your team. They're offering you 150k in Azure credits. And that my friends is like having the best player on the field on your side. And what's more, the Founders Hub has given y'all a unique chance to access open AIs, APIs, and the new Azure Open AI API, the Azure Open AI service. It's like having your own generative AI coach to help you come up
Starting point is 00:12:27 with game winning strategies for your applications. Now, I know how important it is to have the right support. And that's why the folks at Microsoft are also offering one-on-one technical advice, helping you with your game plan, scalability and security. Plus, you'll be part of a network of mentors who know the startup world like the back of their hand. I can't emphasize enough how amazing this opportunity is, friends. And guess what? It's open to everyone, no matter what stage your startup's at, and no funding requirements.
Starting point is 00:12:59 Just take five minutes to apply, and you'll be on your way to reap in some massive benefits. So come on team, let's harness the power of AI for your startup and join Microsoft for Startup Founders Hub today. Head on over to pythonbytes.fm slash foundershub2022 and sign up. This is your chance to score big, so don't let it slip through your fingers. And just so you know, the ad you just heard was written by the same AI you'll get access to. Ain't that something?
Starting point is 00:13:27 So don't wait any longer and sign up at pythonbytes.fm slash Founders Hub 2022. A big thank you to Microsoft for supporting this show. That open AI, that sure is something. All right. Speaking of something, let's talk about Ngrok. Let's talk about Flask. I can't decide. Let's talk about ngrok let's talk about flask like i can't decide let's talk about both so this one i want to cover is uh an interesting one so i've talked about ngrok before for those of you don't know like unfortunately their website i don't know what's
Starting point is 00:13:56 gone on but they redesigned it in a way they can't really tell what it does but it's just, anyway. In Grok, what it does is it lets you run a command locally and then share your web app, whether that be for an API, someone needs to talk to the API, or just the web app itself. So for example, Brian, imagine you had created a cool demo of that nice GUI thing and you wanted to let some people,
Starting point is 00:14:23 you're in a meeting with your team, like, hey, you guys, y'all should check this out. This is really, really cool. And what you might do normally would say, well, let's just fire up a screen sharing and I'll drive it around. But the interaction part of those widgets is really cool. So it'd be better if you could just say, and interact with this, right? So if you fire up ngrok, you just give them a URL that reverse SSH tunnels into your machine, and then they can access it on the internet with their browser, and everyone can play with it live. Right?
Starting point is 00:14:52 So that's really cool. I recently used that for I'm just about to release a course called Python Web Apps that fly with CDNs. Like, basically, how do you do really awesome stuff with CDNs plus Python and Flask and all those things to make your app way, way faster? Well, in order to put that together and test it, you've got to let a public CDN get access to your dev machine, which like, how does that happen? Ngrok is how that happens. Same thing with our mobile apps, like you can see like right here. We had this problem where some of the data wasn't being passed through as headers correctly to the server.
Starting point is 00:15:27 And we're like, we cannot figure out why this is not working. It's clearly in the headers collection. Why is Python not seeing those? And it turns out there was like a weird case sensitivity issue or whatever. But I just fired up ngrok, pressed debug on PyCharm,
Starting point is 00:15:40 and said, all right, try it again. And then boom, I'm like stepping through, like on a mobile device, I'm stepping through its interaction with the APIs. I'm like, oh, I see, try it again. And then boom, I'm like stepping through, like on a mobile device, I'm stepping through its interaction with the APIs. I'm like, oh, I see, here's what's happening. And then we fix it, super easy. All of that is to set up Flask-Ngrok. So all of those benefits are awesome,
Starting point is 00:15:56 but like what I gotta do is I have to go fire up Ngrok, go over, do the thing and then come back, right? So it'd be cool maybe if I could just press go, either run, you know, Flask run or just go in PyCharm or VS Code and it would just, in addition to starting up Flask, it would also start up ngrok pointing back at whatever the right port is, right? So basically that's what this is.
Starting point is 00:16:17 You just wrap the app in run with ngrok. So you get a run with ngrok app. And then when you say flask run it fires up the local version but it also fires up an ngrok url that you can share with people oh cool yeah so not not a huge huge feature because sure you can run ngrok on your own but i think it's kind of cool like it basically that means whenever you run your flask code your flask app for debugging or for dev or whatever, there's always a publicly accessible address that you can share with other people or you can type
Starting point is 00:16:50 into some other tool. I want to validate an RSS feed. I want to have my API, some API client that is not on my machine, like a mobile app or some other, you know, think if this than that, or one of those types of things, all those can just come back right in because you always have this public address available, which I think is pretty cool. That's pretty cool. Yeah. So if that sounds useful, people can check it out. Oh, man.
Starting point is 00:17:16 Okay. So I was just thinking, I wonder if random address, because like I need another URL that I'm not doing anything with, but I was wondering if random address was taken and random address is taken. Is it random addresses? No, we have enough. I've got several that I'm not using. Yeah, that's awesome. All right, cool.
Starting point is 00:17:37 Anyway, people can check this out if they are doing a lot with ngrok. So by the way, one thing that I think would be interesting, I didn't see in the docs whether or not this is easy, possible, impossible, whatever. One of the things you can do is you can set it up so that this random address is repeatable. Otherwise, if you just rerun it, you'll get a new random address, which you got to keep typing in by doing like subdomain type things and stuff. You've got a paid account. I don't know if it's possible to have it do that or not, but it would be cool if you could make it random but not completely random so anyway not complete just
Starting point is 00:18:09 random once and then yeah random once and let's stick with that for a while all right what do you got for our last one i want to talk about async so um will mccougan i wrote an article called no async with python no no async async and it it's not, that's confused me, but it's, it's a really well-written article. There's, there's times where if you want to take advantage of async you you kind of have to have async all the way up and down the call stack, right? Or you maybe that's what it seems like at least to make things sure this all works. But and so that's actually what I guess textual did at one point is made a sync to all the things.
Starting point is 00:18:50 But textual now is a sync optional. And so this article discusses how they do that. And the first part is if you're passing in a callback to if you if you're providing a mechanism for somebody to pass a callback in, and that callback can, you want it to be either just a normal function or an async function. He's utilizing the await me maybe pattern that he borrowed from Simon Willison. So Simon Willison wrote about this a couple years ago. And he shows, scroll almost to the bottom. There's this, basically, there's a way to, you have an async function and it calls.
Starting point is 00:19:29 So the caller is async and you're calling something that could be either async or not. And you, you just call something and check to see if it's a coroutine and then awaited or don't await it. Um, and that's, that's pretty much what, uh, will is showing is, you know, inspect the callback, inspect the result to see if it's awaitable or not. Doing it a little bit different method, but similar sort of effect. So that's neat. So you can provide a mechanism to add async service that could be called in either an async or non-async you want it to be called by anybody because sometimes like he gives an example
Starting point is 00:20:12 of uh mount uh mounting a new widget into into textual um the caller might want to care might care about when that's actually done so they might want to wait for that but they might not they might just like keep going because apparently textual handles it all correctly anyway, they won't let something happen, but the caller might not care about when it's done. So to be able to allow both async and non-async callers to call an async method, that's a little bit yuckier code, but he provides it. So there's, there's a, this class, this await mount option.
Starting point is 00:20:48 So there's, I'm not going to walk through all this code, but basically there's a way to do it. And Will has it, has the method to allow you to have. And I think that's kind of neat to be able to provide services and APIs that can be called both in async and non-async ways. Now, hopefully this still is kind of ugly. So hopefully, as a community, we can come up with a little bit cleaner solution, but at least there's a solution.
Starting point is 00:21:13 So it's kind of nice. Yeah, Will did a nice job of this. And I think it's really a huge benefit that Textual has the ability to be async, but doesn't force you to be async. Because if you're already writing async code, you would like it to be because it's a benefit. You can do more in parallel, be more responsive. But if it means I have to take my non-async code and now convert the whole thing to know about some of the parts of it being async, well, that's a hassle. And I think one of the things that drives me nuts about Python's async, there's a few, few little things that just make me crazy about it.
Starting point is 00:21:45 It's like, wow, it's, it's so close to awesome. Right. And much of it is awesome. But for example, if I have, if I'm in a function and I want to say, here's some async code, I want to just run it here. So for example, async IO, you know, get, get event loop, loop.run sort of thing, or just async IO.run to complete. If it's already being called within an async function with some other event loop, and you don't know about it, under certain times it'll crash and say, there's already an event loop,
Starting point is 00:22:13 or there is no event loop. You're like, well, give me, just if I don't have one, give me one. If there is one, just give me that. I don't care. I just need to run something async. And there's always this like weird, I'm not really sure what state I am. And i get it wrong then it gives me a it crashes and
Starting point is 00:22:28 that's like ah um so i think that makes it challenging to kind of go this part we're just going to like isolate off the async um which it sounds like will did here which is cool so that's really excellent yeah um really quickly here too i've've had a couple of shots at this myself as well. Nothing like published really very much in terms of what Will's doing or what Simon talked about. But like, for example, on fast API chameleon and the Jinja equivalent,
Starting point is 00:22:57 like let's just put a decorator on top of a fast API function and then it returns the HTML view of that and stuff. But those fast API functions, they can be synchronous or they can be asynchronous. And so what it has to do is it has to say, is this function a coroutine? Okay. The decorator has to return also an async one. Otherwise, when you say async and it becomes not async, that's wrong. But if it's a sync one, you can't return the async, right? So you you got to juggle this a lot, which is kind of a pain.
Starting point is 00:23:27 And then the other one, I created this thing, which I put up just as a gist that like just lets you say this async function, we're going to run it in a way that won't have a conflicting event loop complaint by constantly managing the background thread and just pushing the work over there and pulling the results back.
Starting point is 00:23:42 So yeah, it's interesting. But yeah, that's a cool article. Yeah. Do you remember the Call Me Maybe song? Call Me Maybe. Yeah, I do. Yeah. A Wait Me Maybe.
Starting point is 00:23:53 So Chris May added, hey, I just defined you and this may be a sink, but here's my variable, Wait Me Maybe. Nice. Well done, Chris. Well done. I love it. I love it. Well, I don't have any extras brian you got any i do um we'll try to make them quick though so uh pipey has a blog now oh let's uh pop over to here pipey has a blog now so anyway go check it out there's not much there's a welcome article uh so that's nice uh neat uh and And then, okay. So another extra, apparently a Docker. No,
Starting point is 00:24:29 they're laying off plans of charging people for the free team plan, which is kind of a bummer for people like me that paid for it anyway. But anyway, so that's cool. Maybe I won't have to pay next year. I guess they're offering refunds or something, but I'll look into it. I guess there must have been a big backlash. I haven't been tracking this, but. Oh, yeah. I mean, like, it's been a scramble all over the place of people because there's sometimes it's a very minimal interaction with it.
Starting point is 00:24:57 And then suddenly we have to pay for it and you got to figure out how many users and how many seats and all that sort of stuff. And yeah. Or if you want to use it without, so if you, if you want to use it without the user interface, you can use it for free. But if you like people asking are, are you using it? Yes, we are. Cause we debug with it and everything. Um, so, uh, so I'm glad they're backing off. Uh, I still want to, I mean,
Starting point is 00:25:19 of course it's a great service. Uh, they should be able to make money somehow. Uh, but, um, there should be, so it's good news. Uh, should be able to make money somehow, but there should be. So it's good news. The only thing left I have is a joke. Do you want to do mine first or yours first? Let's hear yours first. Let's go. It's just sort of,
Starting point is 00:25:37 I was looking up some documentation for PyTestCov and noticed at the bottom, so it provides a, there's mark, there's, it provides a no cover marker, which is nice. So you can say, don't cover this test. And then there's a fixture.
Starting point is 00:25:53 You can also use that as a fixture, but then there's also the no cover fixture, but there's a cov fixture, which, why would you use that? Well, it says for reasons that no one can remember, there is a cov fixture that provides access to the underlying coverage in an instance. Some say this is disguised as a foot gun and should be removed. And some think mysteries make life more interesting and it should be left alone.
Starting point is 00:26:17 I love finding stuff like that in documentation. Some think mysteries make life more interesting. Indeed. Indeed they do. Okay. Fantastic. All right. I got a quick life more interesting. Indeed. Indeed they do. Okay. Fantastic. All right. I got a quick one for you as well. This one, you knew an XKCD was coming. Good reference earlier. So this has to do with like some deep thinking into how to make your code last so long that it becomes legacy code and people can use it for a long time and maybe even curse its name a little bit. So there's two parallel universes here. On one, this woman just wrote this code. It took some
Starting point is 00:26:52 extra work to build, but now we're able to use it for all of our future projects. And the caption for that is how to ensure your code is never used. The other alternate world is, let's not overthink it. If this code is still in use that far in the future, it will have bigger problems. How to ensure that your code lives forever? And the hover is surely no one, everyone will recognize how flexible and useful this architecture is. Spend a huge amount of effort painstakingly preserving and updating this garbage I wrote in 20 minutes. Yeah. Well, mean it's there's so many examples of that isn't there i mean oh yeah ah yeah i mean internally there's tons there's like oh just this throw this thing together build script or whatever and it's just we'll rewrite it later 10 years later we haven't
Starting point is 00:27:41 rewritten it um things like that um I mean, flask was like a really quick hack, wasn't it? Like a joke at first or something? I think it was an April Fool's thing. I think so. Anyway, and the other side is the lesson that I think people should learn is planning on reuse is just a mistake. And I've been in many, many design meetings where it's like, let's not plan six years out into the future on this. That's ridiculous. We don't even know. Because I've also seen people plan for it, and it is reused, and it is maintained. But the things that you thought you were going to need to be variable are not the things that really need to change in the future.
Starting point is 00:28:24 It's something else. Yeah. Somewhere in the middle there lives a, let's not overthink this, get it out there. Oh, let's take a moment and refactor it so it's more reasonable in the way we now know it needs to be. Carry on. So my advice, keep the interface simple, keep it minimal,
Starting point is 00:28:40 document it, and test it. And then if it grows, great. Yep. Excellent excellent thanks for that that's funny yeah for sure and thanks everybody for showing up and thanks michael again for yeah great to be here

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.