#386: Realtime Web Apps and Dashboards with H2O Wave Transcript
00:00 Python's data science and visualization capabilities are certainly one of the reasons for its meteoric
00:05 rise over the past 10 years. But often, those visuals have been corralled into notebooks used
00:11 by data scientists themselves or into static web pages. Recently, a host of excellent dashboard
00:17 building and hosting frameworks have come along to turn these visuals into interactive apps for
00:23 everyone. On this episode, we'll talk about H2O Wave, one of these excellent dashboard frameworks.
00:28 We have Martin Taroshi from H2O.ai here to tell us about Wave. This is Talk Python to Me,
00:34 episode 386, recorded October 3rd, 2022. Welcome to Talk Python to Me, a weekly podcast on Python.
00:55 This is your host, Michael Kennedy. Follow me on Twitter where I'm @mkennedy, and keep up with
00:59 the show and listen to past episodes at talkpython.fm. And follow the show on Twitter via at Talk Python.
01:06 We've started streaming most of our episodes live on YouTube. Subscribe to our YouTube channel over
01:11 at talkpython.fm/youtube to get notified about upcoming shows and be part of that episode.
01:18 This episode is sponsored by Microsoft for startups founders hub. Check them out at talkpython.fm slash
01:24 founders hub to get early support for your startup. And it's brought to you by Sentry. Don't let those
01:30 errors go unnoticed. Use Sentry. Get started at talkpython.fm/Sentry. Transcripts for this
01:37 and all of our episodes are brought to you by Assembly AI. Do you need a great automatic speech to text API?
01:43 Get human level accuracy in just a few lines of code. Visit talkpython.fm/Assembly AI.
01:48 Martin, welcome to Talk Python to Me.
01:50 Thanks, Michael. Thanks for having me.
01:52 Oh, it's really great to have you here. I'm super excited to learn about H2O Wave. It looks like a
01:58 really cool project. That's one of these enabling, empowering projects for people who don't feel like,
02:05 oh, I could take my whatever I'm building, my ML model or whatever, or my data analysis and turn it
02:11 into a website or an app or any of those sorts of things. And they'll see that they can with Wave,
02:16 right? Yeah, that's right. Yeah, should be tons of fun. I think it's going to be a relevant topic for a
02:21 lot of people. Before we get to any of it, though, tell me about your background. How do you get into
02:26 programming in Python? Like most people do. I went to college, studied programming, computer science.
02:33 I started working originally as a Java developer, actually, then switched to web developer because
02:39 there was a lack of front-end engineers. And once I joined H2O, I mostly work on front-end here as
02:46 well. But I somehow got in charge of this Python framework. So I need to write a lot of Python
02:53 on day-to-day basis as well.
02:55 I think one of the big ironies of these data science tools and these nice Python visualization
03:02 tools is they're there to let people write Python so they don't have to write a ton of front-end code or
03:08 those kinds of things or write their own web frameworks or use Vue or React. And yet people
03:14 like you who actually make them spend so much time in the JavaScript side of things, right? I mean,
03:20 same thing for Jupyter. You know, it's someone's got to do it. And you're kind of doing it for
03:26 everyone else who uses it and gets to avoid it, right?
03:28 Yeah, that's right. I mean, you know, if you have a look at it, then front-end engineering is
03:34 quite complex topic these days compared to what it has been, let's say, 20 years ago.
03:40 You mean it's more than just linking to jQuery on a CDN?
03:44 Definitely.
03:45 It used to be so straightforward. And it really is. If you don't do it day-to-day, it's like,
03:51 how do I even get started to get this app up and going? It's crazy.
03:54 Yeah, exactly. And that's why we are here today to talk about how to make everyone's life easier.
04:00 That's right. Well, everyone but yours. You take the pain for the rest of us.
04:03 Yeah, but I kind of enjoy it. So that's not the problem.
04:07 Yeah, of course. If you love it, then it's all good. Before we get into Wave, you said you did,
04:14 you switched over to front-end stuff. What are your front-end technology favorites,
04:18 like front-end frameworks and stuff?
04:19 To be honest, I don't like frameworks at all. I like web as a platform because it also has become
04:27 very powerful. We have a lot of stuff that we didn't have before. But, you know, if you want to
04:34 build something enterprise-y or something that needs a longer maintenance, then you need to reach out for
04:42 frameworks. So currently, I've gone in React, which is, I would say, industry standard, but also have
04:48 experience with Vue or Angular. So at the end of the day, it's just a tool in our toolbox.
04:55 Pick one and go with it. And other front-end question, straight JavaScript or TypeScript?
04:59 Definitely TypeScript all the way.
05:01 Yeah?
05:01 Yeah. I mean, once you try TypeScript, then there's no way back.
05:05 Okay. I've done a little bit of TypeScript, but not enough to really pick it up, I don't think.
05:10 My JavaScript front-end experience is pretty limited. I try to stick with the Python side of things,
05:16 the server-side type of things as much as possible.
05:18 Speaking of which, sticking with Python, I guess maybe could get to the other question of what do
05:25 you do day-to-day? Kind of edge our way into this project? Day-to-day work on this H2O, right?
05:30 Yeah. Exactly. So basically, I work on H2O way, which is a framework for not only data scientists
05:37 and people making AI models to make their life easier, as you have already said, and to allow
05:44 them to build web applications without regular web knowledge like HTML, CSS, and JavaScript.
05:51 And my day-to-day concept is basically helping people out community-wise, answering questions,
05:58 getting new feature requests in. Then I have also two people, two developers, that I help with
06:06 bringing on their issues up, unblocking them. And I also need to code, bigger features
06:13 and basically picking on podcast if I have time.
06:17 Yeah. It sounds a little bit like a blend between sort of a program manager, software developer
06:25 on one half, and then dev evangelist almost on the other.
06:29 Yeah. In country where I come from, we call it a girl for everything. So basically you need to
06:36 jump on a lot of head.
06:37 Yeah. Perfect. All right. Well, give us the quick elevator pitch of H2O wave. It's four people,
06:46 you know, the, the headline, I guess the H1 of your website, if you will, is make AI apps.
06:52 Yeah, that's right. So basically I've already said H2O wave is a framework that allows you to build web
07:01 applications and dashboards with nothing but Python, no CSS, no HTML, no JavaScript required. However, if you wish
07:08 to sprinkle a little bit of JavaScript or CSS, then you definitely can. That's not a problem. And basically we try to build a rich library of widgets or components that are ready to use. And that should cover a wide range of scenarios that people might encounter. So at the end of the day, you end up with a very little bit of Python code that does very much.
07:36 Yeah. Let's set the stage a little, maybe thinking about what options do people have today? They've got an ML model that makes predictions, or maybe they've got something that will slice and dice the data and turn it into a graph, but you want to let them maybe pick the country by which you do, you pull the data from or the time range or some other aspect and make it a little bit interactive, you know, or even not, if you don't have that option, just make it static, I guess.
08:04 Like, what are the different things people are doing now that might relate to this?
08:08 Yeah, that's a great question. So the simplest thing that people can do is the regular tool of their interest is the notebook, which is very user friendly. You have just a single prompt, which you type into, and that behaves as a repo. And basically,
08:29 what they get in response are just static images of graphs or whatever. And these then can be then copy pasted as screenshots to either PowerPoint presentations or whatnot. However, this approach is, as you have said, somewhat static, and can be not so engaging, let's say. So that's where web application come into play, which can sprinkle a little bit of interactivity. So let's say you have a
08:57 So let's say you have a sidebar that has various controls like filters or maybe some sliders that adjust model values.
09:07 And on the right side, you get your visualization interactively in real time.
09:13 So this is something that has more storytelling power, let's say.
09:19 H2O Wave was initially built with this in mind as well.
09:24 Right, and Jupyter is fantastic.
09:25 I mean, so many people work in Jupyter and do amazing things, but it's not necessarily what you deliver to an end user.
09:34 If the CEO of your company says, hey, I want you to give me a dashboard that helps me understand, say, sales and cost this month,
09:46 you probably aren't going to just point them at your Jupyter Notebook on GitHub.
09:50 You probably still are not even going to point them at a version running on your server.
09:56 What if they want that updated every minute?
09:59 You know, with highlights or important stuff.
10:02 And they want to access it on their phone in a way that is like, you know, you have more control over how it lays out.
10:10 It's just, Jupyter is great, but it's not an end user technology.
10:15 It's an enabling technology, right?
10:18 It's like saying, well, I'm going to give PyCharm to a user to run my app.
10:22 It's like, well, no, no, no, no, no, no.
10:24 It's cool if you could run your code, but that's not the tool that you give them to do it with, right?
10:28 You package it up into a .app or whatever you're after.
10:31 Yeah, exactly.
10:32 And that's kind of the gap you're trying to close, right?
10:34 That's right.
10:35 Well, cool.
10:36 Okay.
10:37 Now, when I hear that, I think of a couple of other projects.
10:41 Streamlit, I interviewed Adrian back, I think it was 2019, who founded Streamlit.
10:47 And Streamlit is about building these really simple dashboards, sort of interactive places,
10:55 where, say, on the left, you've got a few things you can change.
11:00 And on the right, you might have some kind of graph, or you might get a 404 if you're clicking through the gallery right now.
11:06 But this is in that realm.
11:08 And then also, plotly dash as well.
11:12 Give us a sense of, like, how those compare.
11:16 Because there's probably people listening who are like, well, yeah, I'm really interested in this,
11:19 but I've already considered working with Streamlit.
11:21 Should I choose H2O Wave, or should I stick with Streamlit, or whatever?
11:25 Yeah, definitely.
11:26 So basically, one of the main reasons that Wave was built, because it's very similar to the project that you mentioned,
11:34 is that we were not very satisfied with either performance.
11:39 And the second reason was that, for example, Streamlit apps used to be very resource-heavy.
11:48 That means a lot of money in production costs.
11:52 So the reason was that Streamlit used to run a separate process for every single browser tab,
12:01 which, of course, demanded a lot of memory.
12:03 However, I have checked before this podcast to be 100% sure.
12:07 And it seems like they migrated to a single-threaded AsyncIO approach since then,
12:12 which is the same approach that, let's say, Dev or H2O Wave also follow.
12:18 So this is not a differentiator anymore.
12:20 The biggest differentiator is that H2O Wave has most features, let's say, most widgets to use.
12:29 And we also haven't seen any, let's say, regular web application beyond these filters and sliders that change your model outputs.
12:41 H2O Wave, we've seen, like, web applications that you would get maybe only software engineers could build, not the data scientists.
12:50 Right. So, for example, with Streamlit, what I often get, like, here I pulled up an example that they have, some real-time text thing.
12:58 And what you get is kind of this interactive, this one doesn't even have a sidebar.
13:01 It's pretty nice.
13:03 So you can, I've got a little drop-down and a button to start working with it.
13:06 But you don't have, like, a footer and a nav bar and multiple things on there with responsive layout.
13:11 And, you know, like a lot of the stuff you would expect, right?
13:14 It's still pretty close to what you might see on a notebook.
13:18 As nice as it is.
13:20 I do really like Streamlit.
13:21 Yeah, exactly.
13:21 We call this concept toy apps, let's say.
13:24 These are more like POCs, the stuff that we have talked to a while ago.
13:30 Wave is originally built with this in mind, but then somehow grew much larger that we can talk about it.
13:40 Yeah, it definitely seems like it's grown a bit more.
13:45 I haven't checked up on Streamlit enough to be able to follow along with exactly how many widgets they have and so on.
13:52 But, yeah.
13:52 Maybe compare to Plotly Dash as well.
13:56 Yes.
13:56 So I'm not very experienced with Plotly.
13:59 Neither am I, to be honest.
14:00 But assuming the same story there.
14:03 So they have a few form widgets, like text boxes, folders, drop-downs, etc.
14:09 That let you control the visualization.
14:12 But also, if you have a look, this visualization that you present, and these are like 3D models for our listeners who can see our screen.
14:22 Most likely, it's just third-party JavaScript library, which means that it's not necessarily a bundle of Plotly Dash.
14:29 So no Python API.
14:32 Right.
14:32 If we look over here at H2O Wave, the headline is Make AI Apps.
14:38 But it sounds to me like a broad range of apps could really land here.
14:42 If you're interested in almost any kind of reporting, dashboard, visualization, give us some ideas of the types of apps that people are building here.
14:50 The most common applications are the toy apps, as we have already discussed.
14:56 But once people truly discover the power of Wave, then they started to amaze us as developers.
15:04 Because they started to build production-grade applications that could be deployed and put to production and work just fine.
15:14 Right.
15:14 For example, H2O organized public, let's say, hackathon that aimed to save or to predict wildfires in California.
15:25 I believe in California, maybe in the whole world.
15:28 And one kind of software engineer built a truly wonderful Wave app that allowed them to submit their model, to preview them, to make scoreboard and everything within Wave application.
15:45 And it took in like two weeks, which is like incredible.
15:49 Yeah.
15:49 That's amazing.
15:50 Yeah.
15:51 But maybe some success story from a data scientist context, let's say, we have a team at H2O that wasn't very happy with one of our data science products.
16:02 So they decided, let's build one ourselves.
16:04 The result was that they have built, it's called Hydrogen Torch, a framework for deep learning.
16:12 And the result is a Wave application that was built within a week or two as an initial concept.
16:19 And it has features like you can train your models.
16:22 You can see how it predicts, let's say, computer vision models with the image annotations.
16:29 It has support for audio, if I remember correctly.
16:33 And it's...
16:34 Wow.
16:34 Yeah, exactly.
16:35 And it's simply just everything that you can expect from a regular web application.
16:40 And that blew my mind because the guys behind the Hydrogen Torch are not software engineers.
16:46 They are purely data scientists.
16:48 They are even Kaggle grandmasters for those who are aware of Kaggle platform.
16:54 And they were able to build it themselves, which is...
16:58 Oh, that's fantastic.
16:58 ...mind-blowing to me.
17:00 Hydrogen Torch.
17:01 Okay.
17:01 Yeah, I haven't heard of that.
17:02 It looks pretty cool.
17:03 It has experiment flow and dataset connectors and even pre-processed datasets.
17:08 Yes.
17:09 And remember that these features were built by data scientists, which is something that you
17:15 would typically require a whole software engineering team, right?
17:18 Right.
17:19 Probably didn't even use any TypeScript or React.
17:22 No.
17:22 That's cool.
17:24 This portion of Talk Python to Me is brought to you by Microsoft for Startups Founders Hub.
17:30 Starting a business is hard.
17:33 By some estimates, over 90% of startups will go out of business in just their first year.
17:37 With that in mind, Microsoft for Startups set out to understand what startups need to be successful
17:43 and to create a digital platform to help them overcome those challenges.
17:47 Microsoft for Startups Founders Hub was born.
17:50 Founders Hub provides all founders at any stage with free resources to solve their startup challenges.
17:56 The platform provides technology benefits, access to expert guidance and skilled resources,
18:02 mentorship and networking connections, and much more.
18:05 Unlike others in the industry, Microsoft for Startups Founders Hub doesn't require startups
18:10 to be investor-backed or third-party validated to participate.
18:14 Founders Hub is truly open to all.
18:17 So what do you get if you join them?
18:19 You speed up your development with free access to GitHub and Microsoft Cloud computing resources
18:24 and the ability to unlock more credits over time.
18:27 To help your startup innovate, Founders Hub is partnering with innovative companies
18:31 like OpenAI, a global leader in AI research and development, to provide exclusive benefits
18:36 and discounts.
18:37 Through Microsoft for Startups Founders Hub, becoming a founder is no longer about who you know.
18:42 You'll have access to their mentorship network, giving you a pool of hundreds
18:46 of mentors across a range of disciplines and areas like idea validation,
18:50 fundraising, management and coaching, sales and marketing, as well as specific
18:54 technical stress points.
18:56 You'll be able to book a one-on-one meeting with the mentors, many of whom
18:59 are former founders themselves.
19:01 Make your idea a reality today with the critical support you'll get from Founders Hub.
19:06 To join the program, just visit talkpython.fm/Founders Hub, all one word,
19:11 no links in your show notes.
19:13 Thank you to Microsoft for supporting the show.
19:14 I think maybe to give, to make this a little bit concrete to help people get a sense
19:21 of how you work with this and what it has to offer, I want to maybe talk
19:26 through two areas.
19:26 I want to talk through kind of getting started what it looks like to write some code here.
19:30 Also, maybe talk through some of the widgets because as you pointed out,
19:34 if you look through the widgets section, it's like a multi-level hierarchy of things,
19:41 but there's several hundred widgets that you can use so that's a lot to just be able to,
19:49 you know, write a few, one line of Python and bring in some amazing UI element,
19:53 right?
19:53 Yeah, exactly.
19:54 But let's start with going through the tutorial.
19:58 So, we can talk through maybe a couple of these because I think they're a little bit interesting.
20:02 They're all quite short and I'll keep it simple because I know code on the internet is hard
20:07 but just to kind of give you a sense of like some of the moving parts.
20:10 So, in order to do any of this stuff, maybe we should also think a little bit
20:16 about the architecture is you have a Wave server and you have Wave applications,
20:22 right?
20:22 You write these Wave applications in Python but the server itself is like a
20:26 Go centralized host like MicroWSGI or G Unicorn or something but for Wave,
20:32 right?
20:32 Yeah, exactly.
20:33 So basically, as you have said that there are two parts Wave server and Wave application.
20:38 Wave server is written in Golang and it provides one of the highlight features
20:44 of Wave and that is seamless integration with the OpenID Connect which is
20:49 authentication protocol because most of your enterprise applications need to be secured
20:58 somehow, right?
20:59 And as a data scientist, you just don't want to and cannot do that yourself
21:04 because it's security-wise tricky, but they...
21:08 Yeah, sure.
21:08 And even if you did, a lot of the OAuth flow requires you setting up certain endpoints
21:13 and it's tricky.
21:14 Yeah, exactly.
21:15 It's tricky even for regular or for engineers.
21:18 So, that's why we provide this feature out of the box and it's provided by Wave server
21:24 which our Wave app which is a Python server connects to and talks to browser
21:31 through as a proxy, let's say.
21:33 So, every...
21:34 all the data goes from Python application to Wave server and then Wave server
21:40 keeps an open WebSocket connection with browser to perform real-time.
21:46 Okay.
21:46 So, to get started, start the Wave server, create a virtual environment,
21:50 pip install H2O-Wave and then that's it.
21:55 You just have that one dependency.
21:56 I guess you might have to pip install H2O-Wave before you can start the server
22:01 if you haven't got it globally available but then you just have to write a little bit
22:05 of code.
22:06 Now, there's interesting paradigms that you've chosen here.
22:09 A lot of the web frameworks are stateless, right?
22:13 Here's an endpoint and the only thing this endpoint knows about anything
22:16 is that here's the request coming in, maybe a cookie is passed, maybe a query
22:21 string is passed or a form but other than that it's separate, unknown, unrelated,
22:26 no history and with these apps it's a little bit more like a single running
22:32 script that has a bit of a memory, right?
22:34 So basically a wave has two concepts let's say one is a wave script the other one
22:41 is a wave app and the difference is that wave script is as the name suggests a script
22:47 so you write a Python code you involve with like let's say python however
22:55 wrote that pi not like you would do with the normal regular Python script
22:59 and what that does is it converts your Python script wave data into a JSON
23:07 sends it to wave server and keeps it there so that means that your wave your Python
23:12 process is finished and you only serve your data from wave server to users
23:19 which is much more performant than if you had to rerun the script for every single
23:24 user as you would normally do and another concept is a wave app which is
23:30 something that most our users use and wave app lets you add interactivity
23:37 because with wave script more suited for dashboards which are just static
23:42 read only web apps let's say and you can even update it as you wish but with
23:48 wave application you probably want to handle your button clicks or drop down
23:54 changes and all this needs to be recorded back on python server right yeah you're
24:01 going to trigger elements of the page changing and things of that sort so one
24:06 thing that's interesting here is you create a site by giving it an endpoint
24:12 like slash hello and you can have multiple ones of these running on the wave
24:15 server right these multiple scripts or multiple apps and then you start working
24:19 with these widgets and these widgets can be composable and hierarchical and
24:24 they feel a little bit like almost like working with flutter right you have
24:28 these UI elements and you might have like a layout which has a grid and into the grid
24:32 you might put a table and into the table you might put cards right you kind of
24:37 build this up in code mostly you can use HTML and other templating languages but
24:43 mostly you write it in code by first this example you have here you just say I'm
24:47 going to create a UI dot markdown card right yes so basically the basic building
24:52 a block be it the script or apps is something called card so if you want
24:59 in the example in front of us you have specified UI dot markdown card which is
25:05 as the name suggests a card that lets you display markdown and interpret it
25:10 and that's about it you put your cards into the layout and that's it yeah you also
25:14 have the idea of basically a grid layout where you can position these cards to
25:21 be in a certain offset in a certain size right so in your hello world example you have
25:25 the position is box one one two two which means the top left and then too wide too
25:30 tall yes exactly so the box one one two two means cone one row one and width two and
25:37 height two we also support another type of layout and that responsive way
25:43 else for more advanced users this grid layout is more like the simplest layout
25:48 that we could write but it it's fixed it means that it may not work well
25:54 on every single stream but if you want if you want the more responsiveness
25:58 then definitely go for responsive layout which is based on flexbox right so maybe
26:03 it's five wide if you got a big screen but if it's on a phone they just all go
26:07 vertical exactly okay and let's see what else do I want to call it here all right I
26:12 think that one's that one's pretty good you also have this idea of editing your page
26:17 from the repl so after you've run that you can then just fire up python and start working
26:23 with it again how does that work it's mostly just for playing around maybe debugging
26:28 yeah maybe debugging but I don't think that people will develop that way
26:32 it's just to show people it's really nothing but python and no hidden content nothing like
26:39 that you can basically hit up your repo and work from there as well if you want
26:43 yeah but what's surprising to me is you can exit your python script and then you can open
26:48 the repl import the code and then make some calls to it and it actually changes the running
26:53 code that I see right yeah basically the magic behind that if you will notice we have
27:00 that page that save function which basically what it does is make a diff or what has
27:06 changed from your previous save and send it over to the web server and web server then
27:13 deals with that and displays whatever changes you have in it so since this is a static
27:17 file effectively it's just there's a singleton copy on the server that everybody's requesting
27:24 exactly that's why where it's suitable for dashboards sure so another thing that jumps
27:30 out is you make this change and then people who have the browser open to that page
27:36 it just changes they don't have to reload right it has built-in kind of smart hot
27:44 reload tell us about that exactly so this is one of the things that I think that
27:50 may be appealing even to let's say regular software engineers because the
27:56 problem with software engineers is like if you present them with framework like this
28:00 they want to have more control right we are software developers we need to have
28:05 control over everything that's why we don't like let's say WordPress that's a great
28:10 undoing the shiny thing and we have to create it ourselves yeah exactly but the problem
28:16 with let's say the typical approach to building web application today which is a single
28:21 page applications is that all the initial triggers want to be done from client side
28:27 from the browser but if you want to reflect changes that happened on the backend side
28:32 then this can be a bit problematic you either need to introduce polling which means
28:38 calling your web server your backend regularly but that may not be ideal
28:45 because you can flood your server unnecessarily I don't know why we can only
28:50 support 20 users at a time this doesn't make any sense or you can use web socket
28:57 which is not so easy to implement let's say and what wave uses is exactly
29:03 this web socket so it allows you to push changes from server to UI seamlessly
29:08 and that's also one of the wonderful features of wave right so basically
29:13 the takeaway for most people is as you develop your code as you develop your project
29:18 your app you'll have it maybe open on the side in your browser you make some
29:22 changes if you just hit save then it should automatically maybe you have
29:26 to rerun your script but you won't have to go and refresh your browser as well
29:31 right yes exactly even with the wave applications we use UVcorn as the underlying
29:37 Python server which has built in a hot reload and that means that you can
29:42 just save your file and everything reload automatically cool so UVcorn is watching
29:49 your Python files for changes so when you save it automatically restarts it
29:52 you don't even have to do that exactly if they restart it and also the browser
29:57 is refreshed yep okay fantastic so that's a pretty cool little hello world
30:03 the next one is to get the browser to sing 99 bottles of beer on the wall
30:08 this is a fun little demo but this one takes us from oh this one is still
30:14 a script so far right and then the next one will convert it to an app okay
30:19 so for this one the core takeaway here is basically a way to introduce like pushing
30:26 updates from the server to the client so for example you know people don't know
30:31 there's the 99 bottles of beer in the wall 99 bottles of beer take one down
30:34 pass it around now there's 98 then 97 then 96 right so you wanted to have it
30:39 like keep doing that over and over and over so if this was a console app
30:44 how would I do it I would probably say 4i in range and just for 99 and then 90
30:50 and I would just print just print print print print what you can do with wave
30:55 is you can have that exact same super straightforward for loop and then you just
30:59 go to your card that you put in the page and you just say content equals some
31:04 f string right that verse for that number and then you just call page and then
31:09 you don't want it to happen as fast as possible as you sleep right make it
31:13 come out a little bit slower but that does the multi cast broadcast to all
31:18 the clients watching just straight away right just loop over the code make some
31:22 changes and that will automatically push it I guess you got a call to you
31:26 but then it'll push it that's pretty impressive yeah and although by the way
31:30 just not to forget the original author of this framework you're not me but it's my
31:35 boss pretty probable which I would like to give shout out to because he's the
31:39 mastermind behind all this framework yeah cool it's definitely a cool framework
31:43 so this opens up a lot of possibilities for people coming to your site and getting
31:49 some form of interactivity now one thing he said is like I could build say like
31:54 a chat app or like some kind of bot and what I've seen so far it feels like
32:00 what is happening on the server is shared with everyone rather than dedicated
32:07 to a particular user or group of users how do I combine this to say like
32:11 I want them to sing this song but I want everyone maybe who logs in to have their
32:15 own copy right like Sarah came 30 seconds later she shouldn't join the song
32:22 halfway through or a third of the way through she should get it from 99 going
32:25 down yeah that's definitely possible the reason that you see for every single
32:31 dead the same output is because we are only looking at the scripts which
32:37 in case of dashboards that's totally understandable right everybody should
32:41 see the same dashboard because the data is always the same but with wave
32:45 apps you get basically the common behavior as you will suggest so every tab
32:52 can have its own thing session basically exactly so if you have a counter
32:59 app that has a single button and once you click it then it increments counter
33:04 you can basically have a single button instance for every single tab if you
33:10 want to but we also have something called multicast and broadcast mode and
33:17 that means that the value could be synced across every single tab if you
33:22 wanted to but the default mode is called unicast and that means that the
33:27 change is only propagated to the current client which is I see okay yeah
33:32 that makes a lot of sense this portion portion of talk Python is brought
33:37 to you by Sentry how would you like to remove a little stress from your life
33:41 do you worry that users may be encountering errors slowdowns or crashes with your
33:46 app right now would you even know it until they sent you that support email
33:50 how much better would it be to have the error or performance details immediately
33:54 sent to you including the call stack and values of local variables and the
33:58 active user recorded in the report with Sentry this is not only possible
34:03 it's simple in fact we use Sentry on all the talk Python web properties we've
34:08 actually fixed a bug triggered by a user and had the upgrade ready to roll
34:12 out as we got the support email that was a great email to write back hey
34:17 we already saw your error and have already rolled out the fix imagine their
34:20 surprise surprise and delight your users create your Sentry account at talkpython.fm
34:26 slash Sentry and if you sign up with the code talk Python all one word it's
34:31 good for two free months of Sentry's business plan which will give you up
34:35 to 20 times as many monthly events as well as other features create better
34:40 software delight your users and support the podcast visit talkpython.fm slash
34:45 Sentry and use the coupon code talk Python maybe this is a good time to pause
34:54 going through some of these code examples and some of these capabilities
34:57 Bob Vani has a good question what databases are supported not necessarily
35:03 even just databases but where does this code run is this PyScript and PyIodide
35:08 is this on the server what capabilities do I have can I pip install whatever
35:13 I want or am I limited basically there are the limit you know because all the
35:18 code is running in server so that means that you can basically connect to
35:23 any database of your choice the same way as you will do let's say in Django
35:28 or Flask app and so basically you can ppnf out anything you want on your
35:34 server I see so if it's supported with Python or in some crazy indirect way
35:39 that you might write some c you can call from Python you can call it it's
35:43 going to be like it's full Python so it does whatever you want it to do exactly
35:48 whatever you can make Python to do then it's possible in wave as well sure
35:53 that's really good to know all right so I guess maybe the third thing that
35:57 really is let's talk about two things real quick before I get to the third
36:01 one here one thing that's kind of interesting is what you're setting here
36:04 in this example is in the for loop you're saying the content is this f string
36:09 and you regenerate the entire f string and for this example it's like a tiny
36:14 little it's a verse in a song and who cares but you know if this was a much
36:18 more interesting like a full on Jinja style template and you want to change
36:23 one little small piece round tripping that full HTML every time is not the
36:30 most efficient so what you have because you're doing web sockets is you have
36:34 this idea of an expression to send some values over so you pass a dictionary
36:41 of the values and then you set the content to be an expression a little handlebar
36:45 thing like JavaScript front and binding or a Jinja value something along
36:51 those lines right tell us about this and how that works yeah so basically
36:54 it works basically what do you always send just the difference you know the tips
37:01 or let's say deltas what has changed to the UI and once these changes are
37:07 arrived to the browser then a react takes over it and renders whatever changes
37:13 have come right so in this particular case the first change would be the
37:17 whole string because there is nothing else there it would be rendered but
37:23 all the subsequent updates will only contain changes in the form of dictionary
37:29 values which is much less to care about on the network bandwidth type and
37:35 once these values arrive then react again takes over and does it magic and
37:40 updates the UI correctly yeah that's really neat so really great way to be
37:45 super efficient just by setting some values like on your card data dot whatever
37:51 you want to call it and then call save and those correspond over to your
37:55 expression right that makes up your template yeah and that's even more important
38:00 in our domain because data scientists usually have a lot of data extremely
38:08 a lot of data and that means that they would like to push it all into browser
38:13 and render their plots but if they dip on every single update then it might
38:19 not be the best way right so right if you've got a big page and a tiny little
38:25 plot that you want to change you know it'd be better to change that plot
38:29 but leave all the other stuff there exactly cool let's talk the last little
38:34 thing here about how this looks if we make it an actual an app I think if
38:39 you need to go to the list okay maybe be counter that would be simple I think
38:45 the bean counter one yeah the bean counter one yeah yeah yeah this is a real
38:48 simple one so the bean counter one is like a button you press it it just
38:51 goes one two three four right it shows things like state though and what
38:56 not but tell us how does it look different to create something like in the
39:01 script I didn't do anything hardly about like URLs or or functions to call
39:06 or returning I just did some stuff and then it somehow magically changed
39:10 but this looks a little bit more like flask right yeah so the difference
39:15 in syntax is that you need to have a single function that is synchronous
39:21 because we use a single not to block your UI and that function needs to be
39:29 annotated with an app annotation that takes the single required parameter
39:35 which is a URL pad that you want your app to be listened on and within this
39:41 function can I listen to forward slash like all these examples are like slash
39:45 counter and slash hello and so yeah you can also root which will be just
39:52 the forward slash and that's it yeah okay and just to get back so the annotate
39:58 function will give you one parameter which is Q and that stands for query
40:04 and that allows you to control your wave up so it has methods like Q that
40:09 save or Q page save I would say yeah Q page save which is an equivalent of
40:15 page save in our previous script example you also instead of page dictionary
40:22 that you put your cards in you need need need to just prefix it with Q so
40:27 you end up with Q page and then you specify your current and this is how
40:32 you get the per user type of thing because that queue is probably tied to
40:36 them right not necessarily the per user thing is by default but if you go
40:42 to the app annotation you can specify mode there so by default and that's
40:48 how it distributes the changes the queue is more like you can think of it
40:53 as a source of what has changed and how to update your UI so when we go through
41:00 the example you will see that it can also store some local pay or advice
41:06 pay etc okay one of the things that really jumped out to me was seeing the
41:12 async and await stuff everywhere so you have an async method you call await
41:17 page dot save and presumably if you want to work with beanie and mongodb
41:24 you could use its async api if you want to call an api endpoint with httpx
41:29 you could await those calls right so it really allows you to create scalable
41:35 code right yeah definitely and especially the reason why async is because
41:42 if you have the code like you have the single app which is two users and
41:47 the first user would create some blocking action then it would block it also
41:52 the second user because server is busy right it cannot respond so that's
41:57 why you need to make everything asynchromous and you're and you're you're
42:01 you said you're using uveacorn behind the scenes so that's a great server
42:07 for this kind of code yes exactly yeah in that's a lot of heavy lifting for us
42:12 yeah absolutely it's really good to build on it is it running some kind of python
42:16 framework that we don't see like a flask or FastAPI or something or is it
42:20 just all custom it uses starlight although I'm not sure if it the actual
42:26 server because I'm not very familiar with it yeah so starlight is the same
42:30 foundation as FastAPI and other things as well so that's cool all right
42:36 well there's a cool getting started people can walk through and check it out
42:39 it's pretty interesting because it's a it is a different programming model
42:44 compared to how many people would be familiar with flask and those types
42:50 of things that are very stateless and you've got to somehow figure out how to
42:53 get their session and then store then a database or a redis queue and then
42:56 get that back and then you know regenerate it right it's you have this inner
43:00 information more round tripped I think it'll resonate with a lot of people
43:03 it's definitely easier so I want to talk about the widgets but actually before we
43:10 talk about the widgets let's touch on one thing over in the examples here
43:14 templates so when I write traditional web applications let's call them I'll
43:20 create an HTML file and I'll probably use some template language like chameleon
43:25 or Django templates and pass a dictionary over there but I mostly think about what's
43:32 on the page by structuring an HTML file that has CSS and JavaScript and placeholders
43:39 for my things to go into and loops and that sort of thing is there a way
43:44 in HTML wave to have some template like that definitely although we do not
43:51 encourage it very much because we usually tend to think about using your
43:57 custom HTML as escape page and instead we try to provide you with Python
44:05 APIs whenever possible but if you really really want there is also HTML templating
44:12 if you need and that also work the same way as we described the script data
44:18 update so it takes one dictionary with the values and then HTML with the
44:26 templating language right does it do the partial updates based on that as
44:31 well or does it round trip the template the whole thing I'm not sure about
44:35 that one but I would say it also is capable of partial updates okay so basically
44:42 the examples that you have here are you have a little tiny fragment like
44:47 a fragment of HTML that'll go into the page and then that's the template
44:52 sounds a little bit like view components and that style yeah and maybe one more
44:58 the markdown a little bit together yeah exactly and maybe one more interesting
45:02 thing to note because the app that we are currently looking at is called
45:09 H2L Lave Tour and that also wave app in itself so you can see it looks nice
45:17 even though you have a small screen and it's a perfect example of what wave
45:23 is capable because all the code that we see in front of us is rendered in
45:29 VS Code Editor we use called Monaco Editor and that implemented via incorporating
45:36 custom JavaScript into wave so that means if you really need to include some
45:42 third-party libraries in JavaScript then we got you covered as well that's
45:46 really awesome yeah so this H2O wave tour lets you run the code locally and
45:51 explore it and search through the different examples which is really fantastic
45:55 so if you go to the website there's a getting started that shows you how
45:59 to get this up and running what we get is a nav bar across the top and then
46:04 like a drop down combo box and a next previous button on the right side of
46:09 the page we have the rendered output that's live and then on the left side
46:12 we have the code that makes it happen so what you're telling me is that little
46:16 square on the left pane of my two pane window that's basically VS Code yes
46:21 you can edit it you have open one if you can try to type into it hit W and
46:29 let's say button or maybe not maybe I remember it wrongly maybe my ad blockers
46:36 make it angry as well you never know okay but yeah that's cool yeah you get
46:42 like highlighting and indentations and yeah you can you can edit it and your
46:48 changes should be reflected on the right side as well yeah kind of instructive
46:51 yeah you can just set there and edit that's a really cool way to play with
46:55 it right you know you have stuff that'll say take you to repl or whatever
46:59 and there's all these pains like okay what do I click to actually make this
47:03 show up and where is it supposed to go this is this is a really cool way
47:06 to explore I think yeah okay so the thing I wanted to talk about was these
47:11 templates so there is some way to do little bits but it it sounds to me more
47:15 like it's it's a little bit this component model like this little section
47:19 this card that we're going to put somewhere on the screen here's its little
47:22 fragment of HTML that is an expression that goes with it yeah very very neat
47:28 the other one that's pretty nice is markdown right you have nice support
47:32 for just markdown out of the box so I think that's great if you have various
47:37 there's hundreds of examples and some people can go play there but there's
47:41 a couple for the different how markdown gets applied and used let's see another
47:47 thing you know you talked about you told me to type like wbutton and hit
47:51 and tab so that's part of one of the code extensions or plugins depending
47:57 on the editor you're using so you have VS Code and you have PyCharm plugins
48:02 that allow us to create things like if I got a form or something right I
48:08 could type like wform tab and it would go potentially create some kind of
48:14 UI element instead of me having to do that right or if you want to get a
48:18 scaffold up a starter application yes that's right so we have VS Code extension
48:24 and PyCharm plugin which have the same features and the features are one
48:31 is called snippet snippet or the templates that allows you to streamline
48:38 your typing a little bit so you don't need to think about how what are the
48:44 possible attributes in the button for example you can just yeah there is
48:50 a little demo so you can just type w underscore and your card name and it
48:57 will basically give you all the code that is needed and the second part is
49:03 autocomplete because most of the stuff in wave is based on dictionaries which
49:09 are dynamic in their nature so there is not much that the type system can
49:14 infer so we help with that a little bit as well yeah it's amazing how much
49:19 those sort of focused templates are like I'm here to create UI widgets I'm
49:24 telling you this reminds me a lot of Flutter I don't know if you've done
49:26 anything with Flutter just a little bit but the style of the way you create
49:31 these nested UI widgets and the editor tools to build them it's really nice
49:38 I like it I certainly if people are going to build real apps with this they
49:43 should be considering these extensions or plugins right yeah so Phil on the
49:48 audience has an idea says less intelligent more basic this might provide
49:51 an easy way to build a personal media streaming service on my Raspberry Pi
49:55 and a remote control interface to control and view from my phone what do
49:58 you think can you build a control go for it cool I'd say it sounds pretty
50:05 possible Joe the quick note that we are really interested in everything that
50:09 our community does so if you have some cool way up don't hesitate and bring
50:14 it up you can go to GitHub and discussions and there we have a discussion
50:20 dedicated to a community showcase so yeah definitely good idea a lot of things
50:27 I want to ask you about but we're going to run out of time so let's talk
50:31 about deployment so and is this a thing I have to buy in order to use H2O
50:38 wave so suppose I have a virtual Linux server at Linode I want to run this
50:44 there could I do it definitely wave is 100% free of charge so you can use
50:50 it even for commercial projects our license permitted and you can deploy
50:55 wherever we want we even had some blog posts about deploying wave apps on
51:02 Heroku and we plan to also add for AWS EC2 or Linode or whatever and however
51:11 if you are enterprise then part of our business model is that we we basically
51:17 provide a cloud solution for for app deployment for you so that's that's
51:23 okay so if I have like a team of data scientists and I don't want a dedicated
51:29 H2o wave DevOps person I can just pay you all some sort of money and you'll
51:35 set up some number of apps how's the pricing work there I'm not sure because
51:40 I'm not working on the cloud side of things but just to give you maybe more
51:45 just to shed more light on our initial intentions with wave we wanted to
51:52 solve basically three problems one was building nice UIs second was authentication
51:58 out of the box because this is painful and the third one was deployment because
52:03 if you are a data scientist you probably don't know much about it right right
52:07 so that is where our cloud platform comes to play which allows you to easily
52:11 deploy your web apps using CLI it's basically like so your business model
52:18 is basically H2O wave is free open source people can deploy it where they
52:23 want but if they don't want to manage the running and upgrading and backups
52:28 and all that they can buy that as a service from you exactly yeah that sounds
52:32 fair is it hard to set up if I want to host it myself not really basically
52:37 the simplest thing that you need to do is just run hit wave run and then
52:44 your app.py and that should basically run your application you expose your
52:50 correct ports and that I suppose I could put it behind Nginx successfully
52:55 I do got to do something special for like the web socket aspect of it I don't
53:00 think so because I don't think so either because you just need to expose
53:04 the web server part the web application part doesn't need to be exposed at all
53:09 and since the web server is the one that handles web sockets then it shouldn't
53:13 work right I think it just tells the browser hey we're upgrading to web sockets
53:16 let's keep going and that should go through Nginx I would guess okay that way
53:21 like I could do let's encrypt over and all that management stuff at the Nginx
53:27 level yes exactly yeah this sounds good the reason I ask is I know there's a
53:31 bunch of data scientists who don't want to do that but there's also people like
53:36 me who are mostly programmers but have a business with a bunch of dashboards
53:40 that might be cool to build and I've already got eight servers and a bunch
53:45 of stuff I could easily host it on one of them so for me I could set it up
53:49 and use it like I'm asking in a indirect but more broad sense like you know
53:53 this is useful for people beyond just the traditional I want slightly more
53:57 than Jupyter crowd right yes exactly we even think that it might be useful
54:02 for maybe people like you who are more of a software engineer my boss likes to say
54:09 that we would like to compete in Django although our it's not really direct competition
54:15 let's say I would say because Django requires you to know HTML and CSS and JavaScript
54:23 whereas we don't but at the people side we want to target also Python developers
54:30 sure if you're doing pure HTML Django servers up you can start bringing in
54:36 designers and front end people right there's like there's a different kind
54:40 of app that often gets built but can be built but especially if you're talking about
54:46 businesses 80% of the apps that they actually build are just like forms over
54:51 data I need to see what's in the database select a thing filter thing click
54:56 do something to it and that's the entire app right and it sounds like these wave
55:01 apps might be a good fit for it doesn't have to look like Airbnb landing page
55:07 what it needs to do is show me this stuff and let people get to it quick
55:11 and select them and make some actions real quickly right without spending weeks
55:16 to do it exactly would it be good for those kind of apps definitely we also
55:19 have sector stories related to that because we had some let's say product people
55:25 with some engineering skills or with end skills they needed some let's say
55:31 small internal app that would allow them for example to bring people to give trial
55:37 access to people to our platform and this needed to be done by backend developers
55:44 before because there was no infrastructure supporting it so one of our product
55:49 managers went ahead and built a wave app that did exactly that listed all
55:56 the pending trial users and allowed you to basically give them access and that's
56:03 it right it's a very small application but it will build in no time with tremendous
56:09 value yeah and you have all the widgets you need you've got buttons you can
56:13 type in various things you can sort of build up this interaction right you've got
56:18 dropdowns and search and the make it happen type of buttons do you have a grid
56:23 yes it's called table if you will search for it and I have one of the I'll do the
56:28 table search there you go yeah and basically this is one of the fundamental
56:32 components for data scientists right because you want to showcase your data sets
56:38 this is like the perfect component for it yeah even have little cool circular
56:43 progress bars which is those are really nice looking widgets yeah very good
56:48 and then I guess you even have it wasn't page it was filtering but yeah very
56:52 very cool yes we support search filter sort even pagination if you want and have
56:58 really a lot of data yeah we didn't even really get a chance to go through
57:03 all the widgets but you've got most things I can imagine you want to use to build
57:10 build an app you've got a color picker you've got choice groups like a radio
57:14 button I'm presuming you've got images you've got file upload do you have
57:19 a video player not yet but it should land soon because we are working on
57:24 a video annotator component which would basically be also usable as a video
57:30 player okay so you have a text annotator and this would be kind of same thing
57:35 and also an image annotator that's on the ml side where you say here's the
57:39 thing I'm going to feed my model tell it that this is a person and that is a
57:44 cat don't let it think the cat is a person or whatever right yes exactly
57:49 okay yeah cool so you'll probably have the video player as a building block
57:53 there right yes that sounds fun okay any other widgets you want to give a quick
57:57 shout out to I said there I mean there's a whole host of plotting I guess
58:01 also you can integrate with things like Altair and plotly and matplotlib
58:05 you don't have to stick with just your widgets yes and if anyone go to overlay
58:09 sections and we have things like dialogue sidebars etc notification bars
58:15 whatever you can think of if there is something that you need and it is not
58:20 there you can always file a feature request yep and that'll land on your
58:24 desk or on your screen you'll think about it perfect well it certainly looks like
58:30 a capable platform and ability to take it and just go run with it and deploy
58:34 it pretty excellent and if people out there and they don't want to deploy
58:37 it then you have a business for them business offering yes yeah very cool
58:43 all right real quickly because like I said we're getting short on time two things
58:47 let me pull up the actual app here so you have themes right if you it's like
58:54 five or six different ways in which your site can look and you can just apply
58:58 a theme or you can create custom themes or if you want to go crazy you can
59:02 actually include custom CSS right yes but you probably most likely don't want
59:08 to do that but if you want to you are free to go okay yeah there's a way
59:13 to create a UI widget that is a meta element where you can say include this
59:19 JavaScript either off your server or CDN or CSS yeah and also the other question
59:25 the other thing I want to touch on is JavaScript support yes so basically
59:28 we support arbitrary JavaScript as well you just include your script as if you
59:34 did in let's say Django or whatever other other server-side frameworks you are
59:41 good to go the example should be called inline script or script if you whatever
59:47 you wish there we go how about this one yeah so what's interesting is there's
59:50 a way to set up in JavaScript to push back into the wave app and trigger
59:56 that that function to run with new arguments right yeah exactly so that's
01:00:01 how you can basically reach the gap between JavaScript and Python you can
01:00:06 send your data back to Python yeah so you just say in JavaScript you just
01:00:09 say wave.emit and the event and then you know arguments basically right exactly
01:00:15 okay it's always nice to have these escape hatches you know like it's it's 85%
01:00:21 of what I need I just need a little bit something different here and if I
01:00:24 could just put two lines of JavaScript I know I could get there or I need to style
01:00:28 this just a little bit differently exactly cool all right Martin well very
01:00:33 cool project that you're working on here congrats on getting it out there
01:00:37 it looks like it's pretty popular people are definitely digging it and also I
01:00:41 love the command K stuff that you have here on your homepage where you can just
01:00:48 instantly jump in and like search around that that's pretty cool but 3000
01:00:53 GitHub stars looks like a cool framework not exactly a direct head-to-head
01:00:59 competitor Django and Flask but not that far off either right not the end map
01:01:03 let's hold it one day give it a year or two okay cool I love it yeah all right
01:01:08 now before you get out of here got the final two questions for you if we're
01:01:11 going to write some code what editor do you use I prefer VS Code the wonderful
01:01:16 VIM extension I cannot live without it anymore however I do think that the PyCharm has
01:01:23 much better language support I prefer VS Code because I need to jump between
01:01:27 multiple languages cool got it and I'm sure that you run the wave extension or
01:01:33 plugin there's all right yes of course of course and the notable PyPI package
01:01:39 something you find interesting or you want to recommend there are many of course
01:01:43 but maybe one that I would like to give a shout out to is planerite and basically
01:01:50 end-to-end testing framework nothing like Cypress I found that it can be
01:01:56 used for much more than just end-to-end testing we use it for visual regression
01:02:01 testing we use it for generating our imagery into documentation and I have
01:02:07 even done a lot of tests using that as well so it's pretty versatile tool
01:02:15 it's like the new Selenium sort of exactly yeah I did interview Andy Knight
01:02:20 three four months ago about this playwright is really neat it's I had to do
01:02:24 visual testing or testing where I kind of interact with the UI definitely what I
01:02:29 would pick these days yeah excellent all right final call action people want to
01:02:34 get started with wave what do they do either go to our docs which is wave
01:02:39 that they stole that AI or they can turn on our GitHub repository and they will
01:02:45 find their way there I believe and maybe just a quick note we are participating
01:02:52 in Hectoberfest so if you feel like you would like to contribute to open source
01:02:56 then you are more than welcome nice okay I'm sure a lot people are familiar with
01:03:01 Hectoberfest but maybe some aren't what's the story there so basically Hectoberfest
01:03:06 is a month long celebration of open source and it encourages people to contribute back
01:03:13 open source and if they do for valid pull request then they might be eligible
01:03:20 for swag or t-shirt cool and it is October recording on October 3rd so awesome
01:03:26 get out there and be part of it that sounds fun well wave sounds like a really
01:03:31 cool framework we have so many choices and I love that it takes advantage of
01:03:35 some of these modern python ideas like async and await whatever else you want to
01:03:39 bring into it so very cool work thanks for being on the show to share it with us
01:03:43 thanks for having me Michael yeah you bet bye bye this has been another episode
01:03:47 of talk python to me thank you to our sponsors be sure to check out what they're
01:03:52 offering it really helps support the show starting a business is hard Microsoft for
01:03:57 startups founders hub provides all founders at any stage with free resources
01:04:02 and connections to solve startup challenges apply for free today at talkpython.fm
01:04:08 slash founders hub take some stress out of your life get notified immediately about
01:04:13 errors and performance issues in your web or mobile applications with sentry
01:04:17 just visit talkpython.fm/sentry and get started for free and be sure
01:04:23 to use the promo code talkpython all one word want to level up your python
01:04:27 we have one of the largest catalogs of python video courses over at talkpython
01:04:32 our content ranges from true beginners to deeply advanced topics like memory
01:04:36 and async and best of all there's not a subscription in sight check it out
01:04:40 for yourself at training.talkpython.fm be sure to subscribe to the show open your
01:04:45 favorite podcast app and search for python we should be right at the top
01:04:48 you can also find the itunes feed at /itunes the google play feed at slash
01:04:53 play and the direct rss feed at /rss on talkpython.fm we're live we're live
01:04:59 we're live streaming we're live if you want to be part of the air be sure to
01:05:05 subscribe to our youtube channel at talkpython.fm/youtube this is your host
01:05:10 michael kennedy thanks so much for listening i really appreciate it now get out there
01:05:14 and write some python code you you you you you you you Thank you.