WEBVTT
00:00:00.020 --> 00:00:02.020
Where does your Python code actually run?
00:00:02.270 --> 00:00:03.300
A server in Virginia?
00:00:03.570 --> 00:00:04.720
A container in Frankfurt?
00:00:05.300 --> 00:00:07.140
Pyodide put Python in the browser.
00:00:07.799 --> 00:00:10.140
Cloudflare put the browser into the server.
00:00:10.520 --> 00:00:12.560
Combine the two and you get Python workers,
00:00:13.160 --> 00:00:15.400
now generally available from Cloudflare.
00:00:15.630 --> 00:00:17.440
My guests are Hood Chatham, Jay Choi,
00:00:17.900 --> 00:00:19.820
and Dominic Pichetta from Cloudflare.
00:00:20.420 --> 00:00:22.000
Hood and Jay maintain Pyodide.
00:00:22.240 --> 00:00:25.020
Dominic got Python running in Cloudflare workers.
00:00:25.600 --> 00:00:28.220
Your FastAPI app ships as plain files.
00:00:28.620 --> 00:00:31.660
Then you can run it on CPython, compiled to WebAssembly,
00:00:31.860 --> 00:00:35.980
inside V8, at over 350 locations worldwide.
00:00:36.700 --> 00:00:40.120
This is Talk Python To Me, episode 568, recorded October 9th,
00:00:40.460 --> 00:00:41.340
2026.
00:00:57.960 --> 00:00:59.220
Welcome to Talk Python To Me,
00:00:59.380 --> 00:01:02.580
the number one Python podcast for developers and data scientists.
00:01:03.060 --> 00:01:03.860
This is your host,
00:01:04.040 --> 00:01:04.500
Michael Kennedy.
00:01:04.940 --> 00:01:08.420
I'm a PSF fellow who's been coding for over 25 years.
00:01:09.060 --> 00:01:10.180
Let's connect on social media.
00:01:10.500 --> 00:01:12.760
You'll find me and Talk Python on Mastodon, Bluesky,
00:01:13.140 --> 00:01:13.660
and X.
00:01:13.940 --> 00:01:15.700
The social links are all in your show notes.
00:01:16.540 --> 00:01:20.040
You can find over 10 years of past episodes at talkpython.fm.
00:01:20.240 --> 00:01:23.420
And if you want to be part of the show, you can join our recording live streams.
00:01:23.800 --> 00:01:24.260
That's right.
00:01:24.450 --> 00:01:25.700
We live stream the raw,
00:01:25.860 --> 00:01:27.700
uncut version of each episode on YouTube.
00:01:28.320 --> 00:01:32.720
Just visit talkpython.fm/youtube to see the schedule of upcoming events.
00:01:32.940 --> 00:01:36.600
Be sure to subscribe there and press the bell so you'll get notified anytime we're recording.
00:01:37.119 --> 00:01:37.600
Tomorrow,
00:01:38.120 --> 00:01:38.320
Wednesday,
00:01:38.540 --> 00:01:41.620
November 4th, we're having our first tech meetup,
00:01:42.060 --> 00:01:44.400
our live tech event as part of Talk Python membership.
00:01:44.980 --> 00:01:46.000
If you're not yet a member,
00:01:46.480 --> 00:01:46.600
well,
00:01:47.100 --> 00:01:48.360
join up and support the show
00:01:48.580 --> 00:01:51.360
and get an awesome community and experience to boot.
00:01:51.880 --> 00:01:54.660
Just visit talkpython.fm, click membership in the nav bar,
00:01:54.860 --> 00:01:55.900
and you'll be off to the races.
00:01:56.520 --> 00:01:57.580
If you are a member,
00:01:57.800 --> 00:02:03.720
we'll be talking about Talk Python in production and some really wild new ideas that I'm exploring.
00:02:03.940 --> 00:02:07.560
I think you will find both fascinating and actually really practical,
00:02:07.840 --> 00:02:08.560
but no one's doing it.
00:02:09.080 --> 00:02:10.679
So join me on Wednesday, November 4th.
00:02:10.759 --> 00:02:12.600
And if you're listening to this after and thinking, Michael,
00:02:12.760 --> 00:02:14.260
why did you just put this in here?
00:02:14.360 --> 00:02:16.740
Nobody can listen to it because most people listen to after.
00:02:17.200 --> 00:02:18.520
These tech meetups come with recordings.
00:02:19.120 --> 00:02:21.160
Just visit talkpython.fm, click on membership,
00:02:21.320 --> 00:02:23.440
and then browse past member meetups and you'll be able to get it.
00:02:23.900 --> 00:02:26.800
So hopefully either you can join live or you can join afterwards.
00:02:27.580 --> 00:02:28.100
Become a member,
00:02:28.260 --> 00:02:28.840
support the show,
00:02:29.420 --> 00:02:29.840
join the event.
00:02:30.540 --> 00:02:31.360
Dominic J.
00:02:31.880 --> 00:02:32.060
Hood,
00:02:32.240 --> 00:02:34.140
welcome to all of you to Talk Python To Me.
00:02:34.390 --> 00:02:34.980
Awesome to have you here.
00:02:35.220 --> 00:02:35.880
Awesome to be here.
00:02:36.160 --> 00:02:36.420
Yeah,
00:02:36.720 --> 00:02:40.220
I'm really excited to talk about Python on the Edge.
00:02:40.580 --> 00:02:42.400
It's very exciting what you all have announced.
00:02:43.000 --> 00:02:46.700
And I know it's been out there on Cloudflare for a little bit,
00:02:46.860 --> 00:02:49.800
but it's now officially formalized, officially supported,
00:02:50.020 --> 00:02:51.060
a little more smooth.
00:02:51.400 --> 00:02:52.820
So Python workers,
00:02:53.280 --> 00:02:54.100
very, very cool topic.
00:02:54.610 --> 00:02:55.260
Before we get to that,
00:02:55.440 --> 00:02:56.880
though, let's just do a quick,
00:02:57.040 --> 00:02:57.780
who are you?
00:02:58.260 --> 00:03:01.360
Just give me a little bit of your background and what you do and so on.
00:03:01.680 --> 00:03:02.760
Dominic, we'll just go around the squares here.
00:03:02.880 --> 00:03:03.360
Dominic, go first.
00:03:04.160 --> 00:03:04.280
Sure.
00:03:05.330 --> 00:03:08.040
I mean, I can get started how I got into Python.
00:03:08.520 --> 00:03:10.020
And that starts at,
00:03:10.720 --> 00:03:13.380
I guess, a very young age when I was playing with Visual Basic.net.
00:03:13.760 --> 00:03:14.900
And I realized that I hate Windows.
00:03:15.460 --> 00:03:21.600
I needed to get to Linux and Visual Basic.net back then did not support Linux at all.
00:03:21.900 --> 00:03:22.000
So
00:03:22.540 --> 00:03:25.200
a couple of my friends were using Python. So that's how I got into it.
00:03:26.140 --> 00:03:26.620
Afterwards,
00:03:27.460 --> 00:03:30.360
I actually got a little bit annoyed that Python was interpreted.
00:03:30.880 --> 00:03:31.800
So I looked for
00:03:32.000 --> 00:03:35.060
alternatives and I got involved in the NIMH programming language.
00:03:36.440 --> 00:03:37.880
And I became one of the
00:03:37.960 --> 00:03:39.440
core developers of that for a while.
00:03:40.660 --> 00:03:41.520
Fast forward a lot.
00:03:42.340 --> 00:03:43.440
I was working at
00:03:44.140 --> 00:03:51.020
meta and then I moved to Cloudflare to work on the workers runtime team working there on a bunch of
00:03:51.700 --> 00:03:53.120
features for workers in general.
00:03:54.080 --> 00:03:58.040
I actually was the person I guess that kind of experimented with
00:03:58.160 --> 00:04:05.760
Pyodide at Cloudflare and got it working and running and then eventually we got Hoodin to
00:04:05.790 --> 00:04:11.060
help us out with that and we started Python Workers and I've been working on that ever since as well
00:04:11.540 --> 00:04:12.100
And still do.
00:04:12.360 --> 00:04:12.740
Very,
00:04:12.920 --> 00:04:13.240
very excellent.
00:04:13.600 --> 00:04:13.820
You know,
00:04:14.000 --> 00:04:15.560
a word I haven't thought about for a while
00:04:15.760 --> 00:04:17.000
is visualbasic.net.
00:04:17.299 --> 00:04:19.060
I've written a little bit, a little bit.
00:04:19.239 --> 00:04:21.940
I mean, we're talking a couple of files of visualbasic.net.
00:04:22.280 --> 00:04:23.220
What of her boast language?
00:04:23.410 --> 00:04:23.840
I don't know.
00:04:24.160 --> 00:04:25.300
Great language to learn with, though.
00:04:25.580 --> 00:04:26.340
It is, it is.
00:04:26.600 --> 00:04:28.760
You know, I think it's interesting to contrast that
00:04:28.900 --> 00:04:29.200
with Python,
00:04:29.450 --> 00:04:29.540
actually,
00:04:29.720 --> 00:04:31.680
because Python also had many
00:04:31.720 --> 00:04:33.440
of the same goals of VB,
00:04:33.660 --> 00:04:35.800
but it somehow accomplished it
00:04:35.850 --> 00:04:38.340
with a lot less stuff on the screen.
00:04:38.740 --> 00:04:40.240
You know, like there's not begin if,
00:04:40.460 --> 00:04:41.940
end if, all this type of stuff.
00:04:42.030 --> 00:04:42.860
But yeah, very, very fun.
00:04:43.240 --> 00:04:43.320
Jay,
00:04:43.520 --> 00:04:43.920
welcome.
00:04:44.280 --> 00:04:44.500
Hey,
00:04:44.860 --> 00:04:47.880
I think I can start with how I started using Python as well,
00:04:48.060 --> 00:04:48.660
like Dominic.
00:04:48.860 --> 00:04:54.740
So I also started programming using some Visual Basic NC when I was like 10 years ago.
00:04:55.010 --> 00:05:01.120
And then I started learning Python when I was in second grade in university,
00:05:01.340 --> 00:05:01.700
I think.
00:05:01.960 --> 00:05:07.860
I was having some data science course learning about packages like ThumbPy and SciPy.
00:05:08.040 --> 00:05:10.160
That was when I first started using Python.
00:05:10.650 --> 00:05:12.120
And I just fell in love with Python.
00:05:12.760 --> 00:05:15.060
Like making apps were so easy with Python.
00:05:15.370 --> 00:05:19.920
So I was using, I started, starting then I started using Python for like 10 years.
00:05:20.880 --> 00:05:22.620
And around 2021,
00:05:23.410 --> 00:05:28.720
I started contributing to a library called Pyodip,
00:05:28.880 --> 00:05:31.760
which I think we will talk a lot in this podcast.
00:05:32.320 --> 00:05:37.080
And yeah, after maintaining it for around one or five years,
00:05:37.500 --> 00:05:45.980
I got invited to Cloudflare to work on Python workers using Pyrodite from Hoots and joined Cloudflare.
00:05:46.400 --> 00:05:51.300
And yeah, after that, I was working on Cloudflare Python workers for around a year.
00:05:51.600 --> 00:05:55.760
That's super cool that contributing to the project got you that position.
00:05:56.520 --> 00:05:59.440
It's like, I'm really interested in this thing and I get to work on it for a while.
00:05:59.540 --> 00:06:00.340
And all of a sudden they're like, well,
00:06:00.580 --> 00:06:02.560
what if we paid you to do it all the time?
00:06:02.980 --> 00:06:04.080
That's just great, right?
00:06:04.360 --> 00:06:04.580
Yeah,
00:06:04.760 --> 00:06:10.560
it's really interesting that you start to contribute on open source and you get a job with that.
00:06:10.780 --> 00:06:15.020
That's something that all the open source contributors are hoping to.
00:06:15.280 --> 00:06:16.080
Good. Welcome to the show.
00:06:16.380 --> 00:06:19.360
I started out on Lispy MLE languages.
00:06:19.960 --> 00:06:22.520
So I'm a mathematician by training.
00:06:23.720 --> 00:06:29.060
I wrote my first Python code for undergraduate introduction to programming class.
00:06:29.520 --> 00:06:35.200
but then I didn't use it at all until I had to write an email schedule for the math seminar
00:06:35.780 --> 00:06:42.600
which was in Python 2.7 and I am as a mathematician I was very interested in
00:06:43.820 --> 00:06:50.360
math software to try to get software that does a good combination of like research level
00:06:51.250 --> 00:06:58.239
you know like high performance computing and also just like quick experiments and lets people
00:06:58.540 --> 00:07:01.780
figures step out. And I found out that mathematicians don't like to install software
00:07:02.320 --> 00:07:03.720
on their computer. They assume it won't work.
00:07:04.550 --> 00:07:05.100
Of course, a lot of...
00:07:05.100 --> 00:07:06.480
They still have scars from Fortran.
00:07:06.640 --> 00:07:06.920
That's why,
00:07:07.080 --> 00:07:07.200
probably.
00:07:08.000 --> 00:07:08.180
Yeah.
00:07:08.480 --> 00:07:08.840
And also,
00:07:09.100 --> 00:07:14.480
a lot of math software is made by mathematicians and it's not an easy thing to
00:07:14.580 --> 00:07:16.500
distribute software for other people to use.
00:07:16.720 --> 00:07:18.120
And so it's like they have something that works on
00:07:18.240 --> 00:07:21.000
their computer and they tell all their friends, oh, you should use this. And they say, nah,
00:07:21.160 --> 00:07:21.280
man.
00:07:22.380 --> 00:07:28.220
So that was how I got interested in WebAssembly. I mean, I first started by writing software in
00:07:28.240 --> 00:07:32.600
LaTeX because mathematicians already have LaTeX on their computer and they already have TechLive
00:07:32.610 --> 00:07:33.180
on their computer.
00:07:33.570 --> 00:07:36.100
And that's a package manager. It can just get your package onto their computer
00:07:36.280 --> 00:07:36.600
automatically.
00:07:37.140 --> 00:07:41.580
But like people just wouldn't use things that didn't come sort of connected with
00:07:41.720 --> 00:07:42.820
something they already had on their computer.
00:07:43.180 --> 00:07:45.600
And because browsers are a universal computing
00:07:45.820 --> 00:07:46.000
platform,
00:07:46.280 --> 00:07:50.760
you know, I watched the birth and death of JavaScript back in like 2014 or whatever.
00:07:51.280 --> 00:07:52.380
One of the best talks ever.
00:07:52.870 --> 00:07:53.300
So good.
00:07:53.700 --> 00:07:53.820
Yeah,
00:07:54.170 --> 00:07:54.300
yeah,
00:07:54.480 --> 00:07:54.880
it's so good.
00:07:55.430 --> 00:07:57.680
And so I was very excited about the idea of like,
00:07:57.900 --> 00:07:58.020
oh,
00:07:58.220 --> 00:08:00.400
we should just make the software work in WebAssembly
00:08:00.680 --> 00:08:01.540
and ship it to the browser.
00:08:01.810 --> 00:08:04.340
And then mathematicians won't be able to like complain
00:08:04.620 --> 00:08:06.700
that it's maybe takes some work to install.
00:08:08.000 --> 00:08:09.700
But then if you want to have like,
00:08:09.900 --> 00:08:10.040
you know,
00:08:10.300 --> 00:08:11.180
powerful math software,
00:08:11.600 --> 00:08:11.720
you know,
00:08:12.100 --> 00:08:14.140
I wrote all the linear algebra stuff in Rust,
00:08:14.720 --> 00:08:14.980
but then,
00:08:15.480 --> 00:08:15.600
you know,
00:08:16.380 --> 00:08:19.620
you don't really get that much control over it from Rust.
00:08:20.220 --> 00:08:23.080
And you can make a GUI, you can give people JavaScript,
00:08:23.580 --> 00:08:24.640
But, you know,
00:08:25.260 --> 00:08:33.260
JavaScript is really a bit anemic in terms of, you know, like, for instance, our logic have lots of tables of things that were indexed by, you know, tuples of integers.
00:08:34.099 --> 00:08:34.820
And like,
00:08:35.159 --> 00:08:35.380
you know,
00:08:35.700 --> 00:08:39.979
having a map in Python that is nicely indexed by tuples of integers is like,
00:08:40.159 --> 00:08:41.340
you know, you could do it in JavaScript.
00:08:41.560 --> 00:08:42.460
It's just it's just a pain.
00:08:42.820 --> 00:08:46.880
So I really wanted to get Python to be in my web application with everything else.
00:08:47.820 --> 00:08:52.920
And so I found out about Pyodine and I started messing around with it, but it was really buggy and didn't work very well.
00:08:53.260 --> 00:08:54.900
you know, I mean, it was a sort of technical,
00:08:55.400 --> 00:08:56.060
you know,
00:08:56.360 --> 00:08:57.040
like demonstration.
00:08:57.280 --> 00:08:58.080
I mean, it showed
00:08:58.200 --> 00:08:59.460
a lot of promise because,
00:08:59.940 --> 00:09:00.100
you know,
00:09:00.260 --> 00:09:02.820
there was NumPy there running in the browser.
00:09:03.580 --> 00:09:03.680
So,
00:09:03.980 --> 00:09:04.100
you know,
00:09:04.180 --> 00:09:05.760
these binary extensions were working.
00:09:06.400 --> 00:09:06.580
But,
00:09:07.320 --> 00:09:07.460
you know,
00:09:07.660 --> 00:09:09.680
Mike Dropeboom did like amazing work at
00:09:09.920 --> 00:09:14.900
Mozilla to get that working. And I mean, Mozilla really created this whole cool chain on top of it.
00:09:15.260 --> 00:09:15.720
Anyways,
00:09:15.980 --> 00:09:17.860
I can maybe say more about that later.
00:09:18.160 --> 00:09:21.279
But I found PyDyde and it was just a bit after
00:09:21.300 --> 00:09:26.160
mozilla killed the whole project so it wasn't you know um roman urchuk was like just barely keeping
00:09:26.200 --> 00:09:29.800
the lights on and i showed up and i was like here are all the things that are bad about what's
00:09:29.860 --> 00:09:35.640
currently going on it kind of expecting him to be like oh like you're an asshole go away but he was
00:09:35.680 --> 00:09:40.360
like oh well why don't you come fix those things and so so i so he made me into a maintainer it
00:09:40.540 --> 00:09:46.300
actually first took another math that i was working with on the same project uh dexter who who had some
00:09:46.440 --> 00:09:50.540
experience with open source and so he started contributing to fix the problems that i found i
00:09:50.560 --> 00:09:52.240
I was like, oh, I guess I can contribute to this.
00:09:53.340 --> 00:09:53.480
Yeah.
00:09:53.880 --> 00:09:56.680
That's a great way to handle somebody coming and say, I have these complaints.
00:09:56.940 --> 00:09:57.240
It's like,
00:09:57.660 --> 00:09:58.140
instead of saying,
00:09:58.520 --> 00:09:59.840
go away, it's like, you know what?
00:10:00.180 --> 00:10:01.100
Here's how you can fix them.
00:10:01.440 --> 00:10:01.620
Yeah,
00:10:01.840 --> 00:10:01.960
right.
00:10:02.120 --> 00:10:03.000
Yeah, very productive.
00:10:03.340 --> 00:10:03.540
Right.
00:10:03.640 --> 00:10:04.540
They weren't defensive at all.
00:10:04.660 --> 00:10:06.040
They were just like, great, we want this to be better.
00:10:06.440 --> 00:10:06.540
Like,
00:10:06.860 --> 00:10:08.460
if you want to make it better, please make it better.
00:10:09.420 --> 00:10:13.800
And so then I got a National Science Foundation postdoc for math.
00:10:14.220 --> 00:10:16.460
I said I would improve mathematical computing software.
00:10:16.680 --> 00:10:19.660
And so I ended up spending most of that postdoc working on Pyodide.
00:10:20.500 --> 00:10:26.460
And then when I was leaving the postdoc, I got hired to Anaconda to work on their PyScript stuff.
00:10:26.940 --> 00:10:28.260
And then about six months later,
00:10:28.560 --> 00:10:33.920
I got connected to Cloudflare and they were interested in me working on making Python workers exist.
00:10:34.300 --> 00:10:36.760
That was obviously a very fun project.
00:10:37.740 --> 00:10:37.820
Yeah,
00:10:38.000 --> 00:10:39.620
PyScript is such an interesting project.
00:10:40.380 --> 00:10:42.080
I don't know what the future holds for PyScript,
00:10:42.300 --> 00:10:43.840
but it's a very neat project.
00:10:44.280 --> 00:10:45.680
Yeah, it was really an interesting project.
00:10:46.080 --> 00:10:46.460
Actually,
00:10:46.780 --> 00:10:50.840
a lot of people first learned about running Python in the browser from PyScript,
00:10:51.090 --> 00:10:52.100
not from Pyodide.
00:10:52.520 --> 00:10:54.200
Yeah, it was a really interesting project.
00:10:54.540 --> 00:10:59.020
It's very unfortunate they turned into a maintenance mode recently, but they did a real great job.
00:10:59.020 --> 00:11:00.040
I know, it makes me sad.
00:11:02.020 --> 00:11:03.120
Maybe it's just taking a break.
00:11:03.320 --> 00:11:05.660
Maybe it'll come back in the future in some amazing form.
00:11:05.740 --> 00:11:12.300
I would love to see a React or a Vue alternative that just runs all on PyScript.
00:11:12.360 --> 00:11:12.500
But,
00:11:12.840 --> 00:11:16.380
you know, I don't think backed by Pyodide, backed by MicroPython,
00:11:16.840 --> 00:11:17.220
which would be,
00:11:17.640 --> 00:11:19.580
you know, I think a little more practical for web front end.
00:11:19.680 --> 00:11:22.640
But that is an alternate reality and a different thing that we're talking about.
00:11:22.780 --> 00:11:29.540
So let's begin maybe just a quick review of like running in the browser.
00:11:29.620 --> 00:11:33.120
So the goal of Pyodide is to run wherever WebAssembly runs.
00:11:33.580 --> 00:11:33.900
Primarily,
00:11:34.120 --> 00:11:34.640
that's the browser,
00:11:34.800 --> 00:11:35.840
though it doesn't have to be.
00:11:35.920 --> 00:11:39.380
You know, you can kind of treat WebAssembly a bit like a Docker type of thing, like an isolation.
00:11:39.380 --> 00:11:40.120
You can use the JavaScript.
00:11:40.340 --> 00:11:40.420
Right.
00:11:41.080 --> 00:11:47.840
So it does not work in WASM time or these other WebAssembly only run times, but it should work in any JavaScript run.
00:11:47.980 --> 00:11:50.220
I see. So I could run it locally if I had, say,
00:11:50.520 --> 00:11:51.740
Node or Bun or something like that, maybe?
00:11:52.040 --> 00:11:52.420
Absolutely.
00:11:52.740 --> 00:11:52.800
Yeah.
00:11:52.980 --> 00:11:53.760
Okay. That's interesting.
00:11:54.160 --> 00:11:57.480
So we have this WASM execution time,
00:11:58.280 --> 00:11:59.140
execution framework here.
00:11:59.620 --> 00:12:06.260
And the idea you all had is like, well, we have all these points of presence throughout the world with Cloudflare.
00:12:06.620 --> 00:12:07.500
How many places,
00:12:08.190 --> 00:12:10.820
how many spots does this run at? You all know.
00:12:10.880 --> 00:12:15.600
oh i don't know by heart there's like a website you can go on and tells you the
00:12:16.020 --> 00:12:22.140
all of them i think i think the number is above 350 yeah yeah it sounds like yeah so that puts
00:12:22.600 --> 00:12:29.560
10 tends to a hundreds on any given continent right so the idea is with these these kind of
00:12:29.600 --> 00:12:32.220
getting ahead of ourself a little bit but the idea is like well what if we could take this
00:12:32.740 --> 00:12:39.719
pyodide thing that is a miniature python runtime and put it really really close to all the users
00:12:39.720 --> 00:12:42.120
and execute it there instead of routing back,
00:12:42.480 --> 00:12:42.620
you know,
00:12:43.020 --> 00:12:45.460
somewhere in US East 1 or something like that, right?
00:12:45.680 --> 00:12:46.300
Yeah, precisely.
00:12:46.740 --> 00:12:51.360
I mean, you're giving the exact explanation
00:12:51.540 --> 00:12:54.840
that I think a lot of our, like, marketing people would give,
00:12:55.250 --> 00:12:55.720
which is great.
00:12:56.620 --> 00:12:56.820
Basically,
00:12:57.180 --> 00:12:57.260
yeah,
00:12:57.420 --> 00:12:57.560
like,
00:12:57.870 --> 00:13:00.220
you want as little latency as possible
00:13:00.250 --> 00:13:00.800
for your users,
00:13:01.000 --> 00:13:01.100
right?
00:13:01.130 --> 00:13:03.660
So you want to run Python code as close to them as possible,
00:13:03.810 --> 00:13:05.760
and this is a very great way to do that.
00:13:05.980 --> 00:13:07.620
Yeah, and it doesn't run, to be clear,
00:13:07.920 --> 00:13:13.640
what we're talking about does not run in the browser of users like Pyodide can.
00:13:13.920 --> 00:13:19.860
It runs in the edge nodes of Cloudflare that happen to be very near the users, right?
00:13:20.200 --> 00:13:23.680
So I think that's a big difference because it gives you access to an entire platform
00:13:24.280 --> 00:13:27.440
like data and queues and all that kind of stuff that we're going to talk about,
00:13:27.620 --> 00:13:27.680
right?
00:13:28.120 --> 00:13:31.600
The way I like to describe it is like Pyodide is kind of this crazy idea of like,
00:13:31.600 --> 00:13:33.360
we should put Python into the browser.
00:13:33.680 --> 00:13:35.680
And then Cloudflare is kind of this crazy idea of like,
00:13:35.680 --> 00:13:37.560
we should put the browser into the server.
00:13:38.060 --> 00:13:39.800
and so when you put Python into the browser
00:13:39.860 --> 00:13:41.020
and you put the browser in the server,
00:13:41.220 --> 00:13:42.880
that's a funny way of getting Python into the server.
00:13:43.200 --> 00:13:45.740
Yeah, as a mathematician by the transitive property,
00:13:46.120 --> 00:13:46.940
you click it all together.
00:13:47.340 --> 00:13:48.940
It sounds like a crazy idea though.
00:13:49.220 --> 00:13:49.460
Yeah.
00:13:50.040 --> 00:13:51.960
So let's talk PyDyde just for a minute
00:13:52.120 --> 00:13:53.080
before we dive in,
00:13:53.300 --> 00:13:55.140
now that people see where we're going with PyDyde.
00:13:55.360 --> 00:13:56.460
Let's talk about it a little bit
00:13:56.680 --> 00:13:57.620
because very recently,
00:13:57.980 --> 00:13:58.700
let's put some,
00:13:58.880 --> 00:13:59.500
one month ago,
00:14:00.100 --> 00:14:03.920
Hood and JU2 gave a talk at EuroPython,
00:14:04.220 --> 00:14:05.340
which I thought was really interesting.
00:14:05.560 --> 00:14:06.140
Python Everywhere,
00:14:06.320 --> 00:14:08.000
the state of Python on WebAssembly.
00:14:08.270 --> 00:14:09.780
So this is a more general,
00:14:10.000 --> 00:14:12.840
not just Cloudflare worker type of story,
00:14:13.060 --> 00:14:15.440
but give us an update.
00:14:15.610 --> 00:14:17.340
What is the state of Python on WebAssembly?
00:14:17.640 --> 00:14:18.440
Things are good.
00:14:20.340 --> 00:14:26.320
It feels like there is less and less stuff that's going wrong.
00:14:27.680 --> 00:14:31.219
So I have these Python enhancement proposals
00:14:31.220 --> 00:14:37.040
to try and rearrange the governance of our code
00:14:37.600 --> 00:14:40.780
so that it can live maybe more of the stuff
00:14:41.140 --> 00:14:42.560
in the CPython repository.
00:14:44.100 --> 00:14:46.580
But yeah, I mean, I remember just a few years ago
00:14:46.670 --> 00:14:48.560
that there were always like crazy problems
00:14:49.100 --> 00:14:53.040
and lots of confusing bugs.
00:14:53.580 --> 00:14:55.380
And it was like,
00:14:55.590 --> 00:14:55.780
yeah,
00:14:56.100 --> 00:14:57.440
like we got lots of bug reports
00:14:57.720 --> 00:14:58.700
that would just be like,
00:14:58.730 --> 00:15:00.040
I have no idea what to do with this.
00:15:01.260 --> 00:15:04.400
But it feels like we really polished it a lot.
00:15:04.700 --> 00:15:11.980
And I mean, especially Jay moved all of the package build system into external repositories.
00:15:12.560 --> 00:15:16.020
And so the package build system is much less causing us trouble,
00:15:16.400 --> 00:15:19.560
although it's still still causing us some residual trouble.
00:15:19.760 --> 00:15:23.380
But now we have the PEP that says we can upload packages to PyPI.
00:15:23.860 --> 00:15:30.760
So it really feels like it's kind of making this graceful landing and approaching something that, you know,
00:15:31.040 --> 00:15:34.100
it will always take maintenance to keep up with upstream Python,
00:15:34.520 --> 00:15:36.720
but I'm sort of feeling like
00:15:36.870 --> 00:15:39.660
it's taking less and less in addition to that, which is nice.
00:15:39.820 --> 00:15:42.140
What's the situation or the state
00:15:42.380 --> 00:15:47.460
with Pyodide and Python on WebAssembly in terms of being officially supported by the core
00:15:47.680 --> 00:15:48.580
developers of Python?
00:15:48.960 --> 00:15:54.320
I feel like it's gotten some sort of build support acknowledgement before they
00:15:54.720 --> 00:15:59.760
were willing to ship CPython that Python on WebAssembly also compiles. Is that right?
00:15:59.960 --> 00:16:00.460
Yeah,
00:16:00.650 --> 00:16:02.820
so, right, so Python,
00:16:03.480 --> 00:16:05.920
sorry, so the platform we have is called Emscripten, right?
00:16:06.170 --> 00:16:08.080
This is the Emscripten compiler tool chain,
00:16:08.650 --> 00:16:14.020
which is this incredible thing that is front end for Clang and ships.
00:16:14.920 --> 00:16:18.200
JavaScript system calls JavaScript implementation of a file system.
00:16:18.540 --> 00:16:22.520
It's like a JavaScript Musa Linux that Emscripten compiles to.
00:16:22.940 --> 00:16:29.380
And so we have to recommend that people go back and watch the birth and death of JavaScript because it tells the story so well, right?
00:16:29.480 --> 00:16:29.760
Yeah,
00:16:30.140 --> 00:16:31.520
it's one of the greatest videos ever,
00:16:31.740 --> 00:16:31.940
for sure.
00:16:32.860 --> 00:16:35.180
And so, okay, so Emscripten is the platform,
00:16:35.680 --> 00:16:39.600
and Emscripten is tier three supported upstream by Python.
00:16:40.900 --> 00:16:42.960
And what that means is that we,
00:16:43.180 --> 00:16:44.260
well, we run it in CI,
00:16:45.760 --> 00:16:46.240
and,
00:16:47.200 --> 00:16:48.260
you know, it's best effort,
00:16:48.540 --> 00:16:48.760
you know,
00:16:48.980 --> 00:16:50.140
people are allowed to break it,
00:16:50.400 --> 00:16:50.600
and,
00:16:50.940 --> 00:16:52.360
like, I come back and fix it.
00:16:54.080 --> 00:16:56.060
And it's not a release block,
00:16:56.060 --> 00:16:58.640
or they, in fact, do not make releases for Emscripten.
00:16:59.620 --> 00:17:09.980
The reason they don't make releases for Emscripten is because they don't have really a version of like the OS module or for Emscripten.
00:17:09.980 --> 00:17:13.620
So they can't really do IO very much.
00:17:14.100 --> 00:17:15.660
They can't make requests.
00:17:16.459 --> 00:17:18.140
You know, they can't do HTTP stuff.
00:17:18.600 --> 00:17:20.260
They can't receive user input.
00:17:20.459 --> 00:17:22.560
And so in my opinion,
00:17:22.980 --> 00:17:25.920
if we build these executables,
00:17:26.560 --> 00:17:29.860
but no one would want to use it as it is built upstream.
00:17:30.110 --> 00:17:31.240
And so I have this proposal,
00:17:31.410 --> 00:17:32.740
which is PEP 818,
00:17:32.930 --> 00:17:36.440
which I just submitted a few days ago for review by the steering council,
00:17:36.740 --> 00:17:47.920
which is supposed to rectify the situation and make it so that we can have basically useful inscriptive iPhone binaries.
00:17:48.420 --> 00:17:48.620
Okay,
00:17:48.960 --> 00:17:50.980
so let me read the title of PEP for folks.
00:17:51.160 --> 00:17:52.240
It's PEP 818,
00:17:52.520 --> 00:17:56.220
adding the core of the Pyodide foreign function interface to Python.
00:17:56.720 --> 00:18:00.620
Is this a little bit like the ABI interface or CFFI, something like that?
00:18:00.940 --> 00:18:04.820
It's a little bit like CFFI or C types.
00:18:05.180 --> 00:18:05.400
You know,
00:18:05.700 --> 00:18:06.260
the package,
00:18:06.460 --> 00:18:09.420
the top level import is going to be JS types,
00:18:09.600 --> 00:18:10.700
which is following C types.
00:18:11.700 --> 00:18:12.340
And yeah,
00:18:12.500 --> 00:18:16.720
like the point of it is to allow calling JavaScript functions from Python,
00:18:16.840 --> 00:18:21.660
which is important because basically all functionality in a JavaScript runtime goes
00:18:21.680 --> 00:18:22.280
through JavaScript,
00:18:22.480 --> 00:18:24.860
just like the way all functionality in Linux goes through C.
00:18:25.060 --> 00:18:25.220
Okay,
00:18:25.660 --> 00:18:25.860
excellent.
00:18:26.260 --> 00:18:28.340
And this is in draft, might be out next year,
00:18:28.720 --> 00:18:28.820
maybe?
00:18:29.980 --> 00:18:33.280
So I just submitted it for consideration.
00:18:33.920 --> 00:18:37.200
So hopefully in the next couple months,
00:18:37.380 --> 00:18:39.960
the steering council will make a decision on it.
00:18:40.120 --> 00:18:41.400
But you also have,
00:18:41.800 --> 00:18:43.480
and this one is accepted,
00:18:43.920 --> 00:18:45.040
is this is a big deal,
00:18:45.460 --> 00:18:46.560
PEP783,
00:18:46.820 --> 00:18:47.940
the Emscripten
00:18:48.200 --> 00:18:48.540
packaging.
00:18:48.780 --> 00:18:52.000
I think packaging is having a big moment in the Python space.
00:18:52.220 --> 00:18:54.580
We just have the very first packaging council,
00:18:55.100 --> 00:18:55.200
right?
00:18:55.280 --> 00:18:56.280
That election that came out.
00:18:56.280 --> 00:19:01.300
And you talked about Jay doing a bunch of work to get the build of the packages other
00:19:01.520 --> 00:19:01.660
places.
00:19:02.040 --> 00:19:06.940
I'm very excited about the packaging council because what they had before was not that functional.
00:19:08.500 --> 00:19:11.980
Whereas the people on the packaging steering council, I think they're going to do a really good job.
00:19:12.420 --> 00:19:12.480
Yeah,
00:19:12.660 --> 00:19:12.860
yeah, yeah.
00:19:12.980 --> 00:19:13.480
One of the great people.
00:19:13.900 --> 00:19:15.900
Jay, what are your thoughts on this whole packaging story?
00:19:16.080 --> 00:19:17.640
It sounds like you did some work on it as well.
00:19:17.960 --> 00:19:23.940
Yeah, there's a long history about supporting packages in Pyodide and Python in the browser.
00:19:24.320 --> 00:19:26.240
And that 7.83,
00:19:26.460 --> 00:19:31.200
7.83 unscrupulous packaging is really a lifesaver for us.
00:19:31.460 --> 00:19:34.400
Because so from the beginning of the Pyodide,
00:19:34.530 --> 00:19:38.980
we wanted to support packages like NumPy or SciPy or MatBotlib,
00:19:39.140 --> 00:19:41.160
all those scientific Python packages
00:19:41.330 --> 00:19:43.780
that needs to be cross-compiled to WebAssembly
00:19:43.850 --> 00:19:46.160
because they have C codes.
00:19:46.160 --> 00:19:49.660
So if the package only contains the Python code,
00:19:49.780 --> 00:19:52.440
we can just run it because there's nothing needs to compile.
00:19:52.640 --> 00:19:53.360
They're all interpreted.
00:19:53.550 --> 00:19:57.660
But if the package has a C or C++ or Rust code inside,
00:19:58.120 --> 00:20:00.740
they need to be compiled into a platform,
00:20:01.160 --> 00:20:03.400
which is for us WebAssembly or MScripten.
00:20:03.800 --> 00:20:07.580
So at the beginning and until 2025,
00:20:08.160 --> 00:20:12.080
we had to cross-compile and build all the packages
00:20:12.460 --> 00:20:15.380
in Pyodide CI to run them inside Pyodide.
00:20:15.420 --> 00:20:19.539
And I think last year we had around 300 packages
00:20:20.200 --> 00:20:22.820
that needs to be built in our repository.
00:20:22.980 --> 00:20:24.980
And it took like three or four hours
00:20:25.120 --> 00:20:27.420
to build all those packages in our CI.
00:20:27.680 --> 00:20:32.560
So even if you like make a little like one line change in Pyodide
00:20:32.570 --> 00:20:35.680
that needs to run CI for like three and four hours to build.
00:20:35.920 --> 00:20:38.080
And it was very flacky because,
00:20:38.540 --> 00:20:38.660
well,
00:20:38.880 --> 00:20:39.000
you know,
00:20:39.130 --> 00:20:44.180
Python packaging system is running some like Python codes in real time
00:20:44.680 --> 00:20:46.040
and it's very fragile.
00:20:46.600 --> 00:20:48.320
So like CI was always breaking.
00:20:48.770 --> 00:20:55.340
So we really hope to make things done in package themselves.
00:20:55.900 --> 00:20:58.820
We don't want it to maintain all the packages ourselves.
00:20:59.020 --> 00:20:59.680
So we want,
00:20:59.920 --> 00:21:00.320
for instance,
00:21:00.560 --> 00:21:05.360
NumPy to build Pyodide wheels themselves and SciPy too.
00:21:05.880 --> 00:21:09.980
And so that was that PAP 783.
00:21:10.360 --> 00:21:17.860
And we had one more years of discussions to make it accepted thanks to a lot of work by Hood.
00:21:18.080 --> 00:21:24.659
And we also standardized a lot of our build system so that people can actually easily build their packages
00:21:26.080 --> 00:21:27.920
into a PyPI scripting platform
00:21:28.300 --> 00:21:31.180
without setting up a lot of things in their machine.
00:21:31.600 --> 00:21:33.780
They can actually just use a cibuildwheel
00:21:34.100 --> 00:21:35.840
to build PyMD builds in their CI.
00:21:36.140 --> 00:21:38.880
They just need to add one PyMD platform and that's it.
00:21:38.930 --> 00:21:42.160
They can build PyMDs and builds in their CI.
00:21:42.690 --> 00:21:43.800
And that makes such a big difference,
00:21:44.160 --> 00:21:44.260
right?
00:21:44.400 --> 00:21:47.260
Because if you all were trying to take everyone else's projects
00:21:47.390 --> 00:21:48.960
and build it, I can't even imagine.
00:21:49.310 --> 00:21:50.780
I mean, it's one thing that's pure Python,
00:21:51.220 --> 00:21:53.219
but if it's C or Rust
00:21:53.540 --> 00:21:55.580
and it doesn't compile to WebAssembly correctly,
00:21:55.680 --> 00:21:56.560
what do you do, you know?
00:21:57.020 --> 00:22:00.280
Right, well, we have this horrifying compiler wrapper
00:22:00.480 --> 00:22:02.100
that rewrites the compiler arguments
00:22:02.300 --> 00:22:03.400
to fix all the problems.
00:22:03.980 --> 00:22:05.280
Right, we still have that.
00:22:05.940 --> 00:22:07.480
We still have it, it's not going anywhere.
00:22:07.960 --> 00:22:09.320
Cross compiling is still not easy,
00:22:09.480 --> 00:22:12.540
but it's all abstracted inside our build system.
00:22:12.660 --> 00:22:14.280
I mean, people will still face some issues,
00:22:14.860 --> 00:22:16.860
but like most of the packages now just build,
00:22:17.200 --> 00:22:17.720
which is awesome.
00:22:18.000 --> 00:22:20.399
Yeah, this is one concern I have
00:22:21.080 --> 00:22:27.060
been going back and forth with Jay about is that there's still a lot of compiler regressions.
00:22:27.420 --> 00:22:27.480
So
00:22:27.540 --> 00:22:30.280
like when we were doing the Python 3.15 update,
00:22:31.480 --> 00:22:33.140
you know, and I was trying to get up to the most
00:22:33.280 --> 00:22:34.980
recent version of mscripten. And it was like,
00:22:35.260 --> 00:22:37.460
you know, I had to go up like 10 versions,
00:22:37.820 --> 00:22:38.180
10 releases,
00:22:38.480 --> 00:22:42.060
and almost every single one of them had like some weird regression in it.
00:22:42.720 --> 00:22:44.179
And that broke builds of
00:22:44.200 --> 00:22:44.700
some package.
00:22:45.360 --> 00:22:51.120
And so what's really still the big difficulty for us is that we need to make sure
00:22:51.120 --> 00:22:52.420
that we find these problems.
00:22:53.180 --> 00:22:56.800
And then I can put fixes for them into our compiler tool chain,
00:22:57.260 --> 00:22:58.820
our tooling that says like,
00:22:59.000 --> 00:22:59.220
oh,
00:22:59.800 --> 00:23:01.460
there's this weird bug in the compiler.
00:23:01.680 --> 00:23:04.040
But if we edit the compiler
00:23:04.280 --> 00:23:04.700
arguments,
00:23:04.980 --> 00:23:06.860
or we rewrite something a little bit,
00:23:07.020 --> 00:23:10.180
then it will go away and the users won't see it.
00:23:10.280 --> 00:23:11.960
or we can go up to the compiler and say,
00:23:12.030 --> 00:23:12.160
like,
00:23:12.360 --> 00:23:12.700
you know,
00:23:12.960 --> 00:23:13.200
hey,
00:23:13.380 --> 00:23:14.140
like, let's patch this.
00:23:14.410 --> 00:23:14.540
Or,
00:23:14.820 --> 00:23:16.580
you know, I mean, I'm a maintainer of Unscripted now,
00:23:16.690 --> 00:23:17.080
so I can,
00:23:17.780 --> 00:23:19.180
you know, help drive it
00:23:19.390 --> 00:23:20.780
into a non-buggy direction.
00:23:21.400 --> 00:23:25.620
But my concern is very much that we could specify
00:23:26.510 --> 00:23:28.560
an ABI and a platform
00:23:29.000 --> 00:23:31.220
and then not find out that it's broken
00:23:31.700 --> 00:23:34.560
until downstream package maintainers
00:23:34.700 --> 00:23:35.640
start trying to use it.
00:23:35.880 --> 00:23:39.199
And so that's the one sort of big issue
00:23:39.220 --> 00:23:40.520
that we need to figure out is like,
00:23:40.620 --> 00:23:43.160
how do we make sure that we have confidence
00:23:43.720 --> 00:23:44.760
in our platform?
00:23:45.180 --> 00:23:47.120
Which I think basically still means
00:23:47.140 --> 00:23:48.920
we have to carry builds for a bunch of packages
00:23:49.140 --> 00:23:50.800
just to make sure that we cover
00:23:51.220 --> 00:23:52.720
like all the different weird things
00:23:52.900 --> 00:23:54.160
that different packages rely on.
00:23:54.660 --> 00:23:57.860
Compilers have an amazing amount of surface area
00:23:58.240 --> 00:24:00.260
in terms of like what is expected
00:24:00.320 --> 00:24:01.320
for them to behave like.
00:24:01.460 --> 00:24:02.880
Dominic, were you going to jump in and say something?
00:24:03.860 --> 00:24:05.060
Yeah, I was just going to say that
00:24:05.220 --> 00:24:08.019
I think the main thing that this packaging PEP
00:24:08.040 --> 00:24:09.860
really brings is that it does actually
00:24:10.140 --> 00:24:10.320
enable
00:24:11.660 --> 00:24:13.700
packagers and maintainers of packages
00:24:13.940 --> 00:24:15.100
to actually build for
00:24:16.060 --> 00:24:17.600
WebAssembly and for Pyodide, right?
00:24:17.630 --> 00:24:18.800
And it's not really,
00:24:19.100 --> 00:24:19.720
like, it doesn't
00:24:19.730 --> 00:24:21.500
really scale for Pyodide to be
00:24:21.820 --> 00:24:22.680
doing all of that themselves.
00:24:24.120 --> 00:24:25.780
So this is, like, really powerful to
00:24:25.810 --> 00:24:27.300
help spread the
00:24:27.780 --> 00:24:29.480
load and help all these, you know,
00:24:29.650 --> 00:24:31.700
the long tail of packages work
00:24:31.800 --> 00:24:33.640
on Pyodide. So much. I had pulled
00:24:33.650 --> 00:24:35.600
up PyPI here, just as
00:24:35.650 --> 00:24:38.000
I was going to just bring it up. We're coming up
00:24:38.020 --> 00:24:44.480
million packages it doesn't make sense for you all try to bring this in into it yourself so if it's
00:24:44.540 --> 00:24:50.700
possible for whoever wants to be on mscripten and pyodide and so on to just do that by setting up
00:24:50.980 --> 00:24:54.800
ci build wheel and setting a wheel they're basically like it's awesome right yeah yeah
00:24:55.040 --> 00:25:00.600
off the cuff i think only about five percent of those packages have any uh c c plus plus or rust
00:25:00.660 --> 00:25:06.240
in them so uh luckily most of them are pure python and don't yeah that's trying to track what which
00:25:06.260 --> 00:25:13.160
packages have Python scripting wheels now. So there is a website called rwepap783yet,
00:25:13.320 --> 00:25:15.480
which is created by another Pyodag maintainer.
00:25:15.880 --> 00:25:19.440
And it's already a lot of packages have Python
00:25:19.560 --> 00:25:21.920
scripting wheels, and some of them we are still maintaining ourselves.
00:25:22.400 --> 00:25:23.120
But it's,
00:25:23.420 --> 00:25:23.780
yeah,
00:25:24.860 --> 00:25:29.820
like, majority of the Python applications will depend on those top 500 Python packages.
00:25:30.020 --> 00:25:30.220
So you're
00:25:30.320 --> 00:25:31.620
trying to support those packages.
00:25:32.340 --> 00:25:35.240
Yeah, so you can look through and see all the popular ones and go,
00:25:35.420 --> 00:25:35.440
Okay,
00:25:35.640 --> 00:25:36.960
yeah, this is great.
00:25:38.380 --> 00:25:41.920
The yellow ones are those packages that are not supported yet.
00:25:42.280 --> 00:25:47.040
And the green ones are those that have the fence wheels in PyPI.
00:25:47.360 --> 00:25:50.900
And the blue ones are those we are still building ourselves.
00:25:51.560 --> 00:25:51.960
Oh, interesting.
00:25:52.140 --> 00:25:52.820
That's what the blue means.
00:25:52.840 --> 00:25:52.960
Okay.
00:25:53.320 --> 00:25:57.600
And then some of them are just none for their wheel designation because they're pure Python.
00:25:58.020 --> 00:25:59.060
Setup tools is pure Python.
00:25:59.560 --> 00:25:59.820
Right.
00:26:00.760 --> 00:26:03.440
I guess it's probably worth pointing out that you all talked about this before,
00:26:03.800 --> 00:26:05.260
but just because something's pure Python
00:26:05.620 --> 00:26:08.200
doesn't mean that it's going to work on Pyodide, right?
00:26:08.480 --> 00:26:10.520
There's just parts that are missing
00:26:10.800 --> 00:26:12.460
because the runtime themselves are like,
00:26:12.820 --> 00:26:12.880
yeah,
00:26:13.040 --> 00:26:14.000
your OS thing, no.
00:26:14.440 --> 00:26:15.960
This comes from a browser or whatever,
00:26:16.200 --> 00:26:16.320
right?
00:26:16.540 --> 00:26:18.740
Or your raw socket support,
00:26:19.070 --> 00:26:19.740
I don't know about you.
00:26:20.080 --> 00:26:20.560
Yeah,
00:26:20.780 --> 00:26:20.960
right.
00:26:21.760 --> 00:26:24.700
If the package is depending on some native things
00:26:24.960 --> 00:26:28.500
like threadings or multi-processing or self-processing,
00:26:28.640 --> 00:26:31.600
and the native sockets will not basically work
00:26:31.720 --> 00:26:33.560
and browser Piodies.
00:26:33.900 --> 00:26:35.560
If you're running in Cloudflare Workers
00:26:35.900 --> 00:26:36.500
or Node.js,
00:26:36.900 --> 00:26:37.580
they will
00:26:37.860 --> 00:26:39.580
work because Node.js have access
00:26:39.780 --> 00:26:41.540
to some of them and still
00:26:42.040 --> 00:26:43.640
threadings or sub-processes are not
00:26:43.880 --> 00:26:44.000
working,
00:26:44.240 --> 00:26:45.640
but some of them will work
00:26:45.860 --> 00:26:47.480
depending on the platform you're running in Piodies.
00:26:47.820 --> 00:26:48.720
Does async.io work?
00:26:50.360 --> 00:26:51.720
That was a
00:26:51.760 --> 00:26:53.460
big project when I first started maintaining
00:26:53.660 --> 00:26:55.560
Piodies was to make async.io work
00:26:55.880 --> 00:26:57.560
because everything in a
00:26:57.680 --> 00:26:58.460
browser is async.
00:26:58.940 --> 00:27:02.520
So when there wasn't a good asyncio story for Pyodide,
00:27:02.570 --> 00:27:04.100
it was like really rough to use it
00:27:04.190 --> 00:27:05.720
because you had to just like.then,
00:27:05.880 --> 00:27:06.520
.then, you know.
00:27:06.800 --> 00:27:08.300
Yeah, callback, callback, callback,
00:27:08.460 --> 00:27:08.520
right?
00:27:09.420 --> 00:27:11.060
And, you know, at least in JavaScript,
00:27:11.320 --> 00:27:12.640
a lambda can have like,
00:27:12.820 --> 00:27:14.040
you know, a multi-line body.
00:27:14.390 --> 00:27:16.460
And so like lambdas are not that bad in JavaScript,
00:27:16.630 --> 00:27:17.160
whereas in Python,
00:27:17.430 --> 00:27:18.360
like lambdas suck.
00:27:18.560 --> 00:27:19.680
So you have to do like death,
00:27:19.850 --> 00:27:20.280
like a thing,
00:27:20.330 --> 00:27:21.500
and then put it, it's like.
00:27:21.720 --> 00:27:24.720
I wonder if Python should have had multi-line lambdas.
00:27:25.120 --> 00:27:26.900
I do kind of like them for.
00:27:27.130 --> 00:27:28.380
I think it should have actually been.
00:27:28.800 --> 00:27:30.520
and then it kind of went to line land.
00:27:31.559 --> 00:27:32.800
I think curly braces are
00:27:33.140 --> 00:27:33.540
the way.
00:27:35.179 --> 00:27:37.240
Oh, you're going to cause a fight.
00:27:37.340 --> 00:27:38.400
The developers would disagree with that.
00:27:40.340 --> 00:27:41.220
If I have curly braces,
00:27:41.300 --> 00:27:42.640
I can have multi-line lambdas
00:27:42.880 --> 00:27:43.660
that I care way more about.
00:27:44.420 --> 00:27:46.420
You can have multi-line lambdas without
00:27:46.900 --> 00:27:47.820
curly braces as well.
00:27:48.140 --> 00:27:49.720
But no one's ever figured out the syntax.
00:27:49.940 --> 00:27:50.800
That's why it doesn't exist.
00:27:51.420 --> 00:27:52.160
They have,
00:27:52.400 --> 00:27:53.580
actually. There are languages that do it.
00:27:54.460 --> 00:27:54.860
Backslash.
00:27:55.480 --> 00:27:56.280
Backslashes, come on.
00:27:56.860 --> 00:27:59.740
It has to fit with the existing syntax of Python.
00:28:00.580 --> 00:28:01.860
So if you designed a new language,
00:28:02.280 --> 00:28:03.540
you could maybe make it work.
00:28:03.980 --> 00:28:05.320
I don't think we're going to be able to
00:28:06.220 --> 00:28:08.860
completely solve this curly braces are not problem.
00:28:09.440 --> 00:28:12.140
But Hood, I expected parentheses from you
00:28:12.360 --> 00:28:13.140
as a Lisp person,
00:28:13.320 --> 00:28:13.660
just parentheses,
00:28:13.900 --> 00:28:14.080
parentheses,
00:28:14.320 --> 00:28:14.540
parentheses,
00:28:14.740 --> 00:28:14.840
parentheses.
00:28:14.920 --> 00:28:16.120
I'm looking with parentheses too.
00:28:17.080 --> 00:28:17.500
I don't object.
00:28:18.840 --> 00:28:20.300
Lisp also can have multi-line lab.
00:28:21.180 --> 00:28:22.860
I can't do all the parentheses in Lisp.
00:28:23.160 --> 00:28:24.160
It's not going to work for me.
00:28:24.400 --> 00:28:25.400
What if you had new syntax?
00:28:26.620 --> 00:28:29.020
I do think there's interesting new syntax that can be added.
00:28:29.700 --> 00:28:33.680
We've got the no coalescing or non coalescing operators
00:28:34.100 --> 00:28:36.500
and that kind of stuff possibly coming to Python.
00:28:37.260 --> 00:28:39.260
There will be things, but I don't think multi-line lambdas
00:28:39.260 --> 00:28:39.980
are going to be one of them.
00:28:40.280 --> 00:28:42.060
All right, let's talk about,
00:28:42.500 --> 00:28:43.660
we talked about a little bit,
00:28:43.660 --> 00:28:44.900
but let's go ahead and just talk a bit about
00:28:45.740 --> 00:28:47.160
edge workers in general.
00:28:47.480 --> 00:28:50.660
Because we talked about you've got over 300 points of presence.
00:28:50.880 --> 00:28:51.800
They're all near the users.
00:28:52.040 --> 00:28:53.240
That totally makes sense.
00:28:53.640 --> 00:28:57.500
but maybe compare and contrast this with like running on a VIP,
00:28:57.720 --> 00:29:01.660
just a virtual server or in Kubernetes or even serverless.
00:29:01.860 --> 00:29:03.980
Because to me, it feels kind of serverless-like,
00:29:04.240 --> 00:29:04.600
but not.
00:29:04.880 --> 00:29:05.900
I mean, it is serverless,
00:29:06.080 --> 00:29:06.600
I would say.
00:29:06.880 --> 00:29:07.820
What makes you think it's not?
00:29:08.120 --> 00:29:09.940
Well, a traditional serverless, I guess.
00:29:10.140 --> 00:29:11.480
You're right, it is serverless.
00:29:11.560 --> 00:29:14.460
I'm thinking like AWS Lambda and that kind of.
00:29:14.780 --> 00:29:15.040
Yeah.
00:29:15.320 --> 00:29:18.840
So in my mind, AWS Lambda runs in a data center.
00:29:19.060 --> 00:29:24.240
Like my Lambdas are set to run in US East 1 or in Frankfurt or something like that.
00:29:24.400 --> 00:29:25.640
And in that way, it's not the same.
00:29:25.880 --> 00:29:30.720
I feel like these words like edge and serverless and cloud are all more like marketing terms
00:29:31.000 --> 00:29:31.960
than like technical terms.
00:29:32.200 --> 00:29:34.720
And so that leaves some vagueness about what exactly they mean.
00:29:35.100 --> 00:29:36.740
Yeah, I would actually consider,
00:29:37.540 --> 00:29:41.920
I mean, workers in general to be more serverless than AWS Lambda.
00:29:42.260 --> 00:29:42.740
I mean...
00:29:42.960 --> 00:29:43.300
I do too.
00:29:43.620 --> 00:29:43.940
I do too.
00:29:44.160 --> 00:29:44.320
Yeah.
00:29:44.700 --> 00:29:49.520
Just because you don't have to worry about where you're placing your workers.
00:29:50.230 --> 00:29:52.540
They just show up wherever your users are, which is great.
00:29:52.760 --> 00:29:55.600
I think they're more serverless than Lambda as well.
00:29:55.740 --> 00:30:00.700
The only thing is that Lambda claimed the term serverless before,
00:30:01.320 --> 00:30:01.460
right?
00:30:01.510 --> 00:30:04.160
And so I think it's worth a little bit of a compare and contrast.
00:30:04.870 --> 00:30:06.940
So I'm a user I've written,
00:30:07.190 --> 00:30:09.880
or I'm a user I'm consuming in API,
00:30:10.190 --> 00:30:10.540
open up,
00:30:10.760 --> 00:30:11.060
I don't know,
00:30:11.220 --> 00:30:12.280
React front-end app,
00:30:12.560 --> 00:30:16.180
and it says, I need to do my work. I want to do it close to you.
00:30:16.360 --> 00:30:16.480
So
00:30:16.960 --> 00:30:19.900
what happens next? How do these things work? Well,
00:30:20.400 --> 00:30:22.280
you connect to your nearest point of presence.
00:30:22.920 --> 00:30:26.100
That nearest point of presence has the worker's runtime running on it.
00:30:26.520 --> 00:30:27.980
That worker's runtime has
00:30:28.220 --> 00:30:28.760
v8 on it,
00:30:29.100 --> 00:30:32.620
and v8 runs Pyodide in WebAssembly.
00:30:32.860 --> 00:30:33.060
Yeah.
00:30:33.480 --> 00:30:34.360
But as a developer,
00:30:34.530 --> 00:30:35.280
I don't make that
00:30:35.420 --> 00:30:35.560
choice,
00:30:35.820 --> 00:30:38.620
right? It's like a dynamic DNS choice that says,
00:30:38.800 --> 00:30:40.140
I know you asked for,
00:30:40.450 --> 00:30:40.860
I don't know,
00:30:41.200 --> 00:30:43.220
worker.collectifair.com slash whatever,
00:30:43.440 --> 00:30:48.100
but you actually get Southeast Asia in this location.
00:30:48.640 --> 00:30:50.500
And that's just kind of the magic of CDNs, right?
00:30:50.880 --> 00:30:51.000
Yeah.
00:30:51.300 --> 00:30:51.780
Okay.
00:30:52.300 --> 00:30:54.220
So let's talk this back up.
00:30:54.420 --> 00:30:57.980
I always describe this as being like a CDN,
00:30:58.140 --> 00:30:59.580
except for instead of with static assets,
00:30:59.840 --> 00:31:03.480
it distributes programs and then runs the programs on your data.
00:31:03.840 --> 00:31:04.020
Yeah.
00:31:04.520 --> 00:31:04.840
Okay.
00:31:04.940 --> 00:31:06.740
So let's talk about a deployment.
00:31:07.080 --> 00:31:08.880
Do I deploy my Python files?
00:31:09.200 --> 00:31:13.040
Do I do a local build and get a WebAssembly thing that I upload to you?
00:31:13.300 --> 00:31:13.760
How does that work?
00:31:14.260 --> 00:31:16.340
You don't build any WebAssembly things yourself.
00:31:16.660 --> 00:31:19.420
Like all the WebAssembly things are already pre-built.
00:31:19.920 --> 00:31:23.840
So the deploying Python workers is basically you write some Python codes.
00:31:24.100 --> 00:31:26.900
And you need to, if you're using some Python packages as dependencies,
00:31:27.240 --> 00:31:29.100
you need to install them through uv.
00:31:29.380 --> 00:31:33.840
So uv has a support for like installing Python packages
00:31:33.900 --> 00:31:36.120
that are built for WebAssembly into your local files.
00:31:36.260 --> 00:31:38.500
Of course, you cannot run it inside your local machine.
00:31:38.760 --> 00:31:41.820
like you'll only have like a native Python interpreter,
00:31:42.030 --> 00:31:43.420
or you can use Pyodite to run it.
00:31:44.240 --> 00:31:44.760
So basically,
00:31:45.150 --> 00:31:46.980
we like compress all those,
00:31:47.340 --> 00:31:49.140
your Python applications and packages
00:31:49.530 --> 00:31:51.500
into a Cloudflare web server,
00:31:51.670 --> 00:31:52.980
and it's distributed around the world.
00:31:53.540 --> 00:31:56.160
And the Cloudflare runtime will like download the application
00:31:56.510 --> 00:31:58.780
and run it inside Pyodite and Cloudflare runtime.
00:31:59.180 --> 00:31:59.780
Yeah, awesome.
00:32:00.240 --> 00:32:01.320
What's the local dev story?
00:32:01.370 --> 00:32:02.840
Now, I hadn't really thought about that before,
00:32:03.080 --> 00:32:05.320
but I want to debug it, play with it.
00:32:05.640 --> 00:32:05.860
Yeah,
00:32:06.020 --> 00:32:06.140
so...
00:32:06.160 --> 00:32:07.120
I push it up to...
00:32:07.120 --> 00:32:07.440
Yeah, go ahead.
00:32:07.740 --> 00:32:08.180
Go ahead, Dominic.
00:32:08.800 --> 00:32:09.800
Yeah, so I mean,
00:32:10.200 --> 00:32:14.480
part of the worker's runtime is open source as worker D,
00:32:14.910 --> 00:32:15.720
if you want to look it up,
00:32:15.900 --> 00:32:16.280
it's on GitHub.
00:32:17.550 --> 00:32:19.580
And you basically run that locally.
00:32:19.980 --> 00:32:25.920
I mean, we have like a CLI that wraps it for you. So it's nice and easy called Wrangler.
00:32:26.670 --> 00:32:28.720
But we're moving to CF now as well.
00:32:29.440 --> 00:32:30.240
But basically,
00:32:31.140 --> 00:32:32.740
you just you just run it locally,
00:32:32.980 --> 00:32:35.720
you you edit the files of your worker,
00:32:36.300 --> 00:32:37.380
they get reloaded automatically.
00:32:38.840 --> 00:32:39.840
as you edit them,
00:32:40.090 --> 00:32:41.980
you just send requests locally and see what happens.
00:32:42.500 --> 00:32:42.680
Okay.
00:32:42.880 --> 00:32:43.180
Yeah,
00:32:43.360 --> 00:32:46.940
I'll be sure to link to the WorkerD project so people can download and install it.
00:32:46.940 --> 00:32:48.280
I'm sure it's in your quick start, though, right?
00:32:48.580 --> 00:32:48.640
Yeah.
00:32:48.940 --> 00:32:54.380
I think the very cool part of the Cloud for Worker's runtime platform is that the WorkerD is open source.
00:32:54.590 --> 00:32:59.920
So basically, you can run the same code in the same runtime in your local machine and the prods.
00:33:00.090 --> 00:33:02.660
You can test everything that happens in prod in your local machine.
00:33:03.040 --> 00:33:03.260
Interesting.
00:33:03.540 --> 00:33:07.100
So this really is what runs on the edge when stuff happens,
00:33:07.380 --> 00:33:08.480
but you can just run it locally as well.
00:33:08.750 --> 00:33:09.120
Yeah, exactly.
00:33:09.760 --> 00:33:10.980
Yeah, I mean, that's pretty unique,
00:33:11.240 --> 00:33:11.340
right?
00:33:11.440 --> 00:33:13.020
Because if I was doing Lambda
00:33:13.480 --> 00:33:16.160
or I was doing EKS or something like that,
00:33:16.580 --> 00:33:17.580
it's not the same.
00:33:17.860 --> 00:33:19.540
I can install a Kubernetes cluster
00:33:19.920 --> 00:33:20.900
and run pods and stuff,
00:33:21.000 --> 00:33:22.360
but that's not the same as running
00:33:22.600 --> 00:33:24.740
in Amazon's Kubernetes service.
00:33:25.260 --> 00:33:27.040
And this sounds like it kind of is,
00:33:27.180 --> 00:33:27.960
which is pretty interesting.
00:33:28.300 --> 00:33:29.960
So let's talk about the platform a bit
00:33:30.140 --> 00:33:30.460
because this,
00:33:30.700 --> 00:33:33.180
I was a little bit unsure of,
00:33:33.400 --> 00:33:34.860
or just don't have a ton of experience.
00:33:35.280 --> 00:33:36.920
So it's one thing to run Python,
00:33:37.000 --> 00:33:39.660
on a point of presence and point sort of thing.
00:33:40.020 --> 00:33:40.780
But databases,
00:33:41.320 --> 00:33:43.460
is the database got a little bit my data?
00:33:43.600 --> 00:33:45.660
You know, I connect halfway around the world to Postgres
00:33:45.790 --> 00:33:48.240
and is that maybe not as good?
00:33:48.670 --> 00:33:50.540
So there's a bunch of interesting things as well.
00:33:50.860 --> 00:33:54.880
And so you all like numbering for your D1,
00:33:55.100 --> 00:33:55.800
R2 and so on.
00:33:56.140 --> 00:33:59.680
But I have this crazy fascination with SQLite right now.
00:33:59.730 --> 00:34:02.260
So this is especially interesting to me.
00:34:03.000 --> 00:34:04.719
So let's talk about some of these building blocks
00:34:04.720 --> 00:34:07.700
that not just Python workers use, but all of them.
00:34:07.780 --> 00:34:08.659
But at the same time,
00:34:08.860 --> 00:34:10.340
they're here for the Python workers now.
00:34:10.540 --> 00:34:11.659
And so that's pretty interesting.
00:34:12.020 --> 00:34:14.179
Who wants to introduce D1 to the world?
00:34:14.820 --> 00:34:15.100
Dominic.
00:34:16.220 --> 00:34:16.419
Sure.
00:34:16.760 --> 00:34:19.480
I mean, I can give it a shot.
00:34:20.520 --> 00:34:23.320
So I personally love SQLite.
00:34:23.659 --> 00:34:28.100
And I've actually been writing web apps using it,
00:34:28.419 --> 00:34:30.460
just even before running on workers,
00:34:31.020 --> 00:34:32.220
because it's so versatile.
00:34:32.720 --> 00:34:33.580
It's so easy to set up.
00:34:33.780 --> 00:34:40.440
You just load the library and save the database on your local file system.
00:34:41.000 --> 00:34:43.379
And I think this is basically an extension of that.
00:34:43.620 --> 00:34:43.919
I mean,
00:34:44.320 --> 00:34:48.899
you just get a local to your worker SQLite database.
00:34:49.560 --> 00:34:50.440
You can write to it.
00:34:50.840 --> 00:34:53.100
It gets replicated across the world for you.
00:34:53.720 --> 00:34:54.200
So,
00:34:55.020 --> 00:34:56.980
you know, and it scales with your workers as well.
00:34:56.980 --> 00:34:58.360
You don't have to worry about that at all.
00:34:58.500 --> 00:35:03.080
It's pretty wild because you've got like 300 database nodes, which is pretty incredible.
00:35:03.540 --> 00:35:06.500
And for people who don't know, they might think of SQLite as a toy.
00:35:06.530 --> 00:35:08.920
It is extremely fast as a database.
00:35:10.140 --> 00:35:11.600
So it's pretty interesting,
00:35:11.760 --> 00:35:11.940
I think.
00:35:12.260 --> 00:35:18.680
Now, the one thing that seems tricky is somebody in Southeast Asia and somebody in London writes
00:35:18.990 --> 00:35:20.460
to the database at the same time.
00:35:20.780 --> 00:35:21.240
Now what?
00:35:22.880 --> 00:35:25.540
Yeah, to be honest, I don't know the details of how that works.
00:35:25.880 --> 00:35:32.479
But I think there is some mechanisms to make sure that it's all consistent and you can
00:35:32.500 --> 00:35:34.920
make sure there's no conflicts there. Yeah. Yeah. Yeah.
00:35:35.210 --> 00:35:38.700
So something I've been looking at lately is
00:35:39.020 --> 00:35:40.820
Lightstream actually been setting this up.
00:35:41.100 --> 00:35:42.700
So Lightstream is really interesting because it
00:35:42.960 --> 00:35:48.560
works on SQLite and you set up the write ahead log, the wall in SQLite, it will basically
00:35:49.180 --> 00:35:55.540
synchronize and stream that write ahead log off to somewhere else for backup and replication and so
00:35:55.620 --> 00:35:56.500
on. So I'm wondering,
00:35:56.930 --> 00:35:59.959
my first thought is probably they're doing something with the write ahead log
00:36:00.240 --> 00:36:00.860
and then merging,
00:36:01.100 --> 00:36:01.380
you know,
00:36:01.920 --> 00:36:02.620
synchronizing that
00:36:02.800 --> 00:36:03.240
and then merging,
00:36:03.500 --> 00:36:05.060
combining it or something like that.
00:36:05.140 --> 00:36:05.900
I'm not totally sure,
00:36:06.080 --> 00:36:07.100
but this is my theory.
00:36:07.340 --> 00:36:10.140
One of the great things about the design of Python workers
00:36:10.360 --> 00:36:11.660
is that we just consume these things.
00:36:11.800 --> 00:36:12.800
We don't need to know how they work.
00:36:13.260 --> 00:36:13.680
Yeah, exactly.
00:36:14.060 --> 00:36:14.460
It's awesome.
00:36:15.240 --> 00:36:16.180
All right, we got a couple more.
00:36:16.320 --> 00:36:16.680
Hyperdrive.
00:36:16.920 --> 00:36:19.500
So D1 is kind of SQLite Hyperdrive.
00:36:19.760 --> 00:36:21.580
And this, I think, is new as part of your launch,
00:36:21.760 --> 00:36:21.860
right?
00:36:22.120 --> 00:36:24.080
This is kind of like distributed Postgres,
00:36:24.400 --> 00:36:25.440
but that wasn't available before.
00:36:25.960 --> 00:36:26.520
I don't know exactly,
00:36:26.920 --> 00:36:27.020
right?
00:36:27.320 --> 00:36:27.700
Something like this?
00:36:28.040 --> 00:36:30.080
Yeah, I think a hyperdrive is relatively new.
00:36:30.440 --> 00:36:30.800
And,
00:36:31.360 --> 00:36:34.180
and it's kind, I think it's kind of the proxy,
00:36:35.070 --> 00:36:38.460
I think I can explain as a kind of proxy that there's like a truth of source,
00:36:39.099 --> 00:36:41.020
related database like PostgreSQL,
00:36:41.320 --> 00:36:41.520
MySQL,
00:36:41.700 --> 00:36:45.460
Summary, and the Summary. And we have a lot of like
00:36:45.760 --> 00:36:50.880
proxies in the edge that can basically like make your database connections a lot more faster,
00:36:51.340 --> 00:36:56.459
like each there's like 350 hyperdrives that like maintains the connection pool with the original
00:36:56.480 --> 00:36:56.780
database,
00:36:57.300 --> 00:36:59.240
like making the read and write a lot faster.
00:36:59.640 --> 00:36:59.760
Right,
00:36:59.940 --> 00:37:00.040
right.
00:37:00.080 --> 00:37:02.140
You can turn on caching to say,
00:37:02.320 --> 00:37:04.120
you know, this table doesn't change very often.
00:37:04.420 --> 00:37:07.560
So if you've read that table over here, then just,
00:37:08.000 --> 00:37:08.220
you know,
00:37:08.460 --> 00:37:09.700
answer questions from it,
00:37:09.740 --> 00:37:10.180
something like that.
00:37:10.220 --> 00:37:10.460
It's awesome.
00:37:10.780 --> 00:37:12.380
Yeah, I would just add to that.
00:37:13.480 --> 00:37:18.100
It's worth noting that we talked a little bit about sockets before and socket support
00:37:18.360 --> 00:37:19.880
in Piodide.
00:37:20.400 --> 00:37:21.860
And that is actually what I think,
00:37:22.040 --> 00:37:22.160
Jay,
00:37:22.320 --> 00:37:23.140
you've been working on, right?
00:37:23.420 --> 00:37:27.360
making sockets work on workers for Python.
00:37:27.770 --> 00:37:29.340
And that is what makes Hyperdrive work.
00:37:30.240 --> 00:37:32.880
Hyperdrive is built on these TCP sockets.
00:37:33.790 --> 00:37:34.860
So without that, it wouldn't work.
00:37:35.180 --> 00:37:35.360
Yeah,
00:37:35.560 --> 00:37:35.880
exactly.
00:37:36.220 --> 00:37:36.360
Exactly.
00:37:36.510 --> 00:37:40.140
So supporting Hyperdrive in Cloudflare Python workers
00:37:40.310 --> 00:37:43.520
and in Pyrodite was one of the main goals for us
00:37:43.820 --> 00:37:45.840
before launching it at GA.
00:37:47.280 --> 00:37:49.540
And Pyrodite did not have socket support
00:37:49.710 --> 00:37:51.240
because browsers never had that.
00:37:51.380 --> 00:37:54.200
But to use the relational databases,
00:37:54.530 --> 00:37:58.180
you definitely need TCP connections and sockets.
00:37:58.720 --> 00:38:04.540
So we wired up the Node.js socket APIs inside Pyodide.
00:38:05.410 --> 00:38:06.260
So workers'
00:38:06.480 --> 00:38:08.420
runtime support Node.js socket APIs.
00:38:08.860 --> 00:38:11.300
So they are actually wired up inside Pyodide.
00:38:11.310 --> 00:38:17.260
So that by calling socket syscalls inside Pyodide actually calls a Node.js socket calls.
00:38:17.570 --> 00:38:18.940
So that's how AverageRM works.
00:38:18.960 --> 00:38:24.600
This is really crazy because the socket APIs in Node, of course, are all asynchronous,
00:38:25.150 --> 00:38:30.280
but most of the socket system calls that you have in Linux are synchronous calls.
00:38:30.780 --> 00:38:37.220
And so in order to handle the system call,
00:38:37.480 --> 00:38:51.280
the system call has to stack switch and let the JavaScript event loop turn so that it can get the IO completed and then it unstacks switches and returns to the...
00:38:51.460 --> 00:38:52.100
Yeah, that's wild.
00:38:52.740 --> 00:38:54.240
So this is all transparent to C code.
00:38:54.380 --> 00:39:00.400
So if you have a C application that consumes libc APIs to handle sockets,
00:39:00.580 --> 00:39:01.340
it just works.
00:39:01.660 --> 00:39:01.780
Yeah,
00:39:01.960 --> 00:39:10.960
I was kind of wondering if somehow you could unify the event loop of Node and the event loop of asyncio and kind of make them all one thing.
00:39:11.300 --> 00:39:12.240
So that's what we've done.
00:39:12.360 --> 00:39:14.940
So we have our event loop in Python,
00:39:15.940 --> 00:39:18.080
which we use for PyTag, which we call WebLoop.
00:39:18.360 --> 00:39:21.060
And it basically just subscribes to the browser event.
00:39:21.300 --> 00:39:24.440
And this is essentially necessary for two reasons.
00:39:24.600 --> 00:39:28.720
One is that all actual IO happen on the browser loop.
00:39:28.780 --> 00:39:30.060
Like there is really no way,
00:39:30.200 --> 00:39:33.140
like if you can make your own like separate loop,
00:39:33.600 --> 00:39:35.460
but like it can't do IO.
00:39:36.320 --> 00:39:38.120
And while it's spinning the real IO,
00:39:38.600 --> 00:39:40.000
it's blocking the real event loop,
00:39:40.040 --> 00:39:41.120
which can't do the real IO.
00:39:42.140 --> 00:39:42.320
Yeah.
00:39:42.640 --> 00:39:44.120
And I said there were going to be two reasons,
00:39:45.220 --> 00:39:47.100
but I feel like that was both reasons.
00:39:47.960 --> 00:39:48.440
Well,
00:39:49.180 --> 00:39:50.380
it sounds like an important one.
00:39:50.580 --> 00:39:50.680
Okay.
00:39:50.960 --> 00:39:52.860
So we also have R2,
00:39:53.520 --> 00:39:55.440
which is like S3-ish.
00:39:56.000 --> 00:39:56.480
Exactly.
00:39:57.860 --> 00:39:59.020
How is it different,
00:39:59.260 --> 00:39:59.320
though?
00:39:59.660 --> 00:40:01.840
Well, I think it's like almost the same.
00:40:02.080 --> 00:40:04.240
The name R2 actually comes from S3.
00:40:04.580 --> 00:40:08.540
It's like a 1 minus S minus 1 and 3 minus 1.
00:40:08.540 --> 00:40:08.640
I see.
00:40:08.860 --> 00:40:10.920
Yeah, so RS and then 3, 2.
00:40:10.920 --> 00:40:11.200
It's exactly the same.
00:40:11.600 --> 00:40:14.820
I think the main thing with it is that there's no egress fees.
00:40:16.100 --> 00:40:17.060
So it's cheaper.
00:40:17.460 --> 00:40:18.160
No egress fees.
00:40:18.280 --> 00:40:19.080
Okay, very interesting.
00:40:19.460 --> 00:40:19.740
All right.
00:40:20.000 --> 00:40:20.760
And you can use this.
00:40:21.500 --> 00:40:22.060
Some of these things,
00:40:22.300 --> 00:40:23.920
I guess probably almost all of them,
00:40:23.920 --> 00:40:27.140
you can use regardless of whether you're using Cloudflare workers or not.
00:40:27.320 --> 00:40:30.600
I could use R2 just because I want object storage.
00:40:31.080 --> 00:40:31.280
Interesting.
00:40:31.800 --> 00:40:32.820
I'm about to think more about that.
00:40:33.400 --> 00:40:33.980
It's giving me ideas.
00:40:34.180 --> 00:40:34.280
Okay.
00:40:35.000 --> 00:40:37.120
And you've got queues, Cloudflare queues,
00:40:37.640 --> 00:40:38.800
and AI inference.
00:40:39.440 --> 00:40:40.440
So these are all the...
00:40:40.520 --> 00:40:43.480
I kind of wanted to go through these because these are the building blocks
00:40:43.580 --> 00:40:47.380
or the platform pieces that are available to these new Python workers,
00:40:47.580 --> 00:40:47.700
right?
00:40:47.960 --> 00:40:49.800
Yeah, you have a lot of building blocks.
00:40:50.760 --> 00:40:51.560
inside Cloudflow.
00:40:51.800 --> 00:40:53.860
Developer platform, we keep adding it every month.
00:40:54.020 --> 00:40:55.240
So I'm not,
00:40:55.480 --> 00:40:55.840
to be honest,
00:40:56.060 --> 00:40:57.620
not following all those releases,
00:40:58.060 --> 00:41:00.760
but queues and AI and their workflows,
00:41:01.620 --> 00:41:02.100
things like that.
00:41:02.200 --> 00:41:04.080
But you can easily connect your workers
00:41:04.360 --> 00:41:06.440
with those new features
00:41:07.040 --> 00:41:08.960
and to build a full stack application.
00:41:09.140 --> 00:41:10.520
If you need a queue, you can use queue.
00:41:10.680 --> 00:41:13.000
If you want to run AI inference into Edge,
00:41:13.020 --> 00:41:14.020
you can use Worker's AI,
00:41:14.200 --> 00:41:15.500
which is awesome.
00:41:15.940 --> 00:41:16.440
Yeah, that's super,
00:41:16.640 --> 00:41:17.080
super neat.
00:41:17.520 --> 00:41:18.660
All right, let's go to the announcement.
00:41:18.920 --> 00:41:19.640
And here it is.
00:41:19.860 --> 00:41:20.660
September 21.
00:41:21.060 --> 00:41:22.840
Took us a little bit to actually press record,
00:41:23.220 --> 00:41:25.220
but it's been a few weeks, not too long though.
00:41:25.640 --> 00:41:27.120
This announcement by the three of you,
00:41:27.400 --> 00:41:29.960
Python web workers are now generally available.
00:41:30.720 --> 00:41:31.120
Hooray!
00:41:31.520 --> 00:41:31.820
That's awesome.
00:41:32.200 --> 00:41:37.100
How long had they been in beta style availability before that?
00:41:37.380 --> 00:41:39.080
Feels like since like spring of 2024.
00:41:39.980 --> 00:41:42.100
So I started in October of 2023
00:41:42.760 --> 00:41:45.320
and it took about six months to get a beta going
00:41:46.040 --> 00:41:47.960
and then it took like over two years
00:41:47.980 --> 00:41:50.000
to make it generally available.
00:41:50.640 --> 00:41:50.760
Wow.
00:41:51.070 --> 00:41:51.780
So what was that work?
00:41:52.020 --> 00:41:52.340
Like trying,
00:41:52.520 --> 00:41:53.180
for example,
00:41:53.610 --> 00:41:54.420
the IO loops
00:41:54.510 --> 00:41:55.060
and all the different,
00:41:55.500 --> 00:41:57.520
all the just the sockets that Jay worked on,
00:41:57.700 --> 00:41:59.220
all these things that you need in place.
00:41:59.740 --> 00:42:02.020
That's what like data science pyodied
00:42:02.160 --> 00:42:04.840
to full runtime pyodied work was.
00:42:05.140 --> 00:42:07.920
I think the packaging story was actually a big thing.
00:42:07.990 --> 00:42:08.320
I mean,
00:42:08.620 --> 00:42:09.180
when we started,
00:42:09.860 --> 00:42:10.000
we,
00:42:11.100 --> 00:42:12.820
so there was two parts to this.
00:42:13.220 --> 00:42:14.940
One was trying to make sure
00:42:15.070 --> 00:42:17.420
that the cold starts are as fast as possible
00:42:17.740 --> 00:42:19.400
and especially when we're using packages.
00:42:20.120 --> 00:42:21.220
And when we started,
00:42:21.660 --> 00:42:23.480
we figured we'll just allow people
00:42:23.520 --> 00:42:26.880
to use certain built-in packages that Pyodite provides.
00:42:28.020 --> 00:42:30.100
But we just realized that that isn't flexible enough
00:42:30.600 --> 00:42:32.020
and we just need to allow people to use
00:42:32.580 --> 00:42:33.560
whatever packages they want,
00:42:33.740 --> 00:42:33.920
ideally.
00:42:34.300 --> 00:42:37.220
So we basically switched away from that approach
00:42:37.880 --> 00:42:41.300
to building a UV-based tool called PyWrangler,
00:42:41.320 --> 00:42:44.360
which lets you just install any package that you want
00:42:44.760 --> 00:42:46.240
and get it into your worker very easily.
00:42:47.420 --> 00:42:50.960
And then there's the memory snapshots aspect of it, which I think we might get to later.
00:42:51.220 --> 00:42:51.480
Oh, yeah.
00:42:51.820 --> 00:42:52.060
Oh, yeah.
00:42:52.360 --> 00:42:56.240
Memory snapshots were basically what I started working on as soon as I came to Cloudflare.
00:42:56.280 --> 00:43:01.140
I spent like two months researching memory snapshots before I wrote like any code, made
00:43:01.280 --> 00:43:02.400
any pull requests at all.
00:43:03.220 --> 00:43:03.620
Interesting.
00:43:03.880 --> 00:43:04.000
Okay.
00:43:04.520 --> 00:43:06.940
And you just gave a presentation at the Python Language Summit,
00:43:07.480 --> 00:43:08.740
also at EuroPython a little
00:43:08.740 --> 00:43:09.040
while ago,
00:43:09.200 --> 00:43:09.300
right?
00:43:09.700 --> 00:43:10.020
Yeah,
00:43:10.580 --> 00:43:10.640
right.
00:43:10.940 --> 00:43:25.040
So this was about the fact that there is an important difficulty that comes up with memory snapshots, which is that it introduces a difference between sort of startup time or like, you know,
00:43:25.200 --> 00:43:31.140
sort of like top level execution and like your actual like runtime logic.
00:43:31.220 --> 00:43:36.480
And the Python language does not have a distinction like this,
00:43:36.640 --> 00:43:36.760
right?
00:43:36.850 --> 00:43:38.340
Like the Python runtime,
00:43:38.770 --> 00:43:40.380
when you start it up, it bootstraps itself.
00:43:40.980 --> 00:43:43.920
And then it just starts evaling user code.
00:43:44.240 --> 00:43:48.220
And whether it's top level user code or calling a function,
00:43:48.410 --> 00:43:49.160
it doesn't matter.
00:43:49.580 --> 00:43:52.000
Like it just evals until it stops evaling.
00:43:52.010 --> 00:43:53.860
And when it runs out of stuff to do, it shuts down.
00:43:54.600 --> 00:43:54.700
Yeah,
00:43:54.860 --> 00:43:58.140
even things like import statements are really code execution,
00:43:58.460 --> 00:43:59.540
not just, you know,
00:43:59.700 --> 00:44:00.240
linking or whatever.
00:44:00.300 --> 00:44:02.500
It takes a bit to wrap your head around it.
00:44:02.760 --> 00:44:04.160
It's just right.
00:44:04.320 --> 00:44:06.800
Like the import statement is compiled into something.
00:44:07.300 --> 00:44:09.580
And then like those op codes get like interpreted.
00:44:09.920 --> 00:44:13.600
And that causes import lib to go look up files on disk,
00:44:13.760 --> 00:44:15.140
find the thing that it wants to import.
00:44:15.500 --> 00:44:17.680
And then it like starts executing that file.
00:44:18.540 --> 00:44:21.340
And so for memory snapshots,
00:44:21.500 --> 00:44:22.180
you know, we say like, okay,
00:44:22.340 --> 00:44:22.420
look,
00:44:22.660 --> 00:44:23.740
all of that top level stuff,
00:44:23.820 --> 00:44:25.680
it's going to happen the same every time.
00:44:26.160 --> 00:44:32.220
So it's very wasteful to keep doing it every time someone's deployed an application to the edge.
00:44:32.700 --> 00:44:40.240
Like every single time it cold starts, it's going to execute exactly the same top level code and end up with exactly the same outcome.
00:44:40.780 --> 00:44:43.900
And so we would really like to just save that work.
00:44:44.260 --> 00:44:51.660
And this is actually very similar to the work that like optimizing Python compilers like PyPy and Grawl Python do,
00:44:52.650 --> 00:44:57.620
because they also want to evaluate all that stuff at compile time.
00:44:57.630 --> 00:44:58.840
This is like partial evaluation.
00:44:59.310 --> 00:45:01.400
So it's a bit of a different technology than a memory snapshot.
00:45:01.730 --> 00:45:03.400
But it has the same fundamental issue,
00:45:03.570 --> 00:45:08.600
which is that it needs to impose a model of like what is startup time,
00:45:08.780 --> 00:45:12.160
what can be precompiled onto a language that doesn't have one.
00:45:12.680 --> 00:45:13.280
Now, of course,
00:45:13.680 --> 00:45:17.640
you know, I think this is this is this talk is like a fun thing to think about.
00:45:18.280 --> 00:45:18.420
But,
00:45:18.720 --> 00:45:18.920
you know,
00:45:19.080 --> 00:45:19.360
I mean,
00:45:19.740 --> 00:45:22.860
at least Thomas Vouders said that it was like a nonstarter.
00:45:23.020 --> 00:45:27.040
And I think he is right that like, you know, it's sort of too late for the language to get something like this.
00:45:27.400 --> 00:45:29.420
But I have friends that are working on on,
00:45:29.740 --> 00:45:31.060
you know, new programming languages.
00:45:31.180 --> 00:45:34.660
My friend Antonio Cooney is trying to make this language called SPI,
00:45:34.860 --> 00:45:36.100
which stands for static Python,
00:45:37.440 --> 00:45:39.100
which is supposed to be like a better R Python,
00:45:39.960 --> 00:45:40.940
which was used for PyPy.
00:45:41.360 --> 00:45:41.880
And basically,
00:45:42.620 --> 00:45:47.700
the main idea in some sense of the language is to pre-bake a notion of
00:45:48.100 --> 00:45:48.500
compile,
00:45:48.780 --> 00:45:52.380
to create a notion of compile time versus execution time,
00:45:52.720 --> 00:45:54.260
and then allow lots
00:45:54.260 --> 00:45:59.340
of compile time evaluation of spy code so that it can perform that.
00:45:59.600 --> 00:46:02.520
Yeah, the basic idea is something like you're going to load the interpreter,
00:46:02.780 --> 00:46:03.000
it's going to
00:46:03.000 --> 00:46:04.180
load all the standard library,
00:46:04.600 --> 00:46:07.160
it's going to maybe read some of the files,
00:46:07.660 --> 00:46:08.280
parse them,
00:46:08.340 --> 00:46:09.660
do the import processing.
00:46:10.020 --> 00:46:10.840
And that never changes,
00:46:11.140 --> 00:46:11.240
right?
00:46:11.320 --> 00:46:11.560
Well,
00:46:11.760 --> 00:46:13.560
maybe the import, because it depends if you run code or not.
00:46:13.650 --> 00:46:16.960
But other than that, you theoretically could say,
00:46:17.320 --> 00:46:18.500
let's just see what happens.
00:46:18.800 --> 00:46:19.740
And like a VM,
00:46:20.000 --> 00:46:20.280
just go,
00:46:20.440 --> 00:46:21.220
your memory's back.
00:46:21.430 --> 00:46:21.540
Continue.
00:46:22.150 --> 00:46:22.300
Yeah?
00:46:22.660 --> 00:46:22.880
Right.
00:46:22.970 --> 00:46:25.800
And of course, there's a lot of subtlety in there because we have,
00:46:26.600 --> 00:46:27.040
for instance,
00:46:27.260 --> 00:46:28.180
if you
00:46:28.360 --> 00:46:29.540
import a dynamic library,
00:46:29.840 --> 00:46:32.760
it does all this relocations.
00:46:33.530 --> 00:46:39.920
It allocates space for all the global variables that the dynamic library is going to define.
00:46:40.220 --> 00:46:42.180
And then it relocates them all into that space.
00:46:42.720 --> 00:46:43.520
And it, you know,
00:46:43.880 --> 00:46:46.100
relocates all the functions from the dynamic library.
00:46:46.540 --> 00:46:50.020
And somehow you have to do some crazy magic with the dynamic loader.
00:46:50.400 --> 00:46:50.560
Basically,
00:46:51.000 --> 00:46:53.940
like I have a loader patch that when it loads a dynamic library,
00:46:54.360 --> 00:46:59.100
writes down the relocation base that it's putting the dynamic library at.
00:46:59.440 --> 00:47:01.840
And then when I'm going to restore the memory snapshot,
00:47:01.860 --> 00:47:04.780
I have to make sure that it gets relocated to the same place.
00:47:04.880 --> 00:47:07.580
So I patch the malloc so that it will,
00:47:08.020 --> 00:47:09.780
instead of actually doing a memory allocation,
00:47:10.140 --> 00:47:11.060
it just looks,
00:47:11.360 --> 00:47:11.520
oh,
00:47:11.700 --> 00:47:12.360
in this context,
00:47:12.600 --> 00:47:14.580
I'm allocating memory for this dynamic library.
00:47:15.580 --> 00:47:16.260
In the snapshot,
00:47:16.480 --> 00:47:18.060
we allocated it at this address,
00:47:18.240 --> 00:47:19.480
so we're going to play back that address.
00:47:20.160 --> 00:47:22.960
And then all this crazy magic just sort of...
00:47:23.040 --> 00:47:24.680
That sounds supremely complicated.
00:47:25.420 --> 00:47:26.360
It's very...
00:47:26.640 --> 00:47:27.460
It was a lot of fun.
00:47:27.600 --> 00:47:28.500
It's really horrible.
00:47:29.800 --> 00:47:31.540
All right, so let's go back to the announcement.
00:47:31.840 --> 00:47:33.360
There's a couple of code samples
00:47:33.700 --> 00:47:34.900
and different types of things here.
00:47:35.960 --> 00:47:39.020
So programming model is a little bit like writing an API,
00:47:39.280 --> 00:47:39.360
yeah?
00:47:39.680 --> 00:47:40.000
Yeah,
00:47:40.510 --> 00:47:44.860
I think the major usage of workers runtime is writing an API server.
00:47:45.030 --> 00:47:48.000
So we used Face the API a lot in our examples.
00:47:48.720 --> 00:47:52.920
So a lot of Python users might use Python in different ways,
00:47:53.030 --> 00:47:57.020
but I think the major use case of workers runtime is to build an API server
00:47:57.360 --> 00:47:59.580
and connecting different findings in it.
00:47:59.760 --> 00:48:02.460
So yeah, that's the examples we show in our flow post.
00:48:02.760 --> 00:48:05.880
Yeah, you want your API to be super snappy and responsive.
00:48:06.240 --> 00:48:12.400
So if you could put your data in D1 and then have your code also run right literally in
00:48:12.400 --> 00:48:13.640
the same process right there,
00:48:13.880 --> 00:48:14.900
like that's going to be really great.
00:48:15.100 --> 00:48:15.160
Yeah.
00:48:15.500 --> 00:48:16.140
So you can,
00:48:16.300 --> 00:48:17.840
if you know how to write a FastAPI app,
00:48:18.080 --> 00:48:18.920
it's the same thing.
00:48:19.070 --> 00:48:21.200
Just instead of uvacoron.run,
00:48:21.600 --> 00:48:24.280
it's just hand off the app and off it goes,
00:48:24.620 --> 00:48:25.780
which is really,
00:48:25.920 --> 00:48:26.220
really neat.
00:48:26.480 --> 00:48:28.980
Now, the examples that I saw on this page, I don't remember,
00:48:29.180 --> 00:48:30.280
I'm pretty sure they all
00:48:30.420 --> 00:48:32.100
have like one request,
00:48:32.300 --> 00:48:33.020
just like forward slash.
00:48:33.500 --> 00:48:35.300
can I have a more complicated app with,
00:48:35.540 --> 00:48:37.460
say, five or six different endpoints?
00:48:38.200 --> 00:48:38.320
Yeah,
00:48:38.500 --> 00:48:39.260
that's just per short, yes,
00:48:39.440 --> 00:48:39.660
right?
00:48:39.960 --> 00:48:43.140
Like, you know, you could make any FastAPI app you want here, right?
00:48:43.400 --> 00:48:46.320
Yeah, there is no limits to how many endpoints you can have.
00:48:47.200 --> 00:48:50.780
I suppose it might be worth talking about the actual limits that the workers have.
00:48:51.120 --> 00:48:51.620
And that is,
00:48:52.280 --> 00:48:53.640
yeah, so it's memory,
00:48:53.940 --> 00:48:55.280
which is 128 megabytes,
00:48:55.880 --> 00:48:57.960
and CPU time as well.
00:48:59.060 --> 00:49:03.460
You know, I think actually a great thing about workers is that you can do quite a lot
00:49:03.460 --> 00:49:03.540
free,
00:49:04.020 --> 00:49:06.620
like completely for free, you don't have to pay anything to Cloudflare,
00:49:06.850 --> 00:49:07.860
you can run a very
00:49:08.030 --> 00:49:09.340
simple FastAPI application,
00:49:09.560 --> 00:49:10.340
even I think,
00:49:10.600 --> 00:49:10.940
for free.
00:49:11.740 --> 00:49:14.240
What's the free request limit is like 100,000
00:49:14.360 --> 00:49:15.020
requests a day?
00:49:15.260 --> 00:49:15.720
Is that right?
00:49:15.900 --> 00:49:16.140
Yeah,
00:49:16.760 --> 00:49:18.160
yeah, you get 100,000 requests,
00:49:18.780 --> 00:49:20.140
I think, per day.
00:49:20.580 --> 00:49:21.620
And yeah,
00:49:21.670 --> 00:49:24.800
if you type in workers limits into Google,
00:49:25.080 --> 00:49:25.760
it should show up.
00:49:26.670 --> 00:49:27.820
But if you know, if you're just
00:49:27.840 --> 00:49:29.580
doing kind of more CPU intensive stuff,
00:49:29.800 --> 00:49:33.000
then that is another limit that we have.
00:49:33.320 --> 00:49:33.480
Yeah,
00:49:33.660 --> 00:49:34.260
it's basically
00:49:34.580 --> 00:49:38.960
there 10 milliseconds for free of CPU time and five minutes for paid.
00:49:39.980 --> 00:49:41.820
But yeah, you can do quite a lot.
00:49:42.400 --> 00:49:42.760
It's very,
00:49:42.960 --> 00:49:43.380
very flexible.
00:49:43.740 --> 00:49:43.900
Right.
00:49:44.180 --> 00:49:46.120
Speaking of what we were doing for those two years,
00:49:46.300 --> 00:49:46.620
another thing
00:49:46.700 --> 00:49:51.480
that took a lot of careful work was making sure that when you run out of that 10 milliseconds of
00:49:51.500 --> 00:49:55.800
CPU time that a signal is delivered to the Python runtime,
00:49:56.300 --> 00:49:58.120
and it gracefully interrupts its
00:49:58.360 --> 00:50:04.280
execution and returns to Cloudflare so that it doesn't like leave it in a broken state.
00:50:04.630 --> 00:50:04.800
Because
00:50:05.220 --> 00:50:06.720
if you do this the naive way,
00:50:07.640 --> 00:50:12.580
JavaScript throws a non catchable exception into the runtime and
00:50:12.700 --> 00:50:17.060
forcibly unwinds all of the call stack without executing finally blocks or,
00:50:17.220 --> 00:50:17.900
you know, catch blocks.
00:50:18.420 --> 00:50:20.420
And so like any locks that you've taken
00:50:20.660 --> 00:50:22.480
that you were expecting to release in a finally block,
00:50:22.760 --> 00:50:23.760
that just doesn't get executed.
00:50:23.920 --> 00:50:25.760
And then the runtime is like completely broken.
00:50:26.400 --> 00:50:26.780
And so
00:50:27.500 --> 00:50:28.080
Or
00:50:28.080 --> 00:50:30.360
like half written files that are not, the
00:50:30.360 --> 00:50:31.340
buffer's not flushed. All
00:50:31.340 --> 00:50:32.460
sorts of things could go wrong. All
00:50:32.460 --> 00:50:33.320
sorts of things, you know, like
00:50:33.320 --> 00:50:36.160
loss of code relies on finally blocks executing
00:50:36.440 --> 00:50:36.660
and
00:50:37.500 --> 00:50:39.380
it was not executing the finally blocks. And
00:50:39.380 --> 00:50:42.240
so we had to like do some very elaborate thing to
00:50:42.240 --> 00:50:46.000
make the CPU time limiter deliver the signal correctly
00:50:46.000 --> 00:50:46.840
to the Python
00:50:47.860 --> 00:50:49.980
M-scripted operating system inside of the
00:50:50.540 --> 00:50:50.660
runtime.
00:50:50.900 --> 00:50:51.880
Of course, we have the same problem with
00:50:52.000 --> 00:50:52.500
Rust workers.
00:50:52.890 --> 00:50:54.000
So we basically have
00:50:54.040 --> 00:50:55.760
the same solution for both Python
00:50:56.000 --> 00:50:57.360
workers and for Rust workers for that.
00:50:57.720 --> 00:50:59.120
As you start to bring in more languages,
00:50:59.320 --> 00:50:59.500
you're like,
00:50:59.620 --> 00:51:01.340
this is kind of the same problem.
00:51:01.980 --> 00:51:02.580
Okay, this is great.
00:51:02.740 --> 00:51:03.820
You've got a lot of
00:51:04.339 --> 00:51:04.700
computer.
00:51:05.100 --> 00:51:05.860
100,000
00:51:06.020 --> 00:51:07.320
requests a day for free?
00:51:07.860 --> 00:51:08.520
That's a lot.
00:51:08.880 --> 00:51:10.080
You can do a lot.
00:51:10.540 --> 00:51:11.720
Many, many little hobby
00:51:11.900 --> 00:51:13.720
apps and small apps live well under
00:51:13.860 --> 00:51:14.080
that limit.
00:51:14.300 --> 00:51:15.980
Right. I think the good part of
00:51:16.000 --> 00:51:17.880
for like hobby developers
00:51:18.200 --> 00:51:20.300
is we have really generous pricing.
00:51:20.480 --> 00:51:22.080
I don't want to be too marketing pitch,
00:51:22.480 --> 00:51:25.380
but I also used Qualifier when I was a student
00:51:25.740 --> 00:51:27.700
because they really offered a good free pricing.
00:51:28.160 --> 00:51:30.700
Like you can have like 10 gigabytes of R2 for free,
00:51:30.720 --> 00:51:31.120
I guess.
00:51:31.360 --> 00:51:32.240
So there's a storage,
00:51:32.540 --> 00:51:33.420
there's a runtime,
00:51:34.040 --> 00:51:35.820
there's everything you can use freely.
00:51:36.160 --> 00:51:36.560
Yeah, well,
00:51:36.860 --> 00:51:38.540
and you know, the storage is one thing,
00:51:38.700 --> 00:51:39.420
but the egress,
00:51:40.040 --> 00:51:41.440
that's where you pay money often
00:51:41.900 --> 00:51:45.140
for S3 is you pay tons of bandwidth charges.
00:51:45.900 --> 00:51:46.180
Yeah,
00:51:46.360 --> 00:51:46.600
very neat.
00:51:46.960 --> 00:51:47.660
All right, let's see.
00:51:47.920 --> 00:51:49.420
Let's go back to this.
00:51:49.880 --> 00:51:50.920
So first class language,
00:51:51.420 --> 00:51:51.800
really good.
00:51:52.060 --> 00:51:52.660
FastAPI,
00:51:54.260 --> 00:51:54.400
Django,
00:51:54.600 --> 00:51:54.800
Flask.
00:51:55.160 --> 00:51:57.960
Does it basically run anything that does WSGI or ASCII
00:51:58.340 --> 00:51:59.580
as each return that?
00:52:00.520 --> 00:52:00.860
You know,
00:52:01.180 --> 00:52:01.280
like,
00:52:01.600 --> 00:52:02.500
of course, there could be problems
00:52:02.840 --> 00:52:04.640
with them trying to start threads and things like that.
00:52:04.820 --> 00:52:07.580
But assuming that they don't try to start too many threads,
00:52:08.180 --> 00:52:08.260
then,
00:52:08.420 --> 00:52:08.520
like,
00:52:08.760 --> 00:52:11.600
you know, we have a general purpose ASCII
00:52:11.660 --> 00:52:13.440
and WSGI adapters that you see here.
00:52:13.720 --> 00:52:13.940
Okay.
00:52:14.220 --> 00:52:16.540
Yeah, well, you know, that was one of the best things that happened to Python web,
00:52:16.920 --> 00:52:16.980
right?
00:52:17.600 --> 00:52:21.260
That you got this interface that you can plug into all these different runtimes.
00:52:21.420 --> 00:52:21.480
And,
00:52:21.650 --> 00:52:23.100
you know, it sounds like you're as well.
00:52:23.420 --> 00:52:24.380
It's amazing for us.
00:52:24.410 --> 00:52:24.500
Yeah,
00:52:24.680 --> 00:52:26.360
because they don't try to do IO directly.
00:52:26.610 --> 00:52:26.900
And so,
00:52:27.200 --> 00:52:29.980
you know, I mean, that's exactly the problem we have with something like URL of three.
00:52:30.050 --> 00:52:32.640
Of course, URL of three specifically supports Pyodide.
00:52:32.640 --> 00:52:33.060
So it's okay.
00:52:33.980 --> 00:52:34.220
But like,
00:52:34.760 --> 00:52:36.700
it's normal way of doing IO just doesn't work.
00:52:36.710 --> 00:52:40.060
So it needs a separate path for Pyodide.
00:52:40.780 --> 00:52:43.960
And all of these things would need that if it weren't for these beautiful adapters.
00:52:44.560 --> 00:52:45.980
that... Yeah, they're super
00:52:46.240 --> 00:52:47.000
polished and optimized.
00:52:47.580 --> 00:52:48.200
It's really nice.
00:52:48.660 --> 00:52:50.080
Yeah. Let's talk. We only got
00:52:50.080 --> 00:52:52.040
a couple minutes left before we're out
00:52:52.060 --> 00:52:52.340
of time.
00:52:52.820 --> 00:52:54.040
It's late
00:52:54.060 --> 00:52:54.600
in some places,
00:52:54.780 --> 00:52:55.360
early in others.
00:52:56.580 --> 00:52:57.880
Let's maybe round out this
00:52:58.200 --> 00:53:00.040
conversation by the types of
00:53:00.180 --> 00:53:01.860
apps that you see people building
00:53:02.140 --> 00:53:03.960
in Cloudflare workers in general, and
00:53:04.120 --> 00:53:05.600
specifically also in Python.
00:53:06.480 --> 00:53:08.080
Everyone knows what an API that
00:53:08.220 --> 00:53:09.980
talks to a database looks like, but can I
00:53:10.000 --> 00:53:11.340
do data science work here?
00:53:11.560 --> 00:53:12.260
Can I do
00:53:12.580 --> 00:53:15.200
long-running work? What types of things are people building here?
00:53:15.440 --> 00:53:19.440
A lot of the workers that I've looked at are big piles of boring business logic.
00:53:20.400 --> 00:53:21.840
It's just a mess,
00:53:22.160 --> 00:53:24.580
and it does apparently what they are needing.
00:53:25.920 --> 00:53:27.380
I would not recommend data science.
00:53:28.160 --> 00:53:32.620
It's not really a platform that has a lot of computing
00:53:32.980 --> 00:53:33.080
power.
00:53:33.300 --> 00:53:35.360
If you want to do things like graphics cards, SIMD,
00:53:35.580 --> 00:53:37.280
it doesn't have any of that.
00:53:38.800 --> 00:53:42.760
But it's a very powerful platform for stuff.
00:53:43.299 --> 00:53:44.080
That's totally fair.
00:53:44.190 --> 00:53:45.420
And I think that's one of the things
00:53:45.450 --> 00:53:47.760
I was trying to kind of explore is, right?
00:53:47.840 --> 00:53:51.300
Like how far can you push it before it just starts timing out
00:53:51.480 --> 00:53:52.720
or whatever, it runs out of memory.
00:53:53.120 --> 00:53:53.940
But what if I'm,
00:53:54.420 --> 00:53:56.600
let's say I'm a researcher or a student
00:53:56.780 --> 00:53:59.820
and I've got a pandas or just a parquet file
00:54:00.000 --> 00:54:00.980
with 20,000 records.
00:54:01.430 --> 00:54:02.520
And I do basic,
00:54:02.820 --> 00:54:03.200
like, here's a,
00:54:03.430 --> 00:54:04.580
let me do a little bit of query on that
00:54:04.630 --> 00:54:06.400
then I'll draw a graph or whatever.
00:54:06.860 --> 00:54:08.800
It can, in principle, do stuff like that.
00:54:09.200 --> 00:54:10.100
Yeah, that seems like it might work.
00:54:10.560 --> 00:54:10.620
Right.
00:54:10.840 --> 00:54:11.800
You can load pandas.
00:54:11.800 --> 00:54:12.400
You can load,
00:54:12.620 --> 00:54:12.820
you know,
00:54:13.760 --> 00:54:17.620
whatever the parquet package that is popular now is.
00:54:18.680 --> 00:54:19.080
And,
00:54:20.240 --> 00:54:20.900
you know, I mean,
00:54:21.380 --> 00:54:22.580
just the packages,
00:54:22.840 --> 00:54:23.280
you know, if you start,
00:54:23.460 --> 00:54:24.000
you know, like, for instance,
00:54:24.620 --> 00:54:26.320
SciPy is just too big,
00:54:27.200 --> 00:54:27.660
too horrible.
00:54:28.360 --> 00:54:32.460
And it doesn't really work to import SciPy.
00:54:32.520 --> 00:54:33.040
I mean, SciFi,
00:54:33.240 --> 00:54:34.360
when you bring it in,
00:54:34.640 --> 00:54:36.820
it has like over 100 different shared libraries.
00:54:37.520 --> 00:54:37.740
You know,
00:54:38.700 --> 00:54:38.760
yeah,
00:54:39.060 --> 00:54:43.180
SciFi has been like a real journey for us in Pyodide.
00:54:43.240 --> 00:54:45.400
Like it's really like the most horrible package.
00:54:47.800 --> 00:54:49.460
But if it's not SciFi,
00:54:49.680 --> 00:54:51.640
you know, Pandas works and you can just,
00:54:51.940 --> 00:54:55.920
you know, load your Parquet file and share your graph as long as it's not too big.
00:54:56.040 --> 00:54:56.300
Well,
00:54:56.640 --> 00:54:57.180
in my opinion,
00:54:57.360 --> 00:55:02.400
like pandas or docdb or other data processing libraries are not very optimized for Python workers.
00:55:02.580 --> 00:55:03.900
It's because like there are different,
00:55:04.180 --> 00:55:09.480
like the concept is a little bit different because workers is very memory limited environment.
00:55:09.700 --> 00:55:13.020
So we basically recommend everything to run in streams,
00:55:13.280 --> 00:55:14.820
not like load a bunch of memory,
00:55:15.720 --> 00:55:17.500
like lots of data frames inside memory.
00:55:17.700 --> 00:55:18.440
More polars,
00:55:18.620 --> 00:55:19.980
less pandas type of flow,
00:55:20.160 --> 00:55:20.260
yeah?
00:55:20.600 --> 00:55:20.700
Yeah,
00:55:20.940 --> 00:55:21.060
like,
00:55:21.220 --> 00:55:22.180
yeah, more polars,
00:55:22.340 --> 00:55:22.980
not pandas.
00:55:23.140 --> 00:55:26.020
if you need to load all the data frames in your memory,
00:55:26.220 --> 00:55:27.180
that it won't fit.
00:55:27.380 --> 00:55:28.480
You need to do streams.
00:55:28.700 --> 00:55:29.140
But actually,
00:55:29.290 --> 00:55:30.360
like Python packages are,
00:55:31.140 --> 00:55:32.440
especially legacy Python packages,
00:55:32.450 --> 00:55:33.740
are not very optimized for that.
00:55:33.980 --> 00:55:36.180
So we'll need to do a lot of back and forth
00:55:36.230 --> 00:55:37.320
to make it work properly.
00:55:37.720 --> 00:55:37.800
Right.
00:55:38.160 --> 00:55:38.300
Yeah,
00:55:38.520 --> 00:55:39.080
I mean...
00:55:39.380 --> 00:55:39.540
Go ahead.
00:55:39.960 --> 00:55:40.100
You go.
00:55:40.300 --> 00:55:43.200
So we're talking about Pyodide and WebAssembly.
00:55:44.019 --> 00:55:46.740
Another way, if I was this theoretical person
00:55:46.810 --> 00:55:47.340
I was describing,
00:55:47.500 --> 00:55:48.960
wanted to put this stuff on workers,
00:55:49.360 --> 00:55:51.820
maybe what I do is I just put my parquet file
00:55:51.820 --> 00:55:54.240
and my WebAssembly stuff on Cloudflare
00:55:54.460 --> 00:55:55.640
and just put it on the front end,
00:55:55.860 --> 00:55:56.000
right?
00:55:56.380 --> 00:55:59.460
You could run it like a JupyterLite style of execution.
00:55:59.900 --> 00:56:01.940
And then everyone gets their own little browser runtime
00:56:02.220 --> 00:56:03.740
instead of Edgeware runtime.
00:56:03.980 --> 00:56:05.540
Lots of people are doing exactly that.
00:56:06.180 --> 00:56:06.800
And then of course,
00:56:07.080 --> 00:56:09.980
all of the compute is paid for by the end user.
00:56:10.640 --> 00:56:11.000
Exactly.
00:56:11.740 --> 00:56:15.040
That's your iPhone battery or your iPad battery
00:56:15.120 --> 00:56:15.620
or whatever,
00:56:15.940 --> 00:56:17.880
rather than your compute bill.
00:56:19.040 --> 00:56:21.180
Because setting up that kind of stuff is really tricky
00:56:21.180 --> 00:56:23.140
for researchers who are not developers
00:56:23.560 --> 00:56:24.660
and they're not DevOps people.
00:56:24.880 --> 00:56:25.260
They're just like,
00:56:25.420 --> 00:56:26.900
I just want to share this thing, right?
00:56:27.020 --> 00:56:28.880
So maybe that's the way to go.
00:56:29.160 --> 00:56:29.300
All right.
00:56:29.720 --> 00:56:30.720
I've talked to so many people
00:56:31.100 --> 00:56:31.700
who are doing that,
00:56:31.880 --> 00:56:34.180
like sharing their data science notebook,
00:56:34.520 --> 00:56:36.060
like instead of having to have
00:56:36.060 --> 00:56:36.780
a Jupyter notebook
00:56:37.000 --> 00:56:38.180
and then they make it
00:56:38.260 --> 00:56:39.260
and then their collaborators
00:56:39.560 --> 00:56:40.680
don't have the right things
00:56:40.800 --> 00:56:41.460
on their computer
00:56:41.640 --> 00:56:42.580
or it doesn't quite work.
00:56:43.000 --> 00:56:43.700
You know, this is exactly
00:56:43.780 --> 00:56:44.400
the same sorts of problems
00:56:44.460 --> 00:56:45.800
I saw in math all the time.
00:56:46.740 --> 00:56:47.020
And,
00:56:47.280 --> 00:56:47.480
you know,
00:56:47.720 --> 00:56:49.160
these internet-based tools
00:56:49.440 --> 00:56:51.160
are just like so great for them
00:56:51.380 --> 00:57:07.120
You know, and it really is like what happens with like a math or science project is like if there's a lowest common denominator effect where like the technology you can use your research is only the things that the least technically competent person in your group can use.
00:57:07.500 --> 00:57:10.740
Because if you can't get get it onto their computer and get it working for them,
00:57:10.940 --> 00:57:13.840
then they won't be able to productively contribute to a project that needs it.
00:57:13.980 --> 00:57:14.580
Yeah, yeah.
00:57:14.740 --> 00:57:22.400
And you're looking over at your 67 year old thesis advisor who still thinks Fortran is like the hot stuff. And you're like, Oh,
00:57:22.580 --> 00:57:22.780
gosh,
00:57:23.340 --> 00:57:32.920
some of these people literally like it's like they have they like dictate to their secretary and like they've never touched a computer. And some of these people like contribute to the Linux kernel like regularly.
00:57:33.260 --> 00:57:33.380
Yeah,
00:57:33.570 --> 00:57:33.660
exactly.
00:57:34.240 --> 00:57:35.440
They both look like a 67,
00:57:35.780 --> 00:57:36.600
like nerdy mathematician,
00:57:37.320 --> 00:57:37.640
but like,
00:57:37.960 --> 00:57:42.420
just like the farest ends of the scale of like confidence with computers.
00:57:43.150 --> 00:57:43.240
Incredible.
00:57:44.640 --> 00:57:44.940
All right,
00:57:45.300 --> 00:57:46.160
you guys, let's call it there.
00:57:46.680 --> 00:57:48.860
There's a lot of stuff that we could talk about.
00:57:48.930 --> 00:57:49.560
I guess one really,
00:57:49.720 --> 00:57:53.460
really quick thing I just want to give a shout out to is this memory snapshot stuff that we talked about.
00:57:53.840 --> 00:57:57.460
Hood, you all are using that for basically increasing the startup time,
00:57:57.810 --> 00:57:58.740
the cold start time.
00:57:58.780 --> 00:57:59.320
We want it.
00:57:59.370 --> 00:57:59.900
We want it to go.
00:57:59.960 --> 00:58:00.680
Sorry, you're right.
00:58:01.380 --> 00:58:02.740
Increasing the speed,
00:58:03.280 --> 00:58:04.040
decreasing the time.
00:58:04.340 --> 00:58:06.160
Yes, I blended those together and that doesn't work.
00:58:06.560 --> 00:58:08.580
So just that's part of the mix,
00:58:08.740 --> 00:58:08.820
right?
00:58:09.140 --> 00:58:09.880
That's absolutely right.
00:58:10.040 --> 00:58:13.240
It's to not do that startup stuff again.
00:58:13.500 --> 00:58:13.960
Yeah, awesome.
00:58:14.540 --> 00:58:15.500
All right, final thought.
00:58:15.620 --> 00:58:19.120
I'll give you all a chance to give a quick shout out to listeners who are like,
00:58:19.400 --> 00:58:19.480
huh,
00:58:19.860 --> 00:58:21.020
this is interesting.
00:58:21.170 --> 00:58:21.920
What do I do now?
00:58:22.280 --> 00:58:22.540
Dominic,
00:58:22.920 --> 00:58:23.180
you're first.
00:58:24.420 --> 00:58:24.520
Well,
00:58:24.900 --> 00:58:25.800
I was just going to say,
00:58:25.970 --> 00:58:26.100
actually,
00:58:27.210 --> 00:58:31.220
I think the best thing for workers is IO-bound applications.
00:58:31.320 --> 00:58:33.760
if you have something that's like pushing a lot of bytes,
00:58:34.420 --> 00:58:36.140
isn't doing a lot of CPU with them,
00:58:36.640 --> 00:58:37.820
then give it a try.
00:58:38.580 --> 00:58:41.600
I think you'll be surprised how far you can go how many users you can handle
00:58:41.720 --> 00:58:42.460
even on the free tier.
00:58:43.560 --> 00:58:47.740
And yeah, just check it out type in Python workers into Google and give it a
00:58:47.860 --> 00:58:47.960
try.
00:58:48.140 --> 00:58:48.280
Well,
00:58:48.660 --> 00:58:48.780
yeah,
00:58:48.980 --> 00:58:50.940
I also say just give it a try.
00:58:51.120 --> 00:58:53.360
Because I'm already running a lot of my hobby
00:58:53.480 --> 00:58:54.980
applications in Python workers.
00:58:55.280 --> 00:58:56.740
It's working really well.
00:58:57.100 --> 00:58:58.840
So please go give it a try.
00:59:00.880 --> 00:59:01.280
If
00:59:01.300 --> 00:59:03.460
let us know in our Discord and we'll exit.
00:59:03.860 --> 00:59:06.440
And I just want to advertise to anyone out there
00:59:06.660 --> 00:59:09.320
that WebAssembly is like a really cool ecosystem.
00:59:09.500 --> 00:59:10.720
There's a lot of missing pieces
00:59:10.910 --> 00:59:12.320
in terms of like fundamental computing.
00:59:12.510 --> 00:59:14.700
So if you like operating systems,
00:59:14.930 --> 00:59:17.800
if you want to think about like how LibC works
00:59:18.040 --> 00:59:18.340
or,
00:59:18.640 --> 00:59:18.840
you know,
00:59:19.300 --> 00:59:20.560
low level details,
00:59:21.140 --> 00:59:21.320
and,
00:59:22.290 --> 00:59:24.640
you know, you feel like Linux works too well
00:59:25.090 --> 00:59:25.960
for you to get into,
00:59:26.500 --> 00:59:28.500
then like I think WebAssembly is a really great space
00:59:28.680 --> 00:59:30.360
because a lot more of that stuff is just
00:59:30.560 --> 00:59:33.160
I think no one has ever even tried to make it work.
00:59:33.540 --> 00:59:34.640
There's not that much effort.
00:59:35.140 --> 00:59:37.300
The total number of people working on it is quite small.
00:59:37.820 --> 00:59:39.620
So there's lots of open niches.
00:59:39.640 --> 00:59:42.660
And if you find something that you wish worked that doesn't work,
00:59:42.680 --> 00:59:45.540
you can just sort of wedge yourself in there and fix things.
00:59:45.960 --> 00:59:47.100
So I think it's a great space.
00:59:47.340 --> 00:59:47.700
Excellent.
00:59:48.080 --> 00:59:48.280
All right.
00:59:48.320 --> 00:59:49.460
Thank you all for being on the show.
00:59:49.880 --> 00:59:50.620
I learned a lot.
00:59:50.980 --> 00:59:52.160
I didn't point out at the beginning,
00:59:52.320 --> 00:59:52.820
I should have,
00:59:52.960 --> 00:59:55.540
that I'm a complete newbie at all this edge worker stuff.
00:59:55.780 --> 00:59:58.120
So it was really interesting to get a look into it.
00:59:58.160 --> 01:00:00.260
And it's awesome to see it come into the Python space.
01:00:00.750 --> 01:00:01.100
See you all later.
01:00:01.460 --> 01:00:01.640
Thank you.
01:00:02.460 --> 01:00:02.700
Thank you.
01:00:04.520 --> 01:00:06.660
This has been another episode of Talk Python To Me.
01:00:07.040 --> 01:00:07.760
Thank you to our sponsors.
01:00:07.970 --> 01:00:09.240
Be sure to check out what they're offering.
01:00:09.450 --> 01:00:10.820
It really helps support the show.
01:00:11.360 --> 01:00:11.800
Tomorrow,
01:00:12.320 --> 01:00:12.500
Wednesday,
01:00:12.660 --> 01:00:13.420
November 4th,
01:00:13.580 --> 01:00:15.800
we're having our first tech meetup,
01:00:16.240 --> 01:00:18.580
our live tech event as part of Talk Python membership.
01:00:19.180 --> 01:00:20.200
If you're not yet a member,
01:00:20.780 --> 01:00:20.900
well,
01:00:21.300 --> 01:00:22.560
join up and support the show
01:00:22.780 --> 01:00:25.560
and get an awesome community and experience to boot.
01:00:26.060 --> 01:00:27.500
Just visit talkpython.fm,
01:00:27.760 --> 01:00:30.100
Click membership in the nav bar and you'll be off to the races.
01:00:31.040 --> 01:00:31.780
If you are a member,
01:00:32.400 --> 01:00:37.900
we'll be talking about Talk Python in production and some really wild new ideas that I'm exploring.
01:00:38.140 --> 01:00:41.760
I think you will find both fascinating and actually really practical,
01:00:42.020 --> 01:00:42.740
but no one's doing it.
01:00:43.280 --> 01:00:44.880
So join me on Wednesday, November 4th.
01:00:44.940 --> 01:00:46.800
And if you're listening to this after and thinking, Michael,
01:00:46.960 --> 01:00:48.440
why did you just put this in here?
01:00:48.760 --> 01:00:50.940
Nobody can listen to it because most people listen to after.
01:00:51.380 --> 01:00:52.720
These tech meetups come with recordings.
01:00:53.220 --> 01:00:54.620
Just visit talkpython.fm,
01:00:54.840 --> 01:00:55.340
click on membership,
01:00:55.520 --> 01:00:57.620
and then browse past member meetups and you'll be able to get it.
01:00:58.100 --> 01:01:01.000
So hopefully either you can join live or you can join afterwards.
01:01:01.760 --> 01:01:02.300
Become a member,
01:01:02.460 --> 01:01:03.000
support the show,
01:01:03.620 --> 01:01:04.040
join the event.
01:01:04.440 --> 01:01:06.320
If you or your team needs to learn Python,
01:01:06.550 --> 01:01:09.940
we have over 270 hours of beginner and advanced courses
01:01:10.260 --> 01:01:13.680
on topics ranging from complete beginners to async code,
01:01:13.820 --> 01:01:14.080
Flask,
01:01:14.360 --> 01:01:14.500
Django,
01:01:14.920 --> 01:01:16.600
HTMX, and even LLMs.
01:01:16.900 --> 01:01:17.300
Best of all,
01:01:17.520 --> 01:01:19.200
there's no subscription in sight.
01:01:19.640 --> 01:01:21.420
Browse the catalog at talkpython.fm.
01:01:22.160 --> 01:01:24.060
And if you're not already subscribed to the show
01:01:24.300 --> 01:01:25.500
on your favorite podcast player,
01:01:25.720 --> 01:01:26.780
what are you waiting for?
01:01:27.260 --> 01:01:29.220
just search for Python in your podcast player.
01:01:29.290 --> 01:01:30.200
We should be right at the top.
01:01:30.640 --> 01:01:32.160
If you enjoyed that geeky rap song,
01:01:32.270 --> 01:01:33.380
you can download the full track.
01:01:33.590 --> 01:01:35.500
The link is actually in your podcast player share notes.
01:01:36.340 --> 01:01:36.980
This is your host,
01:01:37.200 --> 01:01:37.660
Michael Kennedy.
01:01:38.060 --> 01:01:39.120
Thank you so much for listening.
01:01:39.310 --> 01:01:40.120
I really appreciate it.
01:01:40.560 --> 01:01:41.260
I'll see you next time.
01:01:52.920 --> 01:01:55.720
I'm out.
00:00:00.020 --> 00:00:02.020
Where does your Python code actually run?
00:00:02.270 --> 00:00:03.300
A server in Virginia?
00:00:03.570 --> 00:00:04.720
A container in Frankfurt?
00:00:05.300 --> 00:00:07.140
Pyodide put Python in the browser.
00:00:07.799 --> 00:00:10.140
Cloudflare put the browser into the server.
00:00:10.520 --> 00:00:12.560
Combine the two and you get Python workers,
00:00:13.160 --> 00:00:15.400
now generally available from Cloudflare.
00:00:15.630 --> 00:00:17.440
My guests are Hood Chatham, Jay Choi,
00:00:17.900 --> 00:00:19.820
and Dominic Pichetta from Cloudflare.
00:00:20.420 --> 00:00:22.000
Hood and Jay maintain Pyodide.
00:00:22.240 --> 00:00:25.020
Dominic got Python running in Cloudflare workers.
00:00:25.600 --> 00:00:28.220
Your FastAPI app ships as plain files.
00:00:28.620 --> 00:00:31.660
Then you can run it on CPython, compiled to WebAssembly,
00:00:31.860 --> 00:00:35.980
inside V8, at over 350 locations worldwide.
00:00:36.700 --> 00:00:40.120
This is Talk Python To Me, episode 568, recorded October 9th,
00:00:40.460 --> 00:00:41.340
2026.
00:00:57.960 --> 00:00:59.220
Welcome to Talk Python To Me,
00:00:59.380 --> 00:01:02.580
the number one Python podcast for developers and data scientists.
00:01:03.060 --> 00:01:03.860
This is your host,
00:01:04.040 --> 00:01:04.500
Michael Kennedy.
00:01:04.940 --> 00:01:08.420
I'm a PSF fellow who's been coding for over 25 years.
00:01:09.060 --> 00:01:10.180
Let's connect on social media.
00:01:10.500 --> 00:01:12.760
You'll find me and Talk Python on Mastodon, Bluesky,
00:01:13.140 --> 00:01:13.660
and X.
00:01:13.940 --> 00:01:15.700
The social links are all in your show notes.
00:01:16.540 --> 00:01:20.040
You can find over 10 years of past episodes at talkpython.fm.
00:01:20.240 --> 00:01:23.420
And if you want to be part of the show, you can join our recording live streams.
00:01:23.800 --> 00:01:24.260
That's right.
00:01:24.450 --> 00:01:25.700
We live stream the raw,
00:01:25.860 --> 00:01:27.700
uncut version of each episode on YouTube.
00:01:28.320 --> 00:01:32.720
Just visit talkpython.fm/youtube to see the schedule of upcoming events.
00:01:32.940 --> 00:01:36.600
Be sure to subscribe there and press the bell so you'll get notified anytime we're recording.
00:01:37.119 --> 00:01:37.600
Tomorrow,
00:01:38.120 --> 00:01:38.320
Wednesday,
00:01:38.540 --> 00:01:41.620
November 4th, we're having our first tech meetup,
00:01:42.060 --> 00:01:44.400
our live tech event as part of Talk Python membership.
00:01:44.980 --> 00:01:46.000
If you're not yet a member,
00:01:46.480 --> 00:01:46.600
well,
00:01:47.100 --> 00:01:48.360
join up and support the show
00:01:48.580 --> 00:01:51.360
and get an awesome community and experience to boot.
00:01:51.880 --> 00:01:54.660
Just visit talkpython.fm, click membership in the nav bar,
00:01:54.860 --> 00:01:55.900
and you'll be off to the races.
00:01:56.520 --> 00:01:57.580
If you are a member,
00:01:57.800 --> 00:02:03.720
we'll be talking about Talk Python in production and some really wild new ideas that I'm exploring.
00:02:03.940 --> 00:02:07.560
I think you will find both fascinating and actually really practical,
00:02:07.840 --> 00:02:08.560
but no one's doing it.
00:02:09.080 --> 00:02:10.679
So join me on Wednesday, November 4th.
00:02:10.759 --> 00:02:12.600
And if you're listening to this after and thinking, Michael,
00:02:12.760 --> 00:02:14.260
why did you just put this in here?
00:02:14.360 --> 00:02:16.740
Nobody can listen to it because most people listen to after.
00:02:17.200 --> 00:02:18.520
These tech meetups come with recordings.
00:02:19.120 --> 00:02:21.160
Just visit talkpython.fm, click on membership,
00:02:21.320 --> 00:02:23.440
and then browse past member meetups and you'll be able to get it.
00:02:23.900 --> 00:02:26.800
So hopefully either you can join live or you can join afterwards.
00:02:27.580 --> 00:02:28.100
Become a member,
00:02:28.260 --> 00:02:28.840
support the show,
00:02:29.420 --> 00:02:29.840
join the event.
00:02:30.540 --> 00:02:31.360
Dominic J.
00:02:31.880 --> 00:02:32.060
Hood,
00:02:32.240 --> 00:02:34.140
welcome to all of you to Talk Python To Me.
00:02:34.390 --> 00:02:34.980
Awesome to have you here.
00:02:35.220 --> 00:02:35.880
Awesome to be here.
00:02:36.160 --> 00:02:36.420
Yeah,
00:02:36.720 --> 00:02:40.220
I'm really excited to talk about Python on the Edge.
00:02:40.580 --> 00:02:42.400
It's very exciting what you all have announced.
00:02:43.000 --> 00:02:46.700
And I know it's been out there on Cloudflare for a little bit,
00:02:46.860 --> 00:02:49.800
but it's now officially formalized, officially supported,
00:02:50.020 --> 00:02:51.060
a little more smooth.
00:02:51.400 --> 00:02:52.820
So Python workers,
00:02:53.280 --> 00:02:54.100
very, very cool topic.
00:02:54.610 --> 00:02:55.260
Before we get to that,
00:02:55.440 --> 00:02:56.880
though, let's just do a quick,
00:02:57.040 --> 00:02:57.780
who are you?
00:02:58.260 --> 00:03:01.360
Just give me a little bit of your background and what you do and so on.
00:03:01.680 --> 00:03:02.760
Dominic, we'll just go around the squares here.
00:03:02.880 --> 00:03:03.360
Dominic, go first.
00:03:04.160 --> 00:03:04.280
Sure.
00:03:05.330 --> 00:03:08.040
I mean, I can get started how I got into Python.
00:03:08.520 --> 00:03:10.020
And that starts at,
00:03:10.720 --> 00:03:13.380
I guess, a very young age when I was playing with Visual Basic.net.
00:03:13.760 --> 00:03:14.900
And I realized that I hate Windows.
00:03:15.460 --> 00:03:21.600
I needed to get to Linux and Visual Basic.net back then did not support Linux at all.
00:03:21.900 --> 00:03:22.000
So
00:03:22.540 --> 00:03:25.200
a couple of my friends were using Python. So that's how I got into it.
00:03:26.140 --> 00:03:26.620
Afterwards,
00:03:27.460 --> 00:03:30.360
I actually got a little bit annoyed that Python was interpreted.
00:03:30.880 --> 00:03:31.800
So I looked for
00:03:32.000 --> 00:03:35.060
alternatives and I got involved in the NIMH programming language.
00:03:36.440 --> 00:03:37.880
And I became one of the
00:03:37.960 --> 00:03:39.440
core developers of that for a while.
00:03:40.660 --> 00:03:41.520
Fast forward a lot.
00:03:42.340 --> 00:03:43.440
I was working at
00:03:44.140 --> 00:03:51.020
meta and then I moved to Cloudflare to work on the workers runtime team working there on a bunch of
00:03:51.700 --> 00:03:53.120
features for workers in general.
00:03:54.080 --> 00:03:58.040
I actually was the person I guess that kind of experimented with
00:03:58.160 --> 00:04:05.760
Pyodide at Cloudflare and got it working and running and then eventually we got Hoodin to
00:04:05.790 --> 00:04:11.060
help us out with that and we started Python Workers and I've been working on that ever since as well
00:04:11.540 --> 00:04:12.100
And still do.
00:04:12.360 --> 00:04:12.740
Very,
00:04:12.920 --> 00:04:13.240
very excellent.
00:04:13.600 --> 00:04:13.820
You know,
00:04:14.000 --> 00:04:15.560
a word I haven't thought about for a while
00:04:15.760 --> 00:04:17.000
is visualbasic.net.
00:04:17.299 --> 00:04:19.060
I've written a little bit, a little bit.
00:04:19.239 --> 00:04:21.940
I mean, we're talking a couple of files of visualbasic.net.
00:04:22.280 --> 00:04:23.220
What of her boast language?
00:04:23.410 --> 00:04:23.840
I don't know.
00:04:24.160 --> 00:04:25.300
Great language to learn with, though.
00:04:25.580 --> 00:04:26.340
It is, it is.
00:04:26.600 --> 00:04:28.760
You know, I think it's interesting to contrast that
00:04:28.900 --> 00:04:29.200
with Python,
00:04:29.450 --> 00:04:29.540
actually,
00:04:29.720 --> 00:04:31.680
because Python also had many
00:04:31.720 --> 00:04:33.440
of the same goals of VB,
00:04:33.660 --> 00:04:35.800
but it somehow accomplished it
00:04:35.850 --> 00:04:38.340
with a lot less stuff on the screen.
00:04:38.740 --> 00:04:40.240
You know, like there's not begin if,
00:04:40.460 --> 00:04:41.940
end if, all this type of stuff.
00:04:42.030 --> 00:04:42.860
But yeah, very, very fun.
00:04:43.240 --> 00:04:43.320
Jay,
00:04:43.520 --> 00:04:43.920
welcome.
00:04:44.280 --> 00:04:44.500
Hey,
00:04:44.860 --> 00:04:47.880
I think I can start with how I started using Python as well,
00:04:48.060 --> 00:04:48.660
like Dominic.
00:04:48.860 --> 00:04:54.740
So I also started programming using some Visual Basic NC when I was like 10 years ago.
00:04:55.010 --> 00:05:01.120
And then I started learning Python when I was in second grade in university,
00:05:01.340 --> 00:05:01.700
I think.
00:05:01.960 --> 00:05:07.860
I was having some data science course learning about packages like ThumbPy and SciPy.
00:05:08.040 --> 00:05:10.160
That was when I first started using Python.
00:05:10.650 --> 00:05:12.120
And I just fell in love with Python.
00:05:12.760 --> 00:05:15.060
Like making apps were so easy with Python.
00:05:15.370 --> 00:05:19.920
So I was using, I started, starting then I started using Python for like 10 years.
00:05:20.880 --> 00:05:22.620
And around 2021,
00:05:23.410 --> 00:05:28.720
I started contributing to a library called Pyodip,
00:05:28.880 --> 00:05:31.760
which I think we will talk a lot in this podcast.
00:05:32.320 --> 00:05:37.080
And yeah, after maintaining it for around one or five years,
00:05:37.500 --> 00:05:45.980
I got invited to Cloudflare to work on Python workers using Pyrodite from Hoots and joined Cloudflare.
00:05:46.400 --> 00:05:51.300
And yeah, after that, I was working on Cloudflare Python workers for around a year.
00:05:51.600 --> 00:05:55.760
That's super cool that contributing to the project got you that position.
00:05:56.520 --> 00:05:59.440
It's like, I'm really interested in this thing and I get to work on it for a while.
00:05:59.540 --> 00:06:00.340
And all of a sudden they're like, well,
00:06:00.580 --> 00:06:02.560
what if we paid you to do it all the time?
00:06:02.980 --> 00:06:04.080
That's just great, right?
00:06:04.360 --> 00:06:04.580
Yeah,
00:06:04.760 --> 00:06:10.560
it's really interesting that you start to contribute on open source and you get a job with that.
00:06:10.780 --> 00:06:15.020
That's something that all the open source contributors are hoping to.
00:06:15.280 --> 00:06:16.080
Good. Welcome to the show.
00:06:16.380 --> 00:06:19.360
I started out on Lispy MLE languages.
00:06:19.960 --> 00:06:22.520
So I'm a mathematician by training.
00:06:23.720 --> 00:06:29.060
I wrote my first Python code for undergraduate introduction to programming class.
00:06:29.520 --> 00:06:35.200
but then I didn't use it at all until I had to write an email schedule for the math seminar
00:06:35.780 --> 00:06:42.600
which was in Python 2.7 and I am as a mathematician I was very interested in
00:06:43.820 --> 00:06:50.360
math software to try to get software that does a good combination of like research level
00:06:51.250 --> 00:06:58.239
you know like high performance computing and also just like quick experiments and lets people
00:06:58.540 --> 00:07:01.780
figures step out. And I found out that mathematicians don't like to install software
00:07:02.320 --> 00:07:03.720
on their computer. They assume it won't work.
00:07:04.550 --> 00:07:05.100
Of course, a lot of...
00:07:05.100 --> 00:07:06.480
They still have scars from Fortran.
00:07:06.640 --> 00:07:06.920
That's why,
00:07:07.080 --> 00:07:07.200
probably.
00:07:08.000 --> 00:07:08.180
Yeah.
00:07:08.480 --> 00:07:08.840
And also,
00:07:09.100 --> 00:07:14.480
a lot of math software is made by mathematicians and it's not an easy thing to
00:07:14.580 --> 00:07:16.500
distribute software for other people to use.
00:07:16.720 --> 00:07:18.120
And so it's like they have something that works on
00:07:18.240 --> 00:07:21.000
their computer and they tell all their friends, oh, you should use this. And they say, nah,
00:07:21.160 --> 00:07:21.280
man.
00:07:22.380 --> 00:07:28.220
So that was how I got interested in WebAssembly. I mean, I first started by writing software in
00:07:28.240 --> 00:07:32.600
LaTeX because mathematicians already have LaTeX on their computer and they already have TechLive
00:07:32.610 --> 00:07:33.180
on their computer.
00:07:33.570 --> 00:07:36.100
And that's a package manager. It can just get your package onto their computer
00:07:36.280 --> 00:07:36.600
automatically.
00:07:37.140 --> 00:07:41.580
But like people just wouldn't use things that didn't come sort of connected with
00:07:41.720 --> 00:07:42.820
something they already had on their computer.
00:07:43.180 --> 00:07:45.600
And because browsers are a universal computing
00:07:45.820 --> 00:07:46.000
platform,
00:07:46.280 --> 00:07:50.760
you know, I watched the birth and death of JavaScript back in like 2014 or whatever.
00:07:51.280 --> 00:07:52.380
One of the best talks ever.
00:07:52.870 --> 00:07:53.300
So good.
00:07:53.700 --> 00:07:53.820
Yeah,
00:07:54.170 --> 00:07:54.300
yeah,
00:07:54.480 --> 00:07:54.880
it's so good.
00:07:55.430 --> 00:07:57.680
And so I was very excited about the idea of like,
00:07:57.900 --> 00:07:58.020
oh,
00:07:58.220 --> 00:08:00.400
we should just make the software work in WebAssembly
00:08:00.680 --> 00:08:01.540
and ship it to the browser.
00:08:01.810 --> 00:08:04.340
And then mathematicians won't be able to like complain
00:08:04.620 --> 00:08:06.700
that it's maybe takes some work to install.
00:08:08.000 --> 00:08:09.700
But then if you want to have like,
00:08:09.900 --> 00:08:10.040
you know,
00:08:10.300 --> 00:08:11.180
powerful math software,
00:08:11.600 --> 00:08:11.720
you know,
00:08:12.100 --> 00:08:14.140
I wrote all the linear algebra stuff in Rust,
00:08:14.720 --> 00:08:14.980
but then,
00:08:15.480 --> 00:08:15.600
you know,
00:08:16.380 --> 00:08:19.620
you don't really get that much control over it from Rust.
00:08:20.220 --> 00:08:23.080
And you can make a GUI, you can give people JavaScript,
00:08:23.580 --> 00:08:24.640
But, you know,
00:08:25.260 --> 00:08:33.260
JavaScript is really a bit anemic in terms of, you know, like, for instance, our logic have lots of tables of things that were indexed by, you know, tuples of integers.
00:08:34.099 --> 00:08:34.820
And like,
00:08:35.159 --> 00:08:35.380
you know,
00:08:35.700 --> 00:08:39.979
having a map in Python that is nicely indexed by tuples of integers is like,
00:08:40.159 --> 00:08:41.340
you know, you could do it in JavaScript.
00:08:41.560 --> 00:08:42.460
It's just it's just a pain.
00:08:42.820 --> 00:08:46.880
So I really wanted to get Python to be in my web application with everything else.
00:08:47.820 --> 00:08:52.920
And so I found out about Pyodine and I started messing around with it, but it was really buggy and didn't work very well.
00:08:53.260 --> 00:08:54.900
you know, I mean, it was a sort of technical,
00:08:55.400 --> 00:08:56.060
you know,
00:08:56.360 --> 00:08:57.040
like demonstration.
00:08:57.280 --> 00:08:58.080
I mean, it showed
00:08:58.200 --> 00:08:59.460
a lot of promise because,
00:08:59.940 --> 00:09:00.100
you know,
00:09:00.260 --> 00:09:02.820
there was NumPy there running in the browser.
00:09:03.580 --> 00:09:03.680
So,
00:09:03.980 --> 00:09:04.100
you know,
00:09:04.180 --> 00:09:05.760
these binary extensions were working.
00:09:06.400 --> 00:09:06.580
But,
00:09:07.320 --> 00:09:07.460
you know,
00:09:07.660 --> 00:09:09.680
Mike Dropeboom did like amazing work at
00:09:09.920 --> 00:09:14.900
Mozilla to get that working. And I mean, Mozilla really created this whole cool chain on top of it.
00:09:15.260 --> 00:09:15.720
Anyways,
00:09:15.980 --> 00:09:17.860
I can maybe say more about that later.
00:09:18.160 --> 00:09:21.279
But I found PyDyde and it was just a bit after
00:09:21.300 --> 00:09:26.160
mozilla killed the whole project so it wasn't you know um roman urchuk was like just barely keeping
00:09:26.200 --> 00:09:29.800
the lights on and i showed up and i was like here are all the things that are bad about what's
00:09:29.860 --> 00:09:35.640
currently going on it kind of expecting him to be like oh like you're an asshole go away but he was
00:09:35.680 --> 00:09:40.360
like oh well why don't you come fix those things and so so i so he made me into a maintainer it
00:09:40.540 --> 00:09:46.300
actually first took another math that i was working with on the same project uh dexter who who had some
00:09:46.440 --> 00:09:50.540
experience with open source and so he started contributing to fix the problems that i found i
00:09:50.560 --> 00:09:52.240
I was like, oh, I guess I can contribute to this.
00:09:53.340 --> 00:09:53.480
Yeah.
00:09:53.880 --> 00:09:56.680
That's a great way to handle somebody coming and say, I have these complaints.
00:09:56.940 --> 00:09:57.240
It's like,
00:09:57.660 --> 00:09:58.140
instead of saying,
00:09:58.520 --> 00:09:59.840
go away, it's like, you know what?
00:10:00.180 --> 00:10:01.100
Here's how you can fix them.
00:10:01.440 --> 00:10:01.620
Yeah,
00:10:01.840 --> 00:10:01.960
right.
00:10:02.120 --> 00:10:03.000
Yeah, very productive.
00:10:03.340 --> 00:10:03.540
Right.
00:10:03.640 --> 00:10:04.540
They weren't defensive at all.
00:10:04.660 --> 00:10:06.040
They were just like, great, we want this to be better.
00:10:06.440 --> 00:10:06.540
Like,
00:10:06.860 --> 00:10:08.460
if you want to make it better, please make it better.
00:10:09.420 --> 00:10:13.800
And so then I got a National Science Foundation postdoc for math.
00:10:14.220 --> 00:10:16.460
I said I would improve mathematical computing software.
00:10:16.680 --> 00:10:19.660
And so I ended up spending most of that postdoc working on Pyodide.
00:10:20.500 --> 00:10:26.460
And then when I was leaving the postdoc, I got hired to Anaconda to work on their PyScript stuff.
00:10:26.940 --> 00:10:28.260
And then about six months later,
00:10:28.560 --> 00:10:33.920
I got connected to Cloudflare and they were interested in me working on making Python workers exist.
00:10:34.300 --> 00:10:36.760
That was obviously a very fun project.
00:10:37.740 --> 00:10:37.820
Yeah,
00:10:38.000 --> 00:10:39.620
PyScript is such an interesting project.
00:10:40.380 --> 00:10:42.080
I don't know what the future holds for PyScript,
00:10:42.300 --> 00:10:43.840
but it's a very neat project.
00:10:44.280 --> 00:10:45.680
Yeah, it was really an interesting project.
00:10:46.080 --> 00:10:46.460
Actually,
00:10:46.780 --> 00:10:50.840
a lot of people first learned about running Python in the browser from PyScript,
00:10:51.090 --> 00:10:52.100
not from Pyodide.
00:10:52.520 --> 00:10:54.200
Yeah, it was a really interesting project.
00:10:54.540 --> 00:10:59.020
It's very unfortunate they turned into a maintenance mode recently, but they did a real great job.
00:10:59.020 --> 00:11:00.040
I know, it makes me sad.
00:11:02.020 --> 00:11:03.120
Maybe it's just taking a break.
00:11:03.320 --> 00:11:05.660
Maybe it'll come back in the future in some amazing form.
00:11:05.740 --> 00:11:12.300
I would love to see a React or a Vue alternative that just runs all on PyScript.
00:11:12.360 --> 00:11:12.500
But,
00:11:12.840 --> 00:11:16.380
you know, I don't think backed by Pyodide, backed by MicroPython,
00:11:16.840 --> 00:11:17.220
which would be,
00:11:17.640 --> 00:11:19.580
you know, I think a little more practical for web front end.
00:11:19.680 --> 00:11:22.640
But that is an alternate reality and a different thing that we're talking about.
00:11:22.780 --> 00:11:29.540
So let's begin maybe just a quick review of like running in the browser.
00:11:29.620 --> 00:11:33.120
So the goal of Pyodide is to run wherever WebAssembly runs.
00:11:33.580 --> 00:11:33.900
Primarily,
00:11:34.120 --> 00:11:34.640
that's the browser,
00:11:34.800 --> 00:11:35.840
though it doesn't have to be.
00:11:35.920 --> 00:11:39.380
You know, you can kind of treat WebAssembly a bit like a Docker type of thing, like an isolation.
00:11:39.380 --> 00:11:40.120
You can use the JavaScript.
00:11:40.340 --> 00:11:40.420
Right.
00:11:41.080 --> 00:11:47.840
So it does not work in WASM time or these other WebAssembly only run times, but it should work in any JavaScript run.
00:11:47.980 --> 00:11:50.220
I see. So I could run it locally if I had, say,
00:11:50.520 --> 00:11:51.740
Node or Bun or something like that, maybe?
00:11:52.040 --> 00:11:52.420
Absolutely.
00:11:52.740 --> 00:11:52.800
Yeah.
00:11:52.980 --> 00:11:53.760
Okay. That's interesting.
00:11:54.160 --> 00:11:57.480
So we have this WASM execution time,
00:11:58.280 --> 00:11:59.140
execution framework here.
00:11:59.620 --> 00:12:06.260
And the idea you all had is like, well, we have all these points of presence throughout the world with Cloudflare.
00:12:06.620 --> 00:12:07.500
How many places,
00:12:08.190 --> 00:12:10.820
how many spots does this run at? You all know.
00:12:10.880 --> 00:12:15.600
oh i don't know by heart there's like a website you can go on and tells you the
00:12:16.020 --> 00:12:22.140
all of them i think i think the number is above 350 yeah yeah it sounds like yeah so that puts
00:12:22.600 --> 00:12:29.560
10 tends to a hundreds on any given continent right so the idea is with these these kind of
00:12:29.600 --> 00:12:32.220
getting ahead of ourself a little bit but the idea is like well what if we could take this
00:12:32.740 --> 00:12:39.719
pyodide thing that is a miniature python runtime and put it really really close to all the users
00:12:39.720 --> 00:12:42.120
and execute it there instead of routing back,
00:12:42.480 --> 00:12:42.620
you know,
00:12:43.020 --> 00:12:45.460
somewhere in US East 1 or something like that, right?
00:12:45.680 --> 00:12:46.300
Yeah, precisely.
00:12:46.740 --> 00:12:51.360
I mean, you're giving the exact explanation
00:12:51.540 --> 00:12:54.840
that I think a lot of our, like, marketing people would give,
00:12:55.250 --> 00:12:55.720
which is great.
00:12:56.620 --> 00:12:56.820
Basically,
00:12:57.180 --> 00:12:57.260
yeah,
00:12:57.420 --> 00:12:57.560
like,
00:12:57.870 --> 00:13:00.220
you want as little latency as possible
00:13:00.250 --> 00:13:00.800
for your users,
00:13:01.000 --> 00:13:01.100
right?
00:13:01.130 --> 00:13:03.660
So you want to run Python code as close to them as possible,
00:13:03.810 --> 00:13:05.760
and this is a very great way to do that.
00:13:05.980 --> 00:13:07.620
Yeah, and it doesn't run, to be clear,
00:13:07.920 --> 00:13:13.640
what we're talking about does not run in the browser of users like Pyodide can.
00:13:13.920 --> 00:13:19.860
It runs in the edge nodes of Cloudflare that happen to be very near the users, right?
00:13:20.200 --> 00:13:23.680
So I think that's a big difference because it gives you access to an entire platform
00:13:24.280 --> 00:13:27.440
like data and queues and all that kind of stuff that we're going to talk about,
00:13:27.620 --> 00:13:27.680
right?
00:13:28.120 --> 00:13:31.600
The way I like to describe it is like Pyodide is kind of this crazy idea of like,
00:13:31.600 --> 00:13:33.360
we should put Python into the browser.
00:13:33.680 --> 00:13:35.680
And then Cloudflare is kind of this crazy idea of like,
00:13:35.680 --> 00:13:37.560
we should put the browser into the server.
00:13:38.060 --> 00:13:39.800
and so when you put Python into the browser
00:13:39.860 --> 00:13:41.020
and you put the browser in the server,
00:13:41.220 --> 00:13:42.880
that's a funny way of getting Python into the server.
00:13:43.200 --> 00:13:45.740
Yeah, as a mathematician by the transitive property,
00:13:46.120 --> 00:13:46.940
you click it all together.
00:13:47.340 --> 00:13:48.940
It sounds like a crazy idea though.
00:13:49.220 --> 00:13:49.460
Yeah.
00:13:50.040 --> 00:13:51.960
So let's talk PyDyde just for a minute
00:13:52.120 --> 00:13:53.080
before we dive in,
00:13:53.300 --> 00:13:55.140
now that people see where we're going with PyDyde.
00:13:55.360 --> 00:13:56.460
Let's talk about it a little bit
00:13:56.680 --> 00:13:57.620
because very recently,
00:13:57.980 --> 00:13:58.700
let's put some,
00:13:58.880 --> 00:13:59.500
one month ago,
00:14:00.100 --> 00:14:03.920
Hood and JU2 gave a talk at EuroPython,
00:14:04.220 --> 00:14:05.340
which I thought was really interesting.
00:14:05.560 --> 00:14:06.140
Python Everywhere,
00:14:06.320 --> 00:14:08.000
the state of Python on WebAssembly.
00:14:08.270 --> 00:14:09.780
So this is a more general,
00:14:10.000 --> 00:14:12.840
not just Cloudflare worker type of story,
00:14:13.060 --> 00:14:15.440
but give us an update.
00:14:15.610 --> 00:14:17.340
What is the state of Python on WebAssembly?
00:14:17.640 --> 00:14:18.440
Things are good.
00:14:20.340 --> 00:14:26.320
It feels like there is less and less stuff that's going wrong.
00:14:27.680 --> 00:14:31.219
So I have these Python enhancement proposals
00:14:31.220 --> 00:14:37.040
to try and rearrange the governance of our code
00:14:37.600 --> 00:14:40.780
so that it can live maybe more of the stuff
00:14:41.140 --> 00:14:42.560
in the CPython repository.
00:14:44.100 --> 00:14:46.580
But yeah, I mean, I remember just a few years ago
00:14:46.670 --> 00:14:48.560
that there were always like crazy problems
00:14:49.100 --> 00:14:53.040
and lots of confusing bugs.
00:14:53.580 --> 00:14:55.380
And it was like,
00:14:55.590 --> 00:14:55.780
yeah,
00:14:56.100 --> 00:14:57.440
like we got lots of bug reports
00:14:57.720 --> 00:14:58.700
that would just be like,
00:14:58.730 --> 00:15:00.040
I have no idea what to do with this.
00:15:01.260 --> 00:15:04.400
But it feels like we really polished it a lot.
00:15:04.700 --> 00:15:11.980
And I mean, especially Jay moved all of the package build system into external repositories.
00:15:12.560 --> 00:15:16.020
And so the package build system is much less causing us trouble,
00:15:16.400 --> 00:15:19.560
although it's still still causing us some residual trouble.
00:15:19.760 --> 00:15:23.380
But now we have the PEP that says we can upload packages to PyPI.
00:15:23.860 --> 00:15:30.760
So it really feels like it's kind of making this graceful landing and approaching something that, you know,
00:15:31.040 --> 00:15:34.100
it will always take maintenance to keep up with upstream Python,
00:15:34.520 --> 00:15:36.720
but I'm sort of feeling like
00:15:36.870 --> 00:15:39.660
it's taking less and less in addition to that, which is nice.
00:15:39.820 --> 00:15:42.140
What's the situation or the state
00:15:42.380 --> 00:15:47.460
with Pyodide and Python on WebAssembly in terms of being officially supported by the core
00:15:47.680 --> 00:15:48.580
developers of Python?
00:15:48.960 --> 00:15:54.320
I feel like it's gotten some sort of build support acknowledgement before they
00:15:54.720 --> 00:15:59.760
were willing to ship CPython that Python on WebAssembly also compiles. Is that right?
00:15:59.960 --> 00:16:00.460
Yeah,
00:16:00.650 --> 00:16:02.820
so, right, so Python,
00:16:03.480 --> 00:16:05.920
sorry, so the platform we have is called Emscripten, right?
00:16:06.170 --> 00:16:08.080
This is the Emscripten compiler tool chain,
00:16:08.650 --> 00:16:14.020
which is this incredible thing that is front end for Clang and ships.
00:16:14.920 --> 00:16:18.200
JavaScript system calls JavaScript implementation of a file system.
00:16:18.540 --> 00:16:22.520
It's like a JavaScript Musa Linux that Emscripten compiles to.
00:16:22.940 --> 00:16:29.380
And so we have to recommend that people go back and watch the birth and death of JavaScript because it tells the story so well, right?
00:16:29.480 --> 00:16:29.760
Yeah,
00:16:30.140 --> 00:16:31.520
it's one of the greatest videos ever,
00:16:31.740 --> 00:16:31.940
for sure.
00:16:32.860 --> 00:16:35.180
And so, okay, so Emscripten is the platform,
00:16:35.680 --> 00:16:39.600
and Emscripten is tier three supported upstream by Python.
00:16:40.900 --> 00:16:42.960
And what that means is that we,
00:16:43.180 --> 00:16:44.260
well, we run it in CI,
00:16:45.760 --> 00:16:46.240
and,
00:16:47.200 --> 00:16:48.260
you know, it's best effort,
00:16:48.540 --> 00:16:48.760
you know,
00:16:48.980 --> 00:16:50.140
people are allowed to break it,
00:16:50.400 --> 00:16:50.600
and,
00:16:50.940 --> 00:16:52.360
like, I come back and fix it.
00:16:54.080 --> 00:16:56.060
And it's not a release block,
00:16:56.060 --> 00:16:58.640
or they, in fact, do not make releases for Emscripten.
00:16:59.620 --> 00:17:09.980
The reason they don't make releases for Emscripten is because they don't have really a version of like the OS module or for Emscripten.
00:17:09.980 --> 00:17:13.620
So they can't really do IO very much.
00:17:14.100 --> 00:17:15.660
They can't make requests.
00:17:16.459 --> 00:17:18.140
You know, they can't do HTTP stuff.
00:17:18.600 --> 00:17:20.260
They can't receive user input.
00:17:20.459 --> 00:17:22.560
And so in my opinion,
00:17:22.980 --> 00:17:25.920
if we build these executables,
00:17:26.560 --> 00:17:29.860
but no one would want to use it as it is built upstream.
00:17:30.110 --> 00:17:31.240
And so I have this proposal,
00:17:31.410 --> 00:17:32.740
which is PEP 818,
00:17:32.930 --> 00:17:36.440
which I just submitted a few days ago for review by the steering council,
00:17:36.740 --> 00:17:47.920
which is supposed to rectify the situation and make it so that we can have basically useful inscriptive iPhone binaries.
00:17:48.420 --> 00:17:48.620
Okay,
00:17:48.960 --> 00:17:50.980
so let me read the title of PEP for folks.
00:17:51.160 --> 00:17:52.240
It's PEP 818,
00:17:52.520 --> 00:17:56.220
adding the core of the Pyodide foreign function interface to Python.
00:17:56.720 --> 00:18:00.620
Is this a little bit like the ABI interface or CFFI, something like that?
00:18:00.940 --> 00:18:04.820
It's a little bit like CFFI or C types.
00:18:05.180 --> 00:18:05.400
You know,
00:18:05.700 --> 00:18:06.260
the package,
00:18:06.460 --> 00:18:09.420
the top level import is going to be JS types,
00:18:09.600 --> 00:18:10.700
which is following C types.
00:18:11.700 --> 00:18:12.340
And yeah,
00:18:12.500 --> 00:18:16.720
like the point of it is to allow calling JavaScript functions from Python,
00:18:16.840 --> 00:18:21.660
which is important because basically all functionality in a JavaScript runtime goes
00:18:21.680 --> 00:18:22.280
through JavaScript,
00:18:22.480 --> 00:18:24.860
just like the way all functionality in Linux goes through C.
00:18:25.060 --> 00:18:25.220
Okay,
00:18:25.660 --> 00:18:25.860
excellent.
00:18:26.260 --> 00:18:28.340
And this is in draft, might be out next year,
00:18:28.720 --> 00:18:28.820
maybe?
00:18:29.980 --> 00:18:33.280
So I just submitted it for consideration.
00:18:33.920 --> 00:18:37.200
So hopefully in the next couple months,
00:18:37.380 --> 00:18:39.960
the steering council will make a decision on it.
00:18:40.120 --> 00:18:41.400
But you also have,
00:18:41.800 --> 00:18:43.480
and this one is accepted,
00:18:43.920 --> 00:18:45.040
is this is a big deal,
00:18:45.460 --> 00:18:46.560
PEP783,
00:18:46.820 --> 00:18:47.940
the Emscripten
00:18:48.200 --> 00:18:48.540
packaging.
00:18:48.780 --> 00:18:52.000
I think packaging is having a big moment in the Python space.
00:18:52.220 --> 00:18:54.580
We just have the very first packaging council,
00:18:55.100 --> 00:18:55.200
right?
00:18:55.280 --> 00:18:56.280
That election that came out.
00:18:56.280 --> 00:19:01.300
And you talked about Jay doing a bunch of work to get the build of the packages other
00:19:01.520 --> 00:19:01.660
places.
00:19:02.040 --> 00:19:06.940
I'm very excited about the packaging council because what they had before was not that functional.
00:19:08.500 --> 00:19:11.980
Whereas the people on the packaging steering council, I think they're going to do a really good job.
00:19:12.420 --> 00:19:12.480
Yeah,
00:19:12.660 --> 00:19:12.860
yeah, yeah.
00:19:12.980 --> 00:19:13.480
One of the great people.
00:19:13.900 --> 00:19:15.900
Jay, what are your thoughts on this whole packaging story?
00:19:16.080 --> 00:19:17.640
It sounds like you did some work on it as well.
00:19:17.960 --> 00:19:23.940
Yeah, there's a long history about supporting packages in Pyodide and Python in the browser.
00:19:24.320 --> 00:19:26.240
And that 7.83,
00:19:26.460 --> 00:19:31.200
7.83 unscrupulous packaging is really a lifesaver for us.
00:19:31.460 --> 00:19:34.400
Because so from the beginning of the Pyodide,
00:19:34.530 --> 00:19:38.980
we wanted to support packages like NumPy or SciPy or MatBotlib,
00:19:39.140 --> 00:19:41.160
all those scientific Python packages
00:19:41.330 --> 00:19:43.780
that needs to be cross-compiled to WebAssembly
00:19:43.850 --> 00:19:46.160
because they have C codes.
00:19:46.160 --> 00:19:49.660
So if the package only contains the Python code,
00:19:49.780 --> 00:19:52.440
we can just run it because there's nothing needs to compile.
00:19:52.640 --> 00:19:53.360
They're all interpreted.
00:19:53.550 --> 00:19:57.660
But if the package has a C or C++ or Rust code inside,
00:19:58.120 --> 00:20:00.740
they need to be compiled into a platform,
00:20:01.160 --> 00:20:03.400
which is for us WebAssembly or MScripten.
00:20:03.800 --> 00:20:07.580
So at the beginning and until 2025,
00:20:08.160 --> 00:20:12.080
we had to cross-compile and build all the packages
00:20:12.460 --> 00:20:15.380
in Pyodide CI to run them inside Pyodide.
00:20:15.420 --> 00:20:19.539
And I think last year we had around 300 packages
00:20:20.200 --> 00:20:22.820
that needs to be built in our repository.
00:20:22.980 --> 00:20:24.980
And it took like three or four hours
00:20:25.120 --> 00:20:27.420
to build all those packages in our CI.
00:20:27.680 --> 00:20:32.560
So even if you like make a little like one line change in Pyodide
00:20:32.570 --> 00:20:35.680
that needs to run CI for like three and four hours to build.
00:20:35.920 --> 00:20:38.080
And it was very flacky because,
00:20:38.540 --> 00:20:38.660
well,
00:20:38.880 --> 00:20:39.000
you know,
00:20:39.130 --> 00:20:44.180
Python packaging system is running some like Python codes in real time
00:20:44.680 --> 00:20:46.040
and it's very fragile.
00:20:46.600 --> 00:20:48.320
So like CI was always breaking.
00:20:48.770 --> 00:20:55.340
So we really hope to make things done in package themselves.
00:20:55.900 --> 00:20:58.820
We don't want it to maintain all the packages ourselves.
00:20:59.020 --> 00:20:59.680
So we want,
00:20:59.920 --> 00:21:00.320
for instance,
00:21:00.560 --> 00:21:05.360
NumPy to build Pyodide wheels themselves and SciPy too.
00:21:05.880 --> 00:21:09.980
And so that was that PAP 783.
00:21:10.360 --> 00:21:17.860
And we had one more years of discussions to make it accepted thanks to a lot of work by Hood.
00:21:18.080 --> 00:21:24.659
And we also standardized a lot of our build system so that people can actually easily build their packages
00:21:26.080 --> 00:21:27.920
into a PyPI scripting platform
00:21:28.300 --> 00:21:31.180
without setting up a lot of things in their machine.
00:21:31.600 --> 00:21:33.780
They can actually just use a cibuildwheel
00:21:34.100 --> 00:21:35.840
to build PyMD builds in their CI.
00:21:36.140 --> 00:21:38.880
They just need to add one PyMD platform and that's it.
00:21:38.930 --> 00:21:42.160
They can build PyMDs and builds in their CI.
00:21:42.690 --> 00:21:43.800
And that makes such a big difference,
00:21:44.160 --> 00:21:44.260
right?
00:21:44.400 --> 00:21:47.260
Because if you all were trying to take everyone else's projects
00:21:47.390 --> 00:21:48.960
and build it, I can't even imagine.
00:21:49.310 --> 00:21:50.780
I mean, it's one thing that's pure Python,
00:21:51.220 --> 00:21:53.219
but if it's C or Rust
00:21:53.540 --> 00:21:55.580
and it doesn't compile to WebAssembly correctly,
00:21:55.680 --> 00:21:56.560
what do you do, you know?
00:21:57.020 --> 00:22:00.280
Right, well, we have this horrifying compiler wrapper
00:22:00.480 --> 00:22:02.100
that rewrites the compiler arguments
00:22:02.300 --> 00:22:03.400
to fix all the problems.
00:22:03.980 --> 00:22:05.280
Right, we still have that.
00:22:05.940 --> 00:22:07.480
We still have it, it's not going anywhere.
00:22:07.960 --> 00:22:09.320
Cross compiling is still not easy,
00:22:09.480 --> 00:22:12.540
but it's all abstracted inside our build system.
00:22:12.660 --> 00:22:14.280
I mean, people will still face some issues,
00:22:14.860 --> 00:22:16.860
but like most of the packages now just build,
00:22:17.200 --> 00:22:17.720
which is awesome.
00:22:18.000 --> 00:22:20.399
Yeah, this is one concern I have
00:22:21.080 --> 00:22:27.060
been going back and forth with Jay about is that there's still a lot of compiler regressions.
00:22:27.420 --> 00:22:27.480
So
00:22:27.540 --> 00:22:30.280
like when we were doing the Python 3.15 update,
00:22:31.480 --> 00:22:33.140
you know, and I was trying to get up to the most
00:22:33.280 --> 00:22:34.980
recent version of mscripten. And it was like,
00:22:35.260 --> 00:22:37.460
you know, I had to go up like 10 versions,
00:22:37.820 --> 00:22:38.180
10 releases,
00:22:38.480 --> 00:22:42.060
and almost every single one of them had like some weird regression in it.
00:22:42.720 --> 00:22:44.179
And that broke builds of
00:22:44.200 --> 00:22:44.700
some package.
00:22:45.360 --> 00:22:51.120
And so what's really still the big difficulty for us is that we need to make sure
00:22:51.120 --> 00:22:52.420
that we find these problems.
00:22:53.180 --> 00:22:56.800
And then I can put fixes for them into our compiler tool chain,
00:22:57.260 --> 00:22:58.820
our tooling that says like,
00:22:59.000 --> 00:22:59.220
oh,
00:22:59.800 --> 00:23:01.460
there's this weird bug in the compiler.
00:23:01.680 --> 00:23:04.040
But if we edit the compiler
00:23:04.280 --> 00:23:04.700
arguments,
00:23:04.980 --> 00:23:06.860
or we rewrite something a little bit,
00:23:07.020 --> 00:23:10.180
then it will go away and the users won't see it.
00:23:10.280 --> 00:23:11.960
or we can go up to the compiler and say,
00:23:12.030 --> 00:23:12.160
like,
00:23:12.360 --> 00:23:12.700
you know,
00:23:12.960 --> 00:23:13.200
hey,
00:23:13.380 --> 00:23:14.140
like, let's patch this.
00:23:14.410 --> 00:23:14.540
Or,
00:23:14.820 --> 00:23:16.580
you know, I mean, I'm a maintainer of Unscripted now,
00:23:16.690 --> 00:23:17.080
so I can,
00:23:17.780 --> 00:23:19.180
you know, help drive it
00:23:19.390 --> 00:23:20.780
into a non-buggy direction.
00:23:21.400 --> 00:23:25.620
But my concern is very much that we could specify
00:23:26.510 --> 00:23:28.560
an ABI and a platform
00:23:29.000 --> 00:23:31.220
and then not find out that it's broken
00:23:31.700 --> 00:23:34.560
until downstream package maintainers
00:23:34.700 --> 00:23:35.640
start trying to use it.
00:23:35.880 --> 00:23:39.199
And so that's the one sort of big issue
00:23:39.220 --> 00:23:40.520
that we need to figure out is like,
00:23:40.620 --> 00:23:43.160
how do we make sure that we have confidence
00:23:43.720 --> 00:23:44.760
in our platform?
00:23:45.180 --> 00:23:47.120
Which I think basically still means
00:23:47.140 --> 00:23:48.920
we have to carry builds for a bunch of packages
00:23:49.140 --> 00:23:50.800
just to make sure that we cover
00:23:51.220 --> 00:23:52.720
like all the different weird things
00:23:52.900 --> 00:23:54.160
that different packages rely on.
00:23:54.660 --> 00:23:57.860
Compilers have an amazing amount of surface area
00:23:58.240 --> 00:24:00.260
in terms of like what is expected
00:24:00.320 --> 00:24:01.320
for them to behave like.
00:24:01.460 --> 00:24:02.880
Dominic, were you going to jump in and say something?
00:24:03.860 --> 00:24:05.060
Yeah, I was just going to say that
00:24:05.220 --> 00:24:08.019
I think the main thing that this packaging PEP
00:24:08.040 --> 00:24:09.860
really brings is that it does actually
00:24:10.140 --> 00:24:10.320
enable
00:24:11.660 --> 00:24:13.700
packagers and maintainers of packages
00:24:13.940 --> 00:24:15.100
to actually build for
00:24:16.060 --> 00:24:17.600
WebAssembly and for Pyodide, right?
00:24:17.630 --> 00:24:18.800
And it's not really,
00:24:19.100 --> 00:24:19.720
like, it doesn't
00:24:19.730 --> 00:24:21.500
really scale for Pyodide to be
00:24:21.820 --> 00:24:22.680
doing all of that themselves.
00:24:24.120 --> 00:24:25.780
So this is, like, really powerful to
00:24:25.810 --> 00:24:27.300
help spread the
00:24:27.780 --> 00:24:29.480
load and help all these, you know,
00:24:29.650 --> 00:24:31.700
the long tail of packages work
00:24:31.800 --> 00:24:33.640
on Pyodide. So much. I had pulled
00:24:33.650 --> 00:24:35.600
up PyPI here, just as
00:24:35.650 --> 00:24:38.000
I was going to just bring it up. We're coming up
00:24:38.020 --> 00:24:44.480
million packages it doesn't make sense for you all try to bring this in into it yourself so if it's
00:24:44.540 --> 00:24:50.700
possible for whoever wants to be on mscripten and pyodide and so on to just do that by setting up
00:24:50.980 --> 00:24:54.800
ci build wheel and setting a wheel they're basically like it's awesome right yeah yeah
00:24:55.040 --> 00:25:00.600
off the cuff i think only about five percent of those packages have any uh c c plus plus or rust
00:25:00.660 --> 00:25:06.240
in them so uh luckily most of them are pure python and don't yeah that's trying to track what which
00:25:06.260 --> 00:25:13.160
packages have Python scripting wheels now. So there is a website called rwepap783yet,
00:25:13.320 --> 00:25:15.480
which is created by another Pyodag maintainer.
00:25:15.880 --> 00:25:19.440
And it's already a lot of packages have Python
00:25:19.560 --> 00:25:21.920
scripting wheels, and some of them we are still maintaining ourselves.
00:25:22.400 --> 00:25:23.120
But it's,
00:25:23.420 --> 00:25:23.780
yeah,
00:25:24.860 --> 00:25:29.820
like, majority of the Python applications will depend on those top 500 Python packages.
00:25:30.020 --> 00:25:30.220
So you're
00:25:30.320 --> 00:25:31.620
trying to support those packages.
00:25:32.340 --> 00:25:35.240
Yeah, so you can look through and see all the popular ones and go,
00:25:35.420 --> 00:25:35.440
Okay,
00:25:35.640 --> 00:25:36.960
yeah, this is great.
00:25:38.380 --> 00:25:41.920
The yellow ones are those packages that are not supported yet.
00:25:42.280 --> 00:25:47.040
And the green ones are those that have the fence wheels in PyPI.
00:25:47.360 --> 00:25:50.900
And the blue ones are those we are still building ourselves.
00:25:51.560 --> 00:25:51.960
Oh, interesting.
00:25:52.140 --> 00:25:52.820
That's what the blue means.
00:25:52.840 --> 00:25:52.960
Okay.
00:25:53.320 --> 00:25:57.600
And then some of them are just none for their wheel designation because they're pure Python.
00:25:58.020 --> 00:25:59.060
Setup tools is pure Python.
00:25:59.560 --> 00:25:59.820
Right.
00:26:00.760 --> 00:26:03.440
I guess it's probably worth pointing out that you all talked about this before,
00:26:03.800 --> 00:26:05.260
but just because something's pure Python
00:26:05.620 --> 00:26:08.200
doesn't mean that it's going to work on Pyodide, right?
00:26:08.480 --> 00:26:10.520
There's just parts that are missing
00:26:10.800 --> 00:26:12.460
because the runtime themselves are like,
00:26:12.820 --> 00:26:12.880
yeah,
00:26:13.040 --> 00:26:14.000
your OS thing, no.
00:26:14.440 --> 00:26:15.960
This comes from a browser or whatever,
00:26:16.200 --> 00:26:16.320
right?
00:26:16.540 --> 00:26:18.740
Or your raw socket support,
00:26:19.070 --> 00:26:19.740
I don't know about you.
00:26:20.080 --> 00:26:20.560
Yeah,
00:26:20.780 --> 00:26:20.960
right.
00:26:21.760 --> 00:26:24.700
If the package is depending on some native things
00:26:24.960 --> 00:26:28.500
like threadings or multi-processing or self-processing,
00:26:28.640 --> 00:26:31.600
and the native sockets will not basically work
00:26:31.720 --> 00:26:33.560
and browser Piodies.
00:26:33.900 --> 00:26:35.560
If you're running in Cloudflare Workers
00:26:35.900 --> 00:26:36.500
or Node.js,
00:26:36.900 --> 00:26:37.580
they will
00:26:37.860 --> 00:26:39.580
work because Node.js have access
00:26:39.780 --> 00:26:41.540
to some of them and still
00:26:42.040 --> 00:26:43.640
threadings or sub-processes are not
00:26:43.880 --> 00:26:44.000
working,
00:26:44.240 --> 00:26:45.640
but some of them will work
00:26:45.860 --> 00:26:47.480
depending on the platform you're running in Piodies.
00:26:47.820 --> 00:26:48.720
Does async.io work?
00:26:50.360 --> 00:26:51.720
That was a
00:26:51.760 --> 00:26:53.460
big project when I first started maintaining
00:26:53.660 --> 00:26:55.560
Piodies was to make async.io work
00:26:55.880 --> 00:26:57.560
because everything in a
00:26:57.680 --> 00:26:58.460
browser is async.
00:26:58.940 --> 00:27:02.520
So when there wasn't a good asyncio story for Pyodide,
00:27:02.570 --> 00:27:04.100
it was like really rough to use it
00:27:04.190 --> 00:27:05.720
because you had to just like.then,
00:27:05.880 --> 00:27:06.520
.then, you know.
00:27:06.800 --> 00:27:08.300
Yeah, callback, callback, callback,
00:27:08.460 --> 00:27:08.520
right?
00:27:09.420 --> 00:27:11.060
And, you know, at least in JavaScript,
00:27:11.320 --> 00:27:12.640
a lambda can have like,
00:27:12.820 --> 00:27:14.040
you know, a multi-line body.
00:27:14.390 --> 00:27:16.460
And so like lambdas are not that bad in JavaScript,
00:27:16.630 --> 00:27:17.160
whereas in Python,
00:27:17.430 --> 00:27:18.360
like lambdas suck.
00:27:18.560 --> 00:27:19.680
So you have to do like death,
00:27:19.850 --> 00:27:20.280
like a thing,
00:27:20.330 --> 00:27:21.500
and then put it, it's like.
00:27:21.720 --> 00:27:24.720
I wonder if Python should have had multi-line lambdas.
00:27:25.120 --> 00:27:26.900
I do kind of like them for.
00:27:27.130 --> 00:27:28.380
I think it should have actually been.
00:27:28.800 --> 00:27:30.520
and then it kind of went to line land.
00:27:31.559 --> 00:27:32.800
I think curly braces are
00:27:33.140 --> 00:27:33.540
the way.
00:27:35.179 --> 00:27:37.240
Oh, you're going to cause a fight.
00:27:37.340 --> 00:27:38.400
The developers would disagree with that.
00:27:40.340 --> 00:27:41.220
If I have curly braces,
00:27:41.300 --> 00:27:42.640
I can have multi-line lambdas
00:27:42.880 --> 00:27:43.660
that I care way more about.
00:27:44.420 --> 00:27:46.420
You can have multi-line lambdas without
00:27:46.900 --> 00:27:47.820
curly braces as well.
00:27:48.140 --> 00:27:49.720
But no one's ever figured out the syntax.
00:27:49.940 --> 00:27:50.800
That's why it doesn't exist.
00:27:51.420 --> 00:27:52.160
They have,
00:27:52.400 --> 00:27:53.580
actually. There are languages that do it.
00:27:54.460 --> 00:27:54.860
Backslash.
00:27:55.480 --> 00:27:56.280
Backslashes, come on.
00:27:56.860 --> 00:27:59.740
It has to fit with the existing syntax of Python.
00:28:00.580 --> 00:28:01.860
So if you designed a new language,
00:28:02.280 --> 00:28:03.540
you could maybe make it work.
00:28:03.980 --> 00:28:05.320
I don't think we're going to be able to
00:28:06.220 --> 00:28:08.860
completely solve this curly braces are not problem.
00:28:09.440 --> 00:28:12.140
But Hood, I expected parentheses from you
00:28:12.360 --> 00:28:13.140
as a Lisp person,
00:28:13.320 --> 00:28:13.660
just parentheses,
00:28:13.900 --> 00:28:14.080
parentheses,
00:28:14.320 --> 00:28:14.540
parentheses,
00:28:14.740 --> 00:28:14.840
parentheses.
00:28:14.920 --> 00:28:16.120
I'm looking with parentheses too.
00:28:17.080 --> 00:28:17.500
I don't object.
00:28:18.840 --> 00:28:20.300
Lisp also can have multi-line lab.
00:28:21.180 --> 00:28:22.860
I can't do all the parentheses in Lisp.
00:28:23.160 --> 00:28:24.160
It's not going to work for me.
00:28:24.400 --> 00:28:25.400
What if you had new syntax?
00:28:26.620 --> 00:28:29.020
I do think there's interesting new syntax that can be added.
00:28:29.700 --> 00:28:33.680
We've got the no coalescing or non coalescing operators
00:28:34.100 --> 00:28:36.500
and that kind of stuff possibly coming to Python.
00:28:37.260 --> 00:28:39.260
There will be things, but I don't think multi-line lambdas
00:28:39.260 --> 00:28:39.980
are going to be one of them.
00:28:40.280 --> 00:28:42.060
All right, let's talk about,
00:28:42.500 --> 00:28:43.660
we talked about a little bit,
00:28:43.660 --> 00:28:44.900
but let's go ahead and just talk a bit about
00:28:45.740 --> 00:28:47.160
edge workers in general.
00:28:47.480 --> 00:28:50.660
Because we talked about you've got over 300 points of presence.
00:28:50.880 --> 00:28:51.800
They're all near the users.
00:28:52.040 --> 00:28:53.240
That totally makes sense.
00:28:53.640 --> 00:28:57.500
but maybe compare and contrast this with like running on a VIP,
00:28:57.720 --> 00:29:01.660
just a virtual server or in Kubernetes or even serverless.
00:29:01.860 --> 00:29:03.980
Because to me, it feels kind of serverless-like,
00:29:04.240 --> 00:29:04.600
but not.
00:29:04.880 --> 00:29:05.900
I mean, it is serverless,
00:29:06.080 --> 00:29:06.600
I would say.
00:29:06.880 --> 00:29:07.820
What makes you think it's not?
00:29:08.120 --> 00:29:09.940
Well, a traditional serverless, I guess.
00:29:10.140 --> 00:29:11.480
You're right, it is serverless.
00:29:11.560 --> 00:29:14.460
I'm thinking like AWS Lambda and that kind of.
00:29:14.780 --> 00:29:15.040
Yeah.
00:29:15.320 --> 00:29:18.840
So in my mind, AWS Lambda runs in a data center.
00:29:19.060 --> 00:29:24.240
Like my Lambdas are set to run in US East 1 or in Frankfurt or something like that.
00:29:24.400 --> 00:29:25.640
And in that way, it's not the same.
00:29:25.880 --> 00:29:30.720
I feel like these words like edge and serverless and cloud are all more like marketing terms
00:29:31.000 --> 00:29:31.960
than like technical terms.
00:29:32.200 --> 00:29:34.720
And so that leaves some vagueness about what exactly they mean.
00:29:35.100 --> 00:29:36.740
Yeah, I would actually consider,
00:29:37.540 --> 00:29:41.920
I mean, workers in general to be more serverless than AWS Lambda.
00:29:42.260 --> 00:29:42.740
I mean...
00:29:42.960 --> 00:29:43.300
I do too.
00:29:43.620 --> 00:29:43.940
I do too.
00:29:44.160 --> 00:29:44.320
Yeah.
00:29:44.700 --> 00:29:49.520
Just because you don't have to worry about where you're placing your workers.
00:29:50.230 --> 00:29:52.540
They just show up wherever your users are, which is great.
00:29:52.760 --> 00:29:55.600
I think they're more serverless than Lambda as well.
00:29:55.740 --> 00:30:00.700
The only thing is that Lambda claimed the term serverless before,
00:30:01.320 --> 00:30:01.460
right?
00:30:01.510 --> 00:30:04.160
And so I think it's worth a little bit of a compare and contrast.
00:30:04.870 --> 00:30:06.940
So I'm a user I've written,
00:30:07.190 --> 00:30:09.880
or I'm a user I'm consuming in API,
00:30:10.190 --> 00:30:10.540
open up,
00:30:10.760 --> 00:30:11.060
I don't know,
00:30:11.220 --> 00:30:12.280
React front-end app,
00:30:12.560 --> 00:30:16.180
and it says, I need to do my work. I want to do it close to you.
00:30:16.360 --> 00:30:16.480
So
00:30:16.960 --> 00:30:19.900
what happens next? How do these things work? Well,
00:30:20.400 --> 00:30:22.280
you connect to your nearest point of presence.
00:30:22.920 --> 00:30:26.100
That nearest point of presence has the worker's runtime running on it.
00:30:26.520 --> 00:30:27.980
That worker's runtime has
00:30:28.220 --> 00:30:28.760
v8 on it,
00:30:29.100 --> 00:30:32.620
and v8 runs Pyodide in WebAssembly.
00:30:32.860 --> 00:30:33.060
Yeah.
00:30:33.480 --> 00:30:34.360
But as a developer,
00:30:34.530 --> 00:30:35.280
I don't make that
00:30:35.420 --> 00:30:35.560
choice,
00:30:35.820 --> 00:30:38.620
right? It's like a dynamic DNS choice that says,
00:30:38.800 --> 00:30:40.140
I know you asked for,
00:30:40.450 --> 00:30:40.860
I don't know,
00:30:41.200 --> 00:30:43.220
worker.collectifair.com slash whatever,
00:30:43.440 --> 00:30:48.100
but you actually get Southeast Asia in this location.
00:30:48.640 --> 00:30:50.500
And that's just kind of the magic of CDNs, right?
00:30:50.880 --> 00:30:51.000
Yeah.
00:30:51.300 --> 00:30:51.780
Okay.
00:30:52.300 --> 00:30:54.220
So let's talk this back up.
00:30:54.420 --> 00:30:57.980
I always describe this as being like a CDN,
00:30:58.140 --> 00:30:59.580
except for instead of with static assets,
00:30:59.840 --> 00:31:03.480
it distributes programs and then runs the programs on your data.
00:31:03.840 --> 00:31:04.020
Yeah.
00:31:04.520 --> 00:31:04.840
Okay.
00:31:04.940 --> 00:31:06.740
So let's talk about a deployment.
00:31:07.080 --> 00:31:08.880
Do I deploy my Python files?
00:31:09.200 --> 00:31:13.040
Do I do a local build and get a WebAssembly thing that I upload to you?
00:31:13.300 --> 00:31:13.760
How does that work?
00:31:14.260 --> 00:31:16.340
You don't build any WebAssembly things yourself.
00:31:16.660 --> 00:31:19.420
Like all the WebAssembly things are already pre-built.
00:31:19.920 --> 00:31:23.840
So the deploying Python workers is basically you write some Python codes.
00:31:24.100 --> 00:31:26.900
And you need to, if you're using some Python packages as dependencies,
00:31:27.240 --> 00:31:29.100
you need to install them through uv.
00:31:29.380 --> 00:31:33.840
So uv has a support for like installing Python packages
00:31:33.900 --> 00:31:36.120
that are built for WebAssembly into your local files.
00:31:36.260 --> 00:31:38.500
Of course, you cannot run it inside your local machine.
00:31:38.760 --> 00:31:41.820
like you'll only have like a native Python interpreter,
00:31:42.030 --> 00:31:43.420
or you can use Pyodite to run it.
00:31:44.240 --> 00:31:44.760
So basically,
00:31:45.150 --> 00:31:46.980
we like compress all those,
00:31:47.340 --> 00:31:49.140
your Python applications and packages
00:31:49.530 --> 00:31:51.500
into a Cloudflare web server,
00:31:51.670 --> 00:31:52.980
and it's distributed around the world.
00:31:53.540 --> 00:31:56.160
And the Cloudflare runtime will like download the application
00:31:56.510 --> 00:31:58.780
and run it inside Pyodite and Cloudflare runtime.
00:31:59.180 --> 00:31:59.780
Yeah, awesome.
00:32:00.240 --> 00:32:01.320
What's the local dev story?
00:32:01.370 --> 00:32:02.840
Now, I hadn't really thought about that before,
00:32:03.080 --> 00:32:05.320
but I want to debug it, play with it.
00:32:05.640 --> 00:32:05.860
Yeah,
00:32:06.020 --> 00:32:06.140
so...
00:32:06.160 --> 00:32:07.120
I push it up to...
00:32:07.120 --> 00:32:07.440
Yeah, go ahead.
00:32:07.740 --> 00:32:08.180
Go ahead, Dominic.
00:32:08.800 --> 00:32:09.800
Yeah, so I mean,
00:32:10.200 --> 00:32:14.480
part of the worker's runtime is open source as worker D,
00:32:14.910 --> 00:32:15.720
if you want to look it up,
00:32:15.900 --> 00:32:16.280
it's on GitHub.
00:32:17.550 --> 00:32:19.580
And you basically run that locally.
00:32:19.980 --> 00:32:25.920
I mean, we have like a CLI that wraps it for you. So it's nice and easy called Wrangler.
00:32:26.670 --> 00:32:28.720
But we're moving to CF now as well.
00:32:29.440 --> 00:32:30.240
But basically,
00:32:31.140 --> 00:32:32.740
you just you just run it locally,
00:32:32.980 --> 00:32:35.720
you you edit the files of your worker,
00:32:36.300 --> 00:32:37.380
they get reloaded automatically.
00:32:38.840 --> 00:32:39.840
as you edit them,
00:32:40.090 --> 00:32:41.980
you just send requests locally and see what happens.
00:32:42.500 --> 00:32:42.680
Okay.
00:32:42.880 --> 00:32:43.180
Yeah,
00:32:43.360 --> 00:32:46.940
I'll be sure to link to the WorkerD project so people can download and install it.
00:32:46.940 --> 00:32:48.280
I'm sure it's in your quick start, though, right?
00:32:48.580 --> 00:32:48.640
Yeah.
00:32:48.940 --> 00:32:54.380
I think the very cool part of the Cloud for Worker's runtime platform is that the WorkerD is open source.
00:32:54.590 --> 00:32:59.920
So basically, you can run the same code in the same runtime in your local machine and the prods.
00:33:00.090 --> 00:33:02.660
You can test everything that happens in prod in your local machine.
00:33:03.040 --> 00:33:03.260
Interesting.
00:33:03.540 --> 00:33:07.100
So this really is what runs on the edge when stuff happens,
00:33:07.380 --> 00:33:08.480
but you can just run it locally as well.
00:33:08.750 --> 00:33:09.120
Yeah, exactly.
00:33:09.760 --> 00:33:10.980
Yeah, I mean, that's pretty unique,
00:33:11.240 --> 00:33:11.340
right?
00:33:11.440 --> 00:33:13.020
Because if I was doing Lambda
00:33:13.480 --> 00:33:16.160
or I was doing EKS or something like that,
00:33:16.580 --> 00:33:17.580
it's not the same.
00:33:17.860 --> 00:33:19.540
I can install a Kubernetes cluster
00:33:19.920 --> 00:33:20.900
and run pods and stuff,
00:33:21.000 --> 00:33:22.360
but that's not the same as running
00:33:22.600 --> 00:33:24.740
in Amazon's Kubernetes service.
00:33:25.260 --> 00:33:27.040
And this sounds like it kind of is,
00:33:27.180 --> 00:33:27.960
which is pretty interesting.
00:33:28.300 --> 00:33:29.960
So let's talk about the platform a bit
00:33:30.140 --> 00:33:30.460
because this,
00:33:30.700 --> 00:33:33.180
I was a little bit unsure of,
00:33:33.400 --> 00:33:34.860
or just don't have a ton of experience.
00:33:35.280 --> 00:33:36.920
So it's one thing to run Python,
00:33:37.000 --> 00:33:39.660
on a point of presence and point sort of thing.
00:33:40.020 --> 00:33:40.780
But databases,
00:33:41.320 --> 00:33:43.460
is the database got a little bit my data?
00:33:43.600 --> 00:33:45.660
You know, I connect halfway around the world to Postgres
00:33:45.790 --> 00:33:48.240
and is that maybe not as good?
00:33:48.670 --> 00:33:50.540
So there's a bunch of interesting things as well.
00:33:50.860 --> 00:33:54.880
And so you all like numbering for your D1,
00:33:55.100 --> 00:33:55.800
R2 and so on.
00:33:56.140 --> 00:33:59.680
But I have this crazy fascination with SQLite right now.
00:33:59.730 --> 00:34:02.260
So this is especially interesting to me.
00:34:03.000 --> 00:34:04.719
So let's talk about some of these building blocks
00:34:04.720 --> 00:34:07.700
that not just Python workers use, but all of them.
00:34:07.780 --> 00:34:08.659
But at the same time,
00:34:08.860 --> 00:34:10.340
they're here for the Python workers now.
00:34:10.540 --> 00:34:11.659
And so that's pretty interesting.
00:34:12.020 --> 00:34:14.179
Who wants to introduce D1 to the world?
00:34:14.820 --> 00:34:15.100
Dominic.
00:34:16.220 --> 00:34:16.419
Sure.
00:34:16.760 --> 00:34:19.480
I mean, I can give it a shot.
00:34:20.520 --> 00:34:23.320
So I personally love SQLite.
00:34:23.659 --> 00:34:28.100
And I've actually been writing web apps using it,
00:34:28.419 --> 00:34:30.460
just even before running on workers,
00:34:31.020 --> 00:34:32.220
because it's so versatile.
00:34:32.720 --> 00:34:33.580
It's so easy to set up.
00:34:33.780 --> 00:34:40.440
You just load the library and save the database on your local file system.
00:34:41.000 --> 00:34:43.379
And I think this is basically an extension of that.
00:34:43.620 --> 00:34:43.919
I mean,
00:34:44.320 --> 00:34:48.899
you just get a local to your worker SQLite database.
00:34:49.560 --> 00:34:50.440
You can write to it.
00:34:50.840 --> 00:34:53.100
It gets replicated across the world for you.
00:34:53.720 --> 00:34:54.200
So,
00:34:55.020 --> 00:34:56.980
you know, and it scales with your workers as well.
00:34:56.980 --> 00:34:58.360
You don't have to worry about that at all.
00:34:58.500 --> 00:35:03.080
It's pretty wild because you've got like 300 database nodes, which is pretty incredible.
00:35:03.540 --> 00:35:06.500
And for people who don't know, they might think of SQLite as a toy.
00:35:06.530 --> 00:35:08.920
It is extremely fast as a database.
00:35:10.140 --> 00:35:11.600
So it's pretty interesting,
00:35:11.760 --> 00:35:11.940
I think.
00:35:12.260 --> 00:35:18.680
Now, the one thing that seems tricky is somebody in Southeast Asia and somebody in London writes
00:35:18.990 --> 00:35:20.460
to the database at the same time.
00:35:20.780 --> 00:35:21.240
Now what?
00:35:22.880 --> 00:35:25.540
Yeah, to be honest, I don't know the details of how that works.
00:35:25.880 --> 00:35:32.479
But I think there is some mechanisms to make sure that it's all consistent and you can
00:35:32.500 --> 00:35:34.920
make sure there's no conflicts there. Yeah. Yeah. Yeah.
00:35:35.210 --> 00:35:38.700
So something I've been looking at lately is
00:35:39.020 --> 00:35:40.820
Lightstream actually been setting this up.
00:35:41.100 --> 00:35:42.700
So Lightstream is really interesting because it
00:35:42.960 --> 00:35:48.560
works on SQLite and you set up the write ahead log, the wall in SQLite, it will basically
00:35:49.180 --> 00:35:55.540
synchronize and stream that write ahead log off to somewhere else for backup and replication and so
00:35:55.620 --> 00:35:56.500
on. So I'm wondering,
00:35:56.930 --> 00:35:59.959
my first thought is probably they're doing something with the write ahead log
00:36:00.240 --> 00:36:00.860
and then merging,
00:36:01.100 --> 00:36:01.380
you know,
00:36:01.920 --> 00:36:02.620
synchronizing that
00:36:02.800 --> 00:36:03.240
and then merging,
00:36:03.500 --> 00:36:05.060
combining it or something like that.
00:36:05.140 --> 00:36:05.900
I'm not totally sure,
00:36:06.080 --> 00:36:07.100
but this is my theory.
00:36:07.340 --> 00:36:10.140
One of the great things about the design of Python workers
00:36:10.360 --> 00:36:11.660
is that we just consume these things.
00:36:11.800 --> 00:36:12.800
We don't need to know how they work.
00:36:13.260 --> 00:36:13.680
Yeah, exactly.
00:36:14.060 --> 00:36:14.460
It's awesome.
00:36:15.240 --> 00:36:16.180
All right, we got a couple more.
00:36:16.320 --> 00:36:16.680
Hyperdrive.
00:36:16.920 --> 00:36:19.500
So D1 is kind of SQLite Hyperdrive.
00:36:19.760 --> 00:36:21.580
And this, I think, is new as part of your launch,
00:36:21.760 --> 00:36:21.860
right?
00:36:22.120 --> 00:36:24.080
This is kind of like distributed Postgres,
00:36:24.400 --> 00:36:25.440
but that wasn't available before.
00:36:25.960 --> 00:36:26.520
I don't know exactly,
00:36:26.920 --> 00:36:27.020
right?
00:36:27.320 --> 00:36:27.700
Something like this?
00:36:28.040 --> 00:36:30.080
Yeah, I think a hyperdrive is relatively new.
00:36:30.440 --> 00:36:30.800
And,
00:36:31.360 --> 00:36:34.180
and it's kind, I think it's kind of the proxy,
00:36:35.070 --> 00:36:38.460
I think I can explain as a kind of proxy that there's like a truth of source,
00:36:39.099 --> 00:36:41.020
related database like PostgreSQL,
00:36:41.320 --> 00:36:41.520
MySQL,
00:36:41.700 --> 00:36:45.460
Summary, and the Summary. And we have a lot of like
00:36:45.760 --> 00:36:50.880
proxies in the edge that can basically like make your database connections a lot more faster,
00:36:51.340 --> 00:36:56.459
like each there's like 350 hyperdrives that like maintains the connection pool with the original
00:36:56.480 --> 00:36:56.780
database,
00:36:57.300 --> 00:36:59.240
like making the read and write a lot faster.
00:36:59.640 --> 00:36:59.760
Right,
00:36:59.940 --> 00:37:00.040
right.
00:37:00.080 --> 00:37:02.140
You can turn on caching to say,
00:37:02.320 --> 00:37:04.120
you know, this table doesn't change very often.
00:37:04.420 --> 00:37:07.560
So if you've read that table over here, then just,
00:37:08.000 --> 00:37:08.220
you know,
00:37:08.460 --> 00:37:09.700
answer questions from it,
00:37:09.740 --> 00:37:10.180
something like that.
00:37:10.220 --> 00:37:10.460
It's awesome.
00:37:10.780 --> 00:37:12.380
Yeah, I would just add to that.
00:37:13.480 --> 00:37:18.100
It's worth noting that we talked a little bit about sockets before and socket support
00:37:18.360 --> 00:37:19.880
in Piodide.
00:37:20.400 --> 00:37:21.860
And that is actually what I think,
00:37:22.040 --> 00:37:22.160
Jay,
00:37:22.320 --> 00:37:23.140
you've been working on, right?
00:37:23.420 --> 00:37:27.360
making sockets work on workers for Python.
00:37:27.770 --> 00:37:29.340
And that is what makes Hyperdrive work.
00:37:30.240 --> 00:37:32.880
Hyperdrive is built on these TCP sockets.
00:37:33.790 --> 00:37:34.860
So without that, it wouldn't work.
00:37:35.180 --> 00:37:35.360
Yeah,
00:37:35.560 --> 00:37:35.880
exactly.
00:37:36.220 --> 00:37:36.360
Exactly.
00:37:36.510 --> 00:37:40.140
So supporting Hyperdrive in Cloudflare Python workers
00:37:40.310 --> 00:37:43.520
and in Pyrodite was one of the main goals for us
00:37:43.820 --> 00:37:45.840
before launching it at GA.
00:37:47.280 --> 00:37:49.540
And Pyrodite did not have socket support
00:37:49.710 --> 00:37:51.240
because browsers never had that.
00:37:51.380 --> 00:37:54.200
But to use the relational databases,
00:37:54.530 --> 00:37:58.180
you definitely need TCP connections and sockets.
00:37:58.720 --> 00:38:04.540
So we wired up the Node.js socket APIs inside Pyodide.
00:38:05.410 --> 00:38:06.260
So workers'
00:38:06.480 --> 00:38:08.420
runtime support Node.js socket APIs.
00:38:08.860 --> 00:38:11.300
So they are actually wired up inside Pyodide.
00:38:11.310 --> 00:38:17.260
So that by calling socket syscalls inside Pyodide actually calls a Node.js socket calls.
00:38:17.570 --> 00:38:18.940
So that's how AverageRM works.
00:38:18.960 --> 00:38:24.600
This is really crazy because the socket APIs in Node, of course, are all asynchronous,
00:38:25.150 --> 00:38:30.280
but most of the socket system calls that you have in Linux are synchronous calls.
00:38:30.780 --> 00:38:37.220
And so in order to handle the system call,
00:38:37.480 --> 00:38:51.280
the system call has to stack switch and let the JavaScript event loop turn so that it can get the IO completed and then it unstacks switches and returns to the...
00:38:51.460 --> 00:38:52.100
Yeah, that's wild.
00:38:52.740 --> 00:38:54.240
So this is all transparent to C code.
00:38:54.380 --> 00:39:00.400
So if you have a C application that consumes libc APIs to handle sockets,
00:39:00.580 --> 00:39:01.340
it just works.
00:39:01.660 --> 00:39:01.780
Yeah,
00:39:01.960 --> 00:39:10.960
I was kind of wondering if somehow you could unify the event loop of Node and the event loop of asyncio and kind of make them all one thing.
00:39:11.300 --> 00:39:12.240
So that's what we've done.
00:39:12.360 --> 00:39:14.940
So we have our event loop in Python,
00:39:15.940 --> 00:39:18.080
which we use for PyTag, which we call WebLoop.
00:39:18.360 --> 00:39:21.060
And it basically just subscribes to the browser event.
00:39:21.300 --> 00:39:24.440
And this is essentially necessary for two reasons.
00:39:24.600 --> 00:39:28.720
One is that all actual IO happen on the browser loop.
00:39:28.780 --> 00:39:30.060
Like there is really no way,
00:39:30.200 --> 00:39:33.140
like if you can make your own like separate loop,
00:39:33.600 --> 00:39:35.460
but like it can't do IO.
00:39:36.320 --> 00:39:38.120
And while it's spinning the real IO,
00:39:38.600 --> 00:39:40.000
it's blocking the real event loop,
00:39:40.040 --> 00:39:41.120
which can't do the real IO.
00:39:42.140 --> 00:39:42.320
Yeah.
00:39:42.640 --> 00:39:44.120
And I said there were going to be two reasons,
00:39:45.220 --> 00:39:47.100
but I feel like that was both reasons.
00:39:47.960 --> 00:39:48.440
Well,
00:39:49.180 --> 00:39:50.380
it sounds like an important one.
00:39:50.580 --> 00:39:50.680
Okay.
00:39:50.960 --> 00:39:52.860
So we also have R2,
00:39:53.520 --> 00:39:55.440
which is like S3-ish.
00:39:56.000 --> 00:39:56.480
Exactly.
00:39:57.860 --> 00:39:59.020
How is it different,
00:39:59.260 --> 00:39:59.320
though?
00:39:59.660 --> 00:40:01.840
Well, I think it's like almost the same.
00:40:02.080 --> 00:40:04.240
The name R2 actually comes from S3.
00:40:04.580 --> 00:40:08.540
It's like a 1 minus S minus 1 and 3 minus 1.
00:40:08.540 --> 00:40:08.640
I see.
00:40:08.860 --> 00:40:10.920
Yeah, so RS and then 3, 2.
00:40:10.920 --> 00:40:11.200
It's exactly the same.
00:40:11.600 --> 00:40:14.820
I think the main thing with it is that there's no egress fees.
00:40:16.100 --> 00:40:17.060
So it's cheaper.
00:40:17.460 --> 00:40:18.160
No egress fees.
00:40:18.280 --> 00:40:19.080
Okay, very interesting.
00:40:19.460 --> 00:40:19.740
All right.
00:40:20.000 --> 00:40:20.760
And you can use this.
00:40:21.500 --> 00:40:22.060
Some of these things,
00:40:22.300 --> 00:40:23.920
I guess probably almost all of them,
00:40:23.920 --> 00:40:27.140
you can use regardless of whether you're using Cloudflare workers or not.
00:40:27.320 --> 00:40:30.600
I could use R2 just because I want object storage.
00:40:31.080 --> 00:40:31.280
Interesting.
00:40:31.800 --> 00:40:32.820
I'm about to think more about that.
00:40:33.400 --> 00:40:33.980
It's giving me ideas.
00:40:34.180 --> 00:40:34.280
Okay.
00:40:35.000 --> 00:40:37.120
And you've got queues, Cloudflare queues,
00:40:37.640 --> 00:40:38.800
and AI inference.
00:40:39.440 --> 00:40:40.440
So these are all the...
00:40:40.520 --> 00:40:43.480
I kind of wanted to go through these because these are the building blocks
00:40:43.580 --> 00:40:47.380
or the platform pieces that are available to these new Python workers,
00:40:47.580 --> 00:40:47.700
right?
00:40:47.960 --> 00:40:49.800
Yeah, you have a lot of building blocks.
00:40:50.760 --> 00:40:51.560
inside Cloudflow.
00:40:51.800 --> 00:40:53.860
Developer platform, we keep adding it every month.
00:40:54.020 --> 00:40:55.240
So I'm not,
00:40:55.480 --> 00:40:55.840
to be honest,
00:40:56.060 --> 00:40:57.620
not following all those releases,
00:40:58.060 --> 00:41:00.760
but queues and AI and their workflows,
00:41:01.620 --> 00:41:02.100
things like that.
00:41:02.200 --> 00:41:04.080
But you can easily connect your workers
00:41:04.360 --> 00:41:06.440
with those new features
00:41:07.040 --> 00:41:08.960
and to build a full stack application.
00:41:09.140 --> 00:41:10.520
If you need a queue, you can use queue.
00:41:10.680 --> 00:41:13.000
If you want to run AI inference into Edge,
00:41:13.020 --> 00:41:14.020
you can use Worker's AI,
00:41:14.200 --> 00:41:15.500
which is awesome.
00:41:15.940 --> 00:41:16.440
Yeah, that's super,
00:41:16.640 --> 00:41:17.080
super neat.
00:41:17.520 --> 00:41:18.660
All right, let's go to the announcement.
00:41:18.920 --> 00:41:19.640
And here it is.
00:41:19.860 --> 00:41:20.660
September 21.
00:41:21.060 --> 00:41:22.840
Took us a little bit to actually press record,
00:41:23.220 --> 00:41:25.220
but it's been a few weeks, not too long though.
00:41:25.640 --> 00:41:27.120
This announcement by the three of you,
00:41:27.400 --> 00:41:29.960
Python web workers are now generally available.
00:41:30.720 --> 00:41:31.120
Hooray!
00:41:31.520 --> 00:41:31.820
That's awesome.
00:41:32.200 --> 00:41:37.100
How long had they been in beta style availability before that?
00:41:37.380 --> 00:41:39.080
Feels like since like spring of 2024.
00:41:39.980 --> 00:41:42.100
So I started in October of 2023
00:41:42.760 --> 00:41:45.320
and it took about six months to get a beta going
00:41:46.040 --> 00:41:47.960
and then it took like over two years
00:41:47.980 --> 00:41:50.000
to make it generally available.
00:41:50.640 --> 00:41:50.760
Wow.
00:41:51.070 --> 00:41:51.780
So what was that work?
00:41:52.020 --> 00:41:52.340
Like trying,
00:41:52.520 --> 00:41:53.180
for example,
00:41:53.610 --> 00:41:54.420
the IO loops
00:41:54.510 --> 00:41:55.060
and all the different,
00:41:55.500 --> 00:41:57.520
all the just the sockets that Jay worked on,
00:41:57.700 --> 00:41:59.220
all these things that you need in place.
00:41:59.740 --> 00:42:02.020
That's what like data science pyodied
00:42:02.160 --> 00:42:04.840
to full runtime pyodied work was.
00:42:05.140 --> 00:42:07.920
I think the packaging story was actually a big thing.
00:42:07.990 --> 00:42:08.320
I mean,
00:42:08.620 --> 00:42:09.180
when we started,
00:42:09.860 --> 00:42:10.000
we,
00:42:11.100 --> 00:42:12.820
so there was two parts to this.
00:42:13.220 --> 00:42:14.940
One was trying to make sure
00:42:15.070 --> 00:42:17.420
that the cold starts are as fast as possible
00:42:17.740 --> 00:42:19.400
and especially when we're using packages.
00:42:20.120 --> 00:42:21.220
And when we started,
00:42:21.660 --> 00:42:23.480
we figured we'll just allow people
00:42:23.520 --> 00:42:26.880
to use certain built-in packages that Pyodite provides.
00:42:28.020 --> 00:42:30.100
But we just realized that that isn't flexible enough
00:42:30.600 --> 00:42:32.020
and we just need to allow people to use
00:42:32.580 --> 00:42:33.560
whatever packages they want,
00:42:33.740 --> 00:42:33.920
ideally.
00:42:34.300 --> 00:42:37.220
So we basically switched away from that approach
00:42:37.880 --> 00:42:41.300
to building a UV-based tool called PyWrangler,
00:42:41.320 --> 00:42:44.360
which lets you just install any package that you want
00:42:44.760 --> 00:42:46.240
and get it into your worker very easily.
00:42:47.420 --> 00:42:50.960
And then there's the memory snapshots aspect of it, which I think we might get to later.
00:42:51.220 --> 00:42:51.480
Oh, yeah.
00:42:51.820 --> 00:42:52.060
Oh, yeah.
00:42:52.360 --> 00:42:56.240
Memory snapshots were basically what I started working on as soon as I came to Cloudflare.
00:42:56.280 --> 00:43:01.140
I spent like two months researching memory snapshots before I wrote like any code, made
00:43:01.280 --> 00:43:02.400
any pull requests at all.
00:43:03.220 --> 00:43:03.620
Interesting.
00:43:03.880 --> 00:43:04.000
Okay.
00:43:04.520 --> 00:43:06.940
And you just gave a presentation at the Python Language Summit,
00:43:07.480 --> 00:43:08.740
also at EuroPython a little
00:43:08.740 --> 00:43:09.040
while ago,
00:43:09.200 --> 00:43:09.300
right?
00:43:09.700 --> 00:43:10.020
Yeah,
00:43:10.580 --> 00:43:10.640
right.
00:43:10.940 --> 00:43:25.040
So this was about the fact that there is an important difficulty that comes up with memory snapshots, which is that it introduces a difference between sort of startup time or like, you know,
00:43:25.200 --> 00:43:31.140
sort of like top level execution and like your actual like runtime logic.
00:43:31.220 --> 00:43:36.480
And the Python language does not have a distinction like this,
00:43:36.640 --> 00:43:36.760
right?
00:43:36.850 --> 00:43:38.340
Like the Python runtime,
00:43:38.770 --> 00:43:40.380
when you start it up, it bootstraps itself.
00:43:40.980 --> 00:43:43.920
And then it just starts evaling user code.
00:43:44.240 --> 00:43:48.220
And whether it's top level user code or calling a function,
00:43:48.410 --> 00:43:49.160
it doesn't matter.
00:43:49.580 --> 00:43:52.000
Like it just evals until it stops evaling.
00:43:52.010 --> 00:43:53.860
And when it runs out of stuff to do, it shuts down.
00:43:54.600 --> 00:43:54.700
Yeah,
00:43:54.860 --> 00:43:58.140
even things like import statements are really code execution,
00:43:58.460 --> 00:43:59.540
not just, you know,
00:43:59.700 --> 00:44:00.240
linking or whatever.
00:44:00.300 --> 00:44:02.500
It takes a bit to wrap your head around it.
00:44:02.760 --> 00:44:04.160
It's just right.
00:44:04.320 --> 00:44:06.800
Like the import statement is compiled into something.
00:44:07.300 --> 00:44:09.580
And then like those op codes get like interpreted.
00:44:09.920 --> 00:44:13.600
And that causes import lib to go look up files on disk,
00:44:13.760 --> 00:44:15.140
find the thing that it wants to import.
00:44:15.500 --> 00:44:17.680
And then it like starts executing that file.
00:44:18.540 --> 00:44:21.340
And so for memory snapshots,
00:44:21.500 --> 00:44:22.180
you know, we say like, okay,
00:44:22.340 --> 00:44:22.420
look,
00:44:22.660 --> 00:44:23.740
all of that top level stuff,
00:44:23.820 --> 00:44:25.680
it's going to happen the same every time.
00:44:26.160 --> 00:44:32.220
So it's very wasteful to keep doing it every time someone's deployed an application to the edge.
00:44:32.700 --> 00:44:40.240
Like every single time it cold starts, it's going to execute exactly the same top level code and end up with exactly the same outcome.
00:44:40.780 --> 00:44:43.900
And so we would really like to just save that work.
00:44:44.260 --> 00:44:51.660
And this is actually very similar to the work that like optimizing Python compilers like PyPy and Grawl Python do,
00:44:52.650 --> 00:44:57.620
because they also want to evaluate all that stuff at compile time.
00:44:57.630 --> 00:44:58.840
This is like partial evaluation.
00:44:59.310 --> 00:45:01.400
So it's a bit of a different technology than a memory snapshot.
00:45:01.730 --> 00:45:03.400
But it has the same fundamental issue,
00:45:03.570 --> 00:45:08.600
which is that it needs to impose a model of like what is startup time,
00:45:08.780 --> 00:45:12.160
what can be precompiled onto a language that doesn't have one.
00:45:12.680 --> 00:45:13.280
Now, of course,
00:45:13.680 --> 00:45:17.640
you know, I think this is this is this talk is like a fun thing to think about.
00:45:18.280 --> 00:45:18.420
But,
00:45:18.720 --> 00:45:18.920
you know,
00:45:19.080 --> 00:45:19.360
I mean,
00:45:19.740 --> 00:45:22.860
at least Thomas Vouders said that it was like a nonstarter.
00:45:23.020 --> 00:45:27.040
And I think he is right that like, you know, it's sort of too late for the language to get something like this.
00:45:27.400 --> 00:45:29.420
But I have friends that are working on on,
00:45:29.740 --> 00:45:31.060
you know, new programming languages.
00:45:31.180 --> 00:45:34.660
My friend Antonio Cooney is trying to make this language called SPI,
00:45:34.860 --> 00:45:36.100
which stands for static Python,
00:45:37.440 --> 00:45:39.100
which is supposed to be like a better R Python,
00:45:39.960 --> 00:45:40.940
which was used for PyPy.
00:45:41.360 --> 00:45:41.880
And basically,
00:45:42.620 --> 00:45:47.700
the main idea in some sense of the language is to pre-bake a notion of
00:45:48.100 --> 00:45:48.500
compile,
00:45:48.780 --> 00:45:52.380
to create a notion of compile time versus execution time,
00:45:52.720 --> 00:45:54.260
and then allow lots
00:45:54.260 --> 00:45:59.340
of compile time evaluation of spy code so that it can perform that.
00:45:59.600 --> 00:46:02.520
Yeah, the basic idea is something like you're going to load the interpreter,
00:46:02.780 --> 00:46:03.000
it's going to
00:46:03.000 --> 00:46:04.180
load all the standard library,
00:46:04.600 --> 00:46:07.160
it's going to maybe read some of the files,
00:46:07.660 --> 00:46:08.280
parse them,
00:46:08.340 --> 00:46:09.660
do the import processing.
00:46:10.020 --> 00:46:10.840
And that never changes,
00:46:11.140 --> 00:46:11.240
right?
00:46:11.320 --> 00:46:11.560
Well,
00:46:11.760 --> 00:46:13.560
maybe the import, because it depends if you run code or not.
00:46:13.650 --> 00:46:16.960
But other than that, you theoretically could say,
00:46:17.320 --> 00:46:18.500
let's just see what happens.
00:46:18.800 --> 00:46:19.740
And like a VM,
00:46:20.000 --> 00:46:20.280
just go,
00:46:20.440 --> 00:46:21.220
your memory's back.
00:46:21.430 --> 00:46:21.540
Continue.
00:46:22.150 --> 00:46:22.300
Yeah?
00:46:22.660 --> 00:46:22.880
Right.
00:46:22.970 --> 00:46:25.800
And of course, there's a lot of subtlety in there because we have,
00:46:26.600 --> 00:46:27.040
for instance,
00:46:27.260 --> 00:46:28.180
if you
00:46:28.360 --> 00:46:29.540
import a dynamic library,
00:46:29.840 --> 00:46:32.760
it does all this relocations.
00:46:33.530 --> 00:46:39.920
It allocates space for all the global variables that the dynamic library is going to define.
00:46:40.220 --> 00:46:42.180
And then it relocates them all into that space.
00:46:42.720 --> 00:46:43.520
And it, you know,
00:46:43.880 --> 00:46:46.100
relocates all the functions from the dynamic library.
00:46:46.540 --> 00:46:50.020
And somehow you have to do some crazy magic with the dynamic loader.
00:46:50.400 --> 00:46:50.560
Basically,
00:46:51.000 --> 00:46:53.940
like I have a loader patch that when it loads a dynamic library,
00:46:54.360 --> 00:46:59.100
writes down the relocation base that it's putting the dynamic library at.
00:46:59.440 --> 00:47:01.840
And then when I'm going to restore the memory snapshot,
00:47:01.860 --> 00:47:04.780
I have to make sure that it gets relocated to the same place.
00:47:04.880 --> 00:47:07.580
So I patch the malloc so that it will,
00:47:08.020 --> 00:47:09.780
instead of actually doing a memory allocation,
00:47:10.140 --> 00:47:11.060
it just looks,
00:47:11.360 --> 00:47:11.520
oh,
00:47:11.700 --> 00:47:12.360
in this context,
00:47:12.600 --> 00:47:14.580
I'm allocating memory for this dynamic library.
00:47:15.580 --> 00:47:16.260
In the snapshot,
00:47:16.480 --> 00:47:18.060
we allocated it at this address,
00:47:18.240 --> 00:47:19.480
so we're going to play back that address.
00:47:20.160 --> 00:47:22.960
And then all this crazy magic just sort of...
00:47:23.040 --> 00:47:24.680
That sounds supremely complicated.
00:47:25.420 --> 00:47:26.360
It's very...
00:47:26.640 --> 00:47:27.460
It was a lot of fun.
00:47:27.600 --> 00:47:28.500
It's really horrible.
00:47:29.800 --> 00:47:31.540
All right, so let's go back to the announcement.
00:47:31.840 --> 00:47:33.360
There's a couple of code samples
00:47:33.700 --> 00:47:34.900
and different types of things here.
00:47:35.960 --> 00:47:39.020
So programming model is a little bit like writing an API,
00:47:39.280 --> 00:47:39.360
yeah?
00:47:39.680 --> 00:47:40.000
Yeah,
00:47:40.510 --> 00:47:44.860
I think the major usage of workers runtime is writing an API server.
00:47:45.030 --> 00:47:48.000
So we used Face the API a lot in our examples.
00:47:48.720 --> 00:47:52.920
So a lot of Python users might use Python in different ways,
00:47:53.030 --> 00:47:57.020
but I think the major use case of workers runtime is to build an API server
00:47:57.360 --> 00:47:59.580
and connecting different findings in it.
00:47:59.760 --> 00:48:02.460
So yeah, that's the examples we show in our flow post.
00:48:02.760 --> 00:48:05.880
Yeah, you want your API to be super snappy and responsive.
00:48:06.240 --> 00:48:12.400
So if you could put your data in D1 and then have your code also run right literally in
00:48:12.400 --> 00:48:13.640
the same process right there,
00:48:13.880 --> 00:48:14.900
like that's going to be really great.
00:48:15.100 --> 00:48:15.160
Yeah.
00:48:15.500 --> 00:48:16.140
So you can,
00:48:16.300 --> 00:48:17.840
if you know how to write a FastAPI app,
00:48:18.080 --> 00:48:18.920
it's the same thing.
00:48:19.070 --> 00:48:21.200
Just instead of uvacoron.run,
00:48:21.600 --> 00:48:24.280
it's just hand off the app and off it goes,
00:48:24.620 --> 00:48:25.780
which is really,
00:48:25.920 --> 00:48:26.220
really neat.
00:48:26.480 --> 00:48:28.980
Now, the examples that I saw on this page, I don't remember,
00:48:29.180 --> 00:48:30.280
I'm pretty sure they all
00:48:30.420 --> 00:48:32.100
have like one request,
00:48:32.300 --> 00:48:33.020
just like forward slash.
00:48:33.500 --> 00:48:35.300
can I have a more complicated app with,
00:48:35.540 --> 00:48:37.460
say, five or six different endpoints?
00:48:38.200 --> 00:48:38.320
Yeah,
00:48:38.500 --> 00:48:39.260
that's just per short, yes,
00:48:39.440 --> 00:48:39.660
right?
00:48:39.960 --> 00:48:43.140
Like, you know, you could make any FastAPI app you want here, right?
00:48:43.400 --> 00:48:46.320
Yeah, there is no limits to how many endpoints you can have.
00:48:47.200 --> 00:48:50.780
I suppose it might be worth talking about the actual limits that the workers have.
00:48:51.120 --> 00:48:51.620
And that is,
00:48:52.280 --> 00:48:53.640
yeah, so it's memory,
00:48:53.940 --> 00:48:55.280
which is 128 megabytes,
00:48:55.880 --> 00:48:57.960
and CPU time as well.
00:48:59.060 --> 00:49:03.460
You know, I think actually a great thing about workers is that you can do quite a lot
00:49:03.460 --> 00:49:03.540
free,
00:49:04.020 --> 00:49:06.620
like completely for free, you don't have to pay anything to Cloudflare,
00:49:06.850 --> 00:49:07.860
you can run a very
00:49:08.030 --> 00:49:09.340
simple FastAPI application,
00:49:09.560 --> 00:49:10.340
even I think,
00:49:10.600 --> 00:49:10.940
for free.
00:49:11.740 --> 00:49:14.240
What's the free request limit is like 100,000
00:49:14.360 --> 00:49:15.020
requests a day?
00:49:15.260 --> 00:49:15.720
Is that right?
00:49:15.900 --> 00:49:16.140
Yeah,
00:49:16.760 --> 00:49:18.160
yeah, you get 100,000 requests,
00:49:18.780 --> 00:49:20.140
I think, per day.
00:49:20.580 --> 00:49:21.620
And yeah,
00:49:21.670 --> 00:49:24.800
if you type in workers limits into Google,
00:49:25.080 --> 00:49:25.760
it should show up.
00:49:26.670 --> 00:49:27.820
But if you know, if you're just
00:49:27.840 --> 00:49:29.580
doing kind of more CPU intensive stuff,
00:49:29.800 --> 00:49:33.000
then that is another limit that we have.
00:49:33.320 --> 00:49:33.480
Yeah,
00:49:33.660 --> 00:49:34.260
it's basically
00:49:34.580 --> 00:49:38.960
there 10 milliseconds for free of CPU time and five minutes for paid.
00:49:39.980 --> 00:49:41.820
But yeah, you can do quite a lot.
00:49:42.400 --> 00:49:42.760
It's very,
00:49:42.960 --> 00:49:43.380
very flexible.
00:49:43.740 --> 00:49:43.900
Right.
00:49:44.180 --> 00:49:46.120
Speaking of what we were doing for those two years,
00:49:46.300 --> 00:49:46.620
another thing
00:49:46.700 --> 00:49:51.480
that took a lot of careful work was making sure that when you run out of that 10 milliseconds of
00:49:51.500 --> 00:49:55.800
CPU time that a signal is delivered to the Python runtime,
00:49:56.300 --> 00:49:58.120
and it gracefully interrupts its
00:49:58.360 --> 00:50:04.280
execution and returns to Cloudflare so that it doesn't like leave it in a broken state.
00:50:04.630 --> 00:50:04.800
Because
00:50:05.220 --> 00:50:06.720
if you do this the naive way,
00:50:07.640 --> 00:50:12.580
JavaScript throws a non catchable exception into the runtime and
00:50:12.700 --> 00:50:17.060
forcibly unwinds all of the call stack without executing finally blocks or,
00:50:17.220 --> 00:50:17.900
you know, catch blocks.
00:50:18.420 --> 00:50:20.420
And so like any locks that you've taken
00:50:20.660 --> 00:50:22.480
that you were expecting to release in a finally block,
00:50:22.760 --> 00:50:23.760
that just doesn't get executed.
00:50:23.920 --> 00:50:25.760
And then the runtime is like completely broken.
00:50:26.400 --> 00:50:26.780
And so
00:50:27.500 --> 00:50:28.080
Or
00:50:28.080 --> 00:50:30.360
like half written files that are not, the
00:50:30.360 --> 00:50:31.340
buffer's not flushed. All
00:50:31.340 --> 00:50:32.460
sorts of things could go wrong. All
00:50:32.460 --> 00:50:33.320
sorts of things, you know, like
00:50:33.320 --> 00:50:36.160
loss of code relies on finally blocks executing
00:50:36.440 --> 00:50:36.660
and
00:50:37.500 --> 00:50:39.380
it was not executing the finally blocks. And
00:50:39.380 --> 00:50:42.240
so we had to like do some very elaborate thing to
00:50:42.240 --> 00:50:46.000
make the CPU time limiter deliver the signal correctly
00:50:46.000 --> 00:50:46.840
to the Python
00:50:47.860 --> 00:50:49.980
M-scripted operating system inside of the
00:50:50.540 --> 00:50:50.660
runtime.
00:50:50.900 --> 00:50:51.880
Of course, we have the same problem with
00:50:52.000 --> 00:50:52.500
Rust workers.
00:50:52.890 --> 00:50:54.000
So we basically have
00:50:54.040 --> 00:50:55.760
the same solution for both Python
00:50:56.000 --> 00:50:57.360
workers and for Rust workers for that.
00:50:57.720 --> 00:50:59.120
As you start to bring in more languages,
00:50:59.320 --> 00:50:59.500
you're like,
00:50:59.620 --> 00:51:01.340
this is kind of the same problem.
00:51:01.980 --> 00:51:02.580
Okay, this is great.
00:51:02.740 --> 00:51:03.820
You've got a lot of
00:51:04.339 --> 00:51:04.700
computer.
00:51:05.100 --> 00:51:05.860
100,000
00:51:06.020 --> 00:51:07.320
requests a day for free?
00:51:07.860 --> 00:51:08.520
That's a lot.
00:51:08.880 --> 00:51:10.080
You can do a lot.
00:51:10.540 --> 00:51:11.720
Many, many little hobby
00:51:11.900 --> 00:51:13.720
apps and small apps live well under
00:51:13.860 --> 00:51:14.080
that limit.
00:51:14.300 --> 00:51:15.980
Right. I think the good part of
00:51:16.000 --> 00:51:17.880
for like hobby developers
00:51:18.200 --> 00:51:20.300
is we have really generous pricing.
00:51:20.480 --> 00:51:22.080
I don't want to be too marketing pitch,
00:51:22.480 --> 00:51:25.380
but I also used Qualifier when I was a student
00:51:25.740 --> 00:51:27.700
because they really offered a good free pricing.
00:51:28.160 --> 00:51:30.700
Like you can have like 10 gigabytes of R2 for free,
00:51:30.720 --> 00:51:31.120
I guess.
00:51:31.360 --> 00:51:32.240
So there's a storage,
00:51:32.540 --> 00:51:33.420
there's a runtime,
00:51:34.040 --> 00:51:35.820
there's everything you can use freely.
00:51:36.160 --> 00:51:36.560
Yeah, well,
00:51:36.860 --> 00:51:38.540
and you know, the storage is one thing,
00:51:38.700 --> 00:51:39.420
but the egress,
00:51:40.040 --> 00:51:41.440
that's where you pay money often
00:51:41.900 --> 00:51:45.140
for S3 is you pay tons of bandwidth charges.
00:51:45.900 --> 00:51:46.180
Yeah,
00:51:46.360 --> 00:51:46.600
very neat.
00:51:46.960 --> 00:51:47.660
All right, let's see.
00:51:47.920 --> 00:51:49.420
Let's go back to this.
00:51:49.880 --> 00:51:50.920
So first class language,
00:51:51.420 --> 00:51:51.800
really good.
00:51:52.060 --> 00:51:52.660
FastAPI,
00:51:54.260 --> 00:51:54.400
Django,
00:51:54.600 --> 00:51:54.800
Flask.
00:51:55.160 --> 00:51:57.960
Does it basically run anything that does WSGI or ASCII
00:51:58.340 --> 00:51:59.580
as each return that?
00:52:00.520 --> 00:52:00.860
You know,
00:52:01.180 --> 00:52:01.280
like,
00:52:01.600 --> 00:52:02.500
of course, there could be problems
00:52:02.840 --> 00:52:04.640
with them trying to start threads and things like that.
00:52:04.820 --> 00:52:07.580
But assuming that they don't try to start too many threads,
00:52:08.180 --> 00:52:08.260
then,
00:52:08.420 --> 00:52:08.520
like,
00:52:08.760 --> 00:52:11.600
you know, we have a general purpose ASCII
00:52:11.660 --> 00:52:13.440
and WSGI adapters that you see here.
00:52:13.720 --> 00:52:13.940
Okay.
00:52:14.220 --> 00:52:16.540
Yeah, well, you know, that was one of the best things that happened to Python web,
00:52:16.920 --> 00:52:16.980
right?
00:52:17.600 --> 00:52:21.260
That you got this interface that you can plug into all these different runtimes.
00:52:21.420 --> 00:52:21.480
And,
00:52:21.650 --> 00:52:23.100
you know, it sounds like you're as well.
00:52:23.420 --> 00:52:24.380
It's amazing for us.
00:52:24.410 --> 00:52:24.500
Yeah,
00:52:24.680 --> 00:52:26.360
because they don't try to do IO directly.
00:52:26.610 --> 00:52:26.900
And so,
00:52:27.200 --> 00:52:29.980
you know, I mean, that's exactly the problem we have with something like URL of three.
00:52:30.050 --> 00:52:32.640
Of course, URL of three specifically supports Pyodide.
00:52:32.640 --> 00:52:33.060
So it's okay.
00:52:33.980 --> 00:52:34.220
But like,
00:52:34.760 --> 00:52:36.700
it's normal way of doing IO just doesn't work.
00:52:36.710 --> 00:52:40.060
So it needs a separate path for Pyodide.
00:52:40.780 --> 00:52:43.960
And all of these things would need that if it weren't for these beautiful adapters.
00:52:44.560 --> 00:52:45.980
that... Yeah, they're super
00:52:46.240 --> 00:52:47.000
polished and optimized.
00:52:47.580 --> 00:52:48.200
It's really nice.
00:52:48.660 --> 00:52:50.080
Yeah. Let's talk. We only got
00:52:50.080 --> 00:52:52.040
a couple minutes left before we're out
00:52:52.060 --> 00:52:52.340
of time.
00:52:52.820 --> 00:52:54.040
It's late
00:52:54.060 --> 00:52:54.600
in some places,
00:52:54.780 --> 00:52:55.360
early in others.
00:52:56.580 --> 00:52:57.880
Let's maybe round out this
00:52:58.200 --> 00:53:00.040
conversation by the types of
00:53:00.180 --> 00:53:01.860
apps that you see people building
00:53:02.140 --> 00:53:03.960
in Cloudflare workers in general, and
00:53:04.120 --> 00:53:05.600
specifically also in Python.
00:53:06.480 --> 00:53:08.080
Everyone knows what an API that
00:53:08.220 --> 00:53:09.980
talks to a database looks like, but can I
00:53:10.000 --> 00:53:11.340
do data science work here?
00:53:11.560 --> 00:53:12.260
Can I do
00:53:12.580 --> 00:53:15.200
long-running work? What types of things are people building here?
00:53:15.440 --> 00:53:19.440
A lot of the workers that I've looked at are big piles of boring business logic.
00:53:20.400 --> 00:53:21.840
It's just a mess,
00:53:22.160 --> 00:53:24.580
and it does apparently what they are needing.
00:53:25.920 --> 00:53:27.380
I would not recommend data science.
00:53:28.160 --> 00:53:32.620
It's not really a platform that has a lot of computing
00:53:32.980 --> 00:53:33.080
power.
00:53:33.300 --> 00:53:35.360
If you want to do things like graphics cards, SIMD,
00:53:35.580 --> 00:53:37.280
it doesn't have any of that.
00:53:38.800 --> 00:53:42.760
But it's a very powerful platform for stuff.
00:53:43.299 --> 00:53:44.080
That's totally fair.
00:53:44.190 --> 00:53:45.420
And I think that's one of the things
00:53:45.450 --> 00:53:47.760
I was trying to kind of explore is, right?
00:53:47.840 --> 00:53:51.300
Like how far can you push it before it just starts timing out
00:53:51.480 --> 00:53:52.720
or whatever, it runs out of memory.
00:53:53.120 --> 00:53:53.940
But what if I'm,
00:53:54.420 --> 00:53:56.600
let's say I'm a researcher or a student
00:53:56.780 --> 00:53:59.820
and I've got a pandas or just a parquet file
00:54:00.000 --> 00:54:00.980
with 20,000 records.
00:54:01.430 --> 00:54:02.520
And I do basic,
00:54:02.820 --> 00:54:03.200
like, here's a,
00:54:03.430 --> 00:54:04.580
let me do a little bit of query on that
00:54:04.630 --> 00:54:06.400
then I'll draw a graph or whatever.
00:54:06.860 --> 00:54:08.800
It can, in principle, do stuff like that.
00:54:09.200 --> 00:54:10.100
Yeah, that seems like it might work.
00:54:10.560 --> 00:54:10.620
Right.
00:54:10.840 --> 00:54:11.800
You can load pandas.
00:54:11.800 --> 00:54:12.400
You can load,
00:54:12.620 --> 00:54:12.820
you know,
00:54:13.760 --> 00:54:17.620
whatever the parquet package that is popular now is.
00:54:18.680 --> 00:54:19.080
And,
00:54:20.240 --> 00:54:20.900
you know, I mean,
00:54:21.380 --> 00:54:22.580
just the packages,
00:54:22.840 --> 00:54:23.280
you know, if you start,
00:54:23.460 --> 00:54:24.000
you know, like, for instance,
00:54:24.620 --> 00:54:26.320
SciPy is just too big,
00:54:27.200 --> 00:54:27.660
too horrible.
00:54:28.360 --> 00:54:32.460
And it doesn't really work to import SciPy.
00:54:32.520 --> 00:54:33.040
I mean, SciFi,
00:54:33.240 --> 00:54:34.360
when you bring it in,
00:54:34.640 --> 00:54:36.820
it has like over 100 different shared libraries.
00:54:37.520 --> 00:54:37.740
You know,
00:54:38.700 --> 00:54:38.760
yeah,
00:54:39.060 --> 00:54:43.180
SciFi has been like a real journey for us in Pyodide.
00:54:43.240 --> 00:54:45.400
Like it's really like the most horrible package.
00:54:47.800 --> 00:54:49.460
But if it's not SciFi,
00:54:49.680 --> 00:54:51.640
you know, Pandas works and you can just,
00:54:51.940 --> 00:54:55.920
you know, load your Parquet file and share your graph as long as it's not too big.
00:54:56.040 --> 00:54:56.300
Well,
00:54:56.640 --> 00:54:57.180
in my opinion,
00:54:57.360 --> 00:55:02.400
like pandas or docdb or other data processing libraries are not very optimized for Python workers.
00:55:02.580 --> 00:55:03.900
It's because like there are different,
00:55:04.180 --> 00:55:09.480
like the concept is a little bit different because workers is very memory limited environment.
00:55:09.700 --> 00:55:13.020
So we basically recommend everything to run in streams,
00:55:13.280 --> 00:55:14.820
not like load a bunch of memory,
00:55:15.720 --> 00:55:17.500
like lots of data frames inside memory.
00:55:17.700 --> 00:55:18.440
More polars,
00:55:18.620 --> 00:55:19.980
less pandas type of flow,
00:55:20.160 --> 00:55:20.260
yeah?
00:55:20.600 --> 00:55:20.700
Yeah,
00:55:20.940 --> 00:55:21.060
like,
00:55:21.220 --> 00:55:22.180
yeah, more polars,
00:55:22.340 --> 00:55:22.980
not pandas.
00:55:23.140 --> 00:55:26.020
if you need to load all the data frames in your memory,
00:55:26.220 --> 00:55:27.180
that it won't fit.
00:55:27.380 --> 00:55:28.480
You need to do streams.
00:55:28.700 --> 00:55:29.140
But actually,
00:55:29.290 --> 00:55:30.360
like Python packages are,
00:55:31.140 --> 00:55:32.440
especially legacy Python packages,
00:55:32.450 --> 00:55:33.740
are not very optimized for that.
00:55:33.980 --> 00:55:36.180
So we'll need to do a lot of back and forth
00:55:36.230 --> 00:55:37.320
to make it work properly.
00:55:37.720 --> 00:55:37.800
Right.
00:55:38.160 --> 00:55:38.300
Yeah,
00:55:38.520 --> 00:55:39.080
I mean...
00:55:39.380 --> 00:55:39.540
Go ahead.
00:55:39.960 --> 00:55:40.100
You go.
00:55:40.300 --> 00:55:43.200
So we're talking about Pyodide and WebAssembly.
00:55:44.019 --> 00:55:46.740
Another way, if I was this theoretical person
00:55:46.810 --> 00:55:47.340
I was describing,
00:55:47.500 --> 00:55:48.960
wanted to put this stuff on workers,
00:55:49.360 --> 00:55:51.820
maybe what I do is I just put my parquet file
00:55:51.820 --> 00:55:54.240
and my WebAssembly stuff on Cloudflare
00:55:54.460 --> 00:55:55.640
and just put it on the front end,
00:55:55.860 --> 00:55:56.000
right?
00:55:56.380 --> 00:55:59.460
You could run it like a JupyterLite style of execution.
00:55:59.900 --> 00:56:01.940
And then everyone gets their own little browser runtime
00:56:02.220 --> 00:56:03.740
instead of Edgeware runtime.
00:56:03.980 --> 00:56:05.540
Lots of people are doing exactly that.
00:56:06.180 --> 00:56:06.800
And then of course,
00:56:07.080 --> 00:56:09.980
all of the compute is paid for by the end user.
00:56:10.640 --> 00:56:11.000
Exactly.
00:56:11.740 --> 00:56:15.040
That's your iPhone battery or your iPad battery
00:56:15.120 --> 00:56:15.620
or whatever,
00:56:15.940 --> 00:56:17.880
rather than your compute bill.
00:56:19.040 --> 00:56:21.180
Because setting up that kind of stuff is really tricky
00:56:21.180 --> 00:56:23.140
for researchers who are not developers
00:56:23.560 --> 00:56:24.660
and they're not DevOps people.
00:56:24.880 --> 00:56:25.260
They're just like,
00:56:25.420 --> 00:56:26.900
I just want to share this thing, right?
00:56:27.020 --> 00:56:28.880
So maybe that's the way to go.
00:56:29.160 --> 00:56:29.300
All right.
00:56:29.720 --> 00:56:30.720
I've talked to so many people
00:56:31.100 --> 00:56:31.700
who are doing that,
00:56:31.880 --> 00:56:34.180
like sharing their data science notebook,
00:56:34.520 --> 00:56:36.060
like instead of having to have
00:56:36.060 --> 00:56:36.780
a Jupyter notebook
00:56:37.000 --> 00:56:38.180
and then they make it
00:56:38.260 --> 00:56:39.260
and then their collaborators
00:56:39.560 --> 00:56:40.680
don't have the right things
00:56:40.800 --> 00:56:41.460
on their computer
00:56:41.640 --> 00:56:42.580
or it doesn't quite work.
00:56:43.000 --> 00:56:43.700
You know, this is exactly
00:56:43.780 --> 00:56:44.400
the same sorts of problems
00:56:44.460 --> 00:56:45.800
I saw in math all the time.
00:56:46.740 --> 00:56:47.020
And,
00:56:47.280 --> 00:56:47.480
you know,
00:56:47.720 --> 00:56:49.160
these internet-based tools
00:56:49.440 --> 00:56:51.160
are just like so great for them
00:56:51.380 --> 00:57:07.120
You know, and it really is like what happens with like a math or science project is like if there's a lowest common denominator effect where like the technology you can use your research is only the things that the least technically competent person in your group can use.
00:57:07.500 --> 00:57:10.740
Because if you can't get get it onto their computer and get it working for them,
00:57:10.940 --> 00:57:13.840
then they won't be able to productively contribute to a project that needs it.
00:57:13.980 --> 00:57:14.580
Yeah, yeah.
00:57:14.740 --> 00:57:22.400
And you're looking over at your 67 year old thesis advisor who still thinks Fortran is like the hot stuff. And you're like, Oh,
00:57:22.580 --> 00:57:22.780
gosh,
00:57:23.340 --> 00:57:32.920
some of these people literally like it's like they have they like dictate to their secretary and like they've never touched a computer. And some of these people like contribute to the Linux kernel like regularly.
00:57:33.260 --> 00:57:33.380
Yeah,
00:57:33.570 --> 00:57:33.660
exactly.
00:57:34.240 --> 00:57:35.440
They both look like a 67,
00:57:35.780 --> 00:57:36.600
like nerdy mathematician,
00:57:37.320 --> 00:57:37.640
but like,
00:57:37.960 --> 00:57:42.420
just like the farest ends of the scale of like confidence with computers.
00:57:43.150 --> 00:57:43.240
Incredible.
00:57:44.640 --> 00:57:44.940
All right,
00:57:45.300 --> 00:57:46.160
you guys, let's call it there.
00:57:46.680 --> 00:57:48.860
There's a lot of stuff that we could talk about.
00:57:48.930 --> 00:57:49.560
I guess one really,
00:57:49.720 --> 00:57:53.460
really quick thing I just want to give a shout out to is this memory snapshot stuff that we talked about.
00:57:53.840 --> 00:57:57.460
Hood, you all are using that for basically increasing the startup time,
00:57:57.810 --> 00:57:58.740
the cold start time.
00:57:58.780 --> 00:57:59.320
We want it.
00:57:59.370 --> 00:57:59.900
We want it to go.
00:57:59.960 --> 00:58:00.680
Sorry, you're right.
00:58:01.380 --> 00:58:02.740
Increasing the speed,
00:58:03.280 --> 00:58:04.040
decreasing the time.
00:58:04.340 --> 00:58:06.160
Yes, I blended those together and that doesn't work.
00:58:06.560 --> 00:58:08.580
So just that's part of the mix,
00:58:08.740 --> 00:58:08.820
right?
00:58:09.140 --> 00:58:09.880
That's absolutely right.
00:58:10.040 --> 00:58:13.240
It's to not do that startup stuff again.
00:58:13.500 --> 00:58:13.960
Yeah, awesome.
00:58:14.540 --> 00:58:15.500
All right, final thought.
00:58:15.620 --> 00:58:19.120
I'll give you all a chance to give a quick shout out to listeners who are like,
00:58:19.400 --> 00:58:19.480
huh,
00:58:19.860 --> 00:58:21.020
this is interesting.
00:58:21.170 --> 00:58:21.920
What do I do now?
00:58:22.280 --> 00:58:22.540
Dominic,
00:58:22.920 --> 00:58:23.180
you're first.
00:58:24.420 --> 00:58:24.520
Well,
00:58:24.900 --> 00:58:25.800
I was just going to say,
00:58:25.970 --> 00:58:26.100
actually,
00:58:27.210 --> 00:58:31.220
I think the best thing for workers is IO-bound applications.
00:58:31.320 --> 00:58:33.760
if you have something that's like pushing a lot of bytes,
00:58:34.420 --> 00:58:36.140
isn't doing a lot of CPU with them,
00:58:36.640 --> 00:58:37.820
then give it a try.
00:58:38.580 --> 00:58:41.600
I think you'll be surprised how far you can go how many users you can handle
00:58:41.720 --> 00:58:42.460
even on the free tier.
00:58:43.560 --> 00:58:47.740
And yeah, just check it out type in Python workers into Google and give it a
00:58:47.860 --> 00:58:47.960
try.
00:58:48.140 --> 00:58:48.280
Well,
00:58:48.660 --> 00:58:48.780
yeah,
00:58:48.980 --> 00:58:50.940
I also say just give it a try.
00:58:51.120 --> 00:58:53.360
Because I'm already running a lot of my hobby
00:58:53.480 --> 00:58:54.980
applications in Python workers.
00:58:55.280 --> 00:58:56.740
It's working really well.
00:58:57.100 --> 00:58:58.840
So please go give it a try.
00:59:00.880 --> 00:59:01.280
If
00:59:01.300 --> 00:59:03.460
let us know in our Discord and we'll exit.
00:59:03.860 --> 00:59:06.440
And I just want to advertise to anyone out there
00:59:06.660 --> 00:59:09.320
that WebAssembly is like a really cool ecosystem.
00:59:09.500 --> 00:59:10.720
There's a lot of missing pieces
00:59:10.910 --> 00:59:12.320
in terms of like fundamental computing.
00:59:12.510 --> 00:59:14.700
So if you like operating systems,
00:59:14.930 --> 00:59:17.800
if you want to think about like how LibC works
00:59:18.040 --> 00:59:18.340
or,
00:59:18.640 --> 00:59:18.840
you know,
00:59:19.300 --> 00:59:20.560
low level details,
00:59:21.140 --> 00:59:21.320
and,
00:59:22.290 --> 00:59:24.640
you know, you feel like Linux works too well
00:59:25.090 --> 00:59:25.960
for you to get into,
00:59:26.500 --> 00:59:28.500
then like I think WebAssembly is a really great space
00:59:28.680 --> 00:59:30.360
because a lot more of that stuff is just
00:59:30.560 --> 00:59:33.160
I think no one has ever even tried to make it work.
00:59:33.540 --> 00:59:34.640
There's not that much effort.
00:59:35.140 --> 00:59:37.300
The total number of people working on it is quite small.
00:59:37.820 --> 00:59:39.620
So there's lots of open niches.
00:59:39.640 --> 00:59:42.660
And if you find something that you wish worked that doesn't work,
00:59:42.680 --> 00:59:45.540
you can just sort of wedge yourself in there and fix things.
00:59:45.960 --> 00:59:47.100
So I think it's a great space.
00:59:47.340 --> 00:59:47.700
Excellent.
00:59:48.080 --> 00:59:48.280
All right.
00:59:48.320 --> 00:59:49.460
Thank you all for being on the show.
00:59:49.880 --> 00:59:50.620
I learned a lot.
00:59:50.980 --> 00:59:52.160
I didn't point out at the beginning,
00:59:52.320 --> 00:59:52.820
I should have,
00:59:52.960 --> 00:59:55.540
that I'm a complete newbie at all this edge worker stuff.
00:59:55.780 --> 00:59:58.120
So it was really interesting to get a look into it.
00:59:58.160 --> 01:00:00.260
And it's awesome to see it come into the Python space.
01:00:00.750 --> 01:00:01.100
See you all later.
01:00:01.460 --> 01:00:01.640
Thank you.
01:00:02.460 --> 01:00:02.700
Thank you.
01:00:04.520 --> 01:00:06.660
This has been another episode of Talk Python To Me.
01:00:07.040 --> 01:00:07.760
Thank you to our sponsors.
01:00:07.970 --> 01:00:09.240
Be sure to check out what they're offering.
01:00:09.450 --> 01:00:10.820
It really helps support the show.
01:00:11.360 --> 01:00:11.800
Tomorrow,
01:00:12.320 --> 01:00:12.500
Wednesday,
01:00:12.660 --> 01:00:13.420
November 4th,
01:00:13.580 --> 01:00:15.800
we're having our first tech meetup,
01:00:16.240 --> 01:00:18.580
our live tech event as part of Talk Python membership.
01:00:19.180 --> 01:00:20.200
If you're not yet a member,
01:00:20.780 --> 01:00:20.900
well,
01:00:21.300 --> 01:00:22.560
join up and support the show
01:00:22.780 --> 01:00:25.560
and get an awesome community and experience to boot.
01:00:26.060 --> 01:00:27.500
Just visit talkpython.fm,
01:00:27.760 --> 01:00:30.100
Click membership in the nav bar and you'll be off to the races.
01:00:31.040 --> 01:00:31.780
If you are a member,
01:00:32.400 --> 01:00:37.900
we'll be talking about Talk Python in production and some really wild new ideas that I'm exploring.
01:00:38.140 --> 01:00:41.760
I think you will find both fascinating and actually really practical,
01:00:42.020 --> 01:00:42.740
but no one's doing it.
01:00:43.280 --> 01:00:44.880
So join me on Wednesday, November 4th.
01:00:44.940 --> 01:00:46.800
And if you're listening to this after and thinking, Michael,
01:00:46.960 --> 01:00:48.440
why did you just put this in here?
01:00:48.760 --> 01:00:50.940
Nobody can listen to it because most people listen to after.
01:00:51.380 --> 01:00:52.720
These tech meetups come with recordings.
01:00:53.220 --> 01:00:54.620
Just visit talkpython.fm,
01:00:54.840 --> 01:00:55.340
click on membership,
01:00:55.520 --> 01:00:57.620
and then browse past member meetups and you'll be able to get it.
01:00:58.100 --> 01:01:01.000
So hopefully either you can join live or you can join afterwards.
01:01:01.760 --> 01:01:02.300
Become a member,
01:01:02.460 --> 01:01:03.000
support the show,
01:01:03.620 --> 01:01:04.040
join the event.
01:01:04.440 --> 01:01:06.320
If you or your team needs to learn Python,
01:01:06.550 --> 01:01:09.940
we have over 270 hours of beginner and advanced courses
01:01:10.260 --> 01:01:13.680
on topics ranging from complete beginners to async code,
01:01:13.820 --> 01:01:14.080
Flask,
01:01:14.360 --> 01:01:14.500
Django,
01:01:14.920 --> 01:01:16.600
HTMX, and even LLMs.
01:01:16.900 --> 01:01:17.300
Best of all,
01:01:17.520 --> 01:01:19.200
there's no subscription in sight.
01:01:19.640 --> 01:01:21.420
Browse the catalog at talkpython.fm.
01:01:22.160 --> 01:01:24.060
And if you're not already subscribed to the show
01:01:24.300 --> 01:01:25.500
on your favorite podcast player,
01:01:25.720 --> 01:01:26.780
what are you waiting for?
01:01:27.260 --> 01:01:29.220
just search for Python in your podcast player.
01:01:29.290 --> 01:01:30.200
We should be right at the top.
01:01:30.640 --> 01:01:32.160
If you enjoyed that geeky rap song,
01:01:32.270 --> 01:01:33.380
you can download the full track.
01:01:33.590 --> 01:01:35.500
The link is actually in your podcast player share notes.
01:01:36.340 --> 01:01:36.980
This is your host,
01:01:37.200 --> 01:01:37.660
Michael Kennedy.
01:01:38.060 --> 01:01:39.120
Thank you so much for listening.
01:01:39.310 --> 01:01:40.120
I really appreciate it.
01:01:40.560 --> 01:01:41.260
I'll see you next time.
01:01:52.920 --> 01:01:55.720
I'm out.