Learn Python with Talk Python's 270 hours of courses

#386: Realtime Web Apps and Dashboards with H2O Wave Transcript

Recorded on Monday, Oct 3, 2022.

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.

Back to show page
Talk Python's Mastodon Michael Kennedy's Mastodon