WEBVTT
00:00:00.220 --> 00:00:02.400
Lent the entire CPython code base from scratch.
00:00:02.950 --> 00:00:06.460
It takes 0.3 seconds, three blinks of an eye.
00:00:06.860 --> 00:00:08.900
That is rough, and it's written in Rust.
00:00:09.250 --> 00:00:11.800
So are Pydantic, Polars, uv, and Granian.
00:00:12.300 --> 00:00:14.620
Rust shows up in Python in three ways.
00:00:15.140 --> 00:00:24.280
Tools that happen to be written in Rust, libraries Python itself imports and runs, and servers that themselves run Python inside of Rust.
00:00:24.840 --> 00:00:27.160
This episode is Rust for Python developers.
00:00:27.740 --> 00:00:33.160
And Christopher Trudeau is back on Talk Python to discuss Rust and his latest course up and running with Rust.
00:00:34.060 --> 00:00:38.800
The core rule is that only one thing can own a value or variable at a time.
00:00:39.240 --> 00:00:42.860
Pass it around freely in Python and the garbage collector cleans it up.
00:00:43.220 --> 00:00:45.400
Do that in Rust and you get a compiler error.
00:00:46.000 --> 00:00:52.620
This is Talk Python To Me, episode 563, recorded Wednesday, September 9th, 2026.
00:01:10.020 --> 00:01:14.720
Welcome to Talk Python To Me, the number one Python podcast for developers and data scientists.
00:01:15.240 --> 00:01:20.560
This is your host, Michael Kennedy. I'm a PSF fellow who's been coding for over 25 years.
00:01:21.100 --> 00:01:22.300
Let's connect on social media.
00:01:22.720 --> 00:01:25.780
You'll find me and Talk Python on Mastodon, Bluesky, and X.
00:01:25.960 --> 00:01:27.900
The social links are all in your show notes.
00:01:28.660 --> 00:01:32.180
You can find over 10 years of past episodes at talkpython.fm.
00:01:32.360 --> 00:01:35.600
And if you want to be part of the show, you can join our recording live streams.
00:01:35.920 --> 00:01:36.380
That's right.
00:01:36.600 --> 00:01:39.840
We live stream the raw uncut version of each episode on YouTube.
00:01:40.420 --> 00:01:44.760
Just visit talkpython.fm/youtube to see the schedule of upcoming events.
00:01:45.100 --> 00:01:48.720
Be sure to subscribe there and press the bell so you'll get notified anytime we're recording.
00:01:49.000 --> 00:01:50.560
This episode is brought to you by Sentry.
00:01:51.320 --> 00:01:54.320
You know Sentry for the error monitoring, but they now have logs too.
00:01:54.540 --> 00:02:01.680
And with Sentry, your logs become way more usable, interleaving into your error reports to enhance debugging and understanding.
00:02:02.220 --> 00:02:05.380
Get started today at talkpython.fm/sentry.
00:02:06.300 --> 00:02:14.100
And it's brought to you by the Talk Python in Production Book, an inside look at 10 years of the real-world DevOps behind the Talk Python sites and apps.
00:02:14.420 --> 00:02:17.160
Check it out at talkpython.fm/DevOpsBook.
00:02:19.560 --> 00:02:22.900
Christopher, welcome back to Talk Python To Me. Always nice to hang out with you.
00:02:23.120 --> 00:02:24.380
Yeah, thanks for having me back.
00:02:24.660 --> 00:02:27.400
I feel it's going to be a little old-fashioned, a little rusty.
00:02:30.280 --> 00:02:33.720
Yes, let's just start with the crap jokes and get them out of the way, yes.
00:02:34.160 --> 00:02:47.200
Yeah, oh yeah, this might not actually be the final Ferris joke or whatever, but no, we're going to talk about Rust for Python devs, specifically not for Rust experts,
00:02:47.740 --> 00:02:57.600
But I want to know enough Rust so that things like Pydantic, ty, if I ended up poking around them or some other extension, it would make sense, right?
00:02:57.760 --> 00:03:00.500
Or maybe write a little bit of Rust to speed up some of your Python code.
00:03:00.700 --> 00:03:07.260
It's obviously the most influential way to make Python extensions or core faster pieces, right?
00:03:07.500 --> 00:03:09.220
It seems to be the new way of doing things.
00:03:09.580 --> 00:03:20.520
And in fact, I saw something in the news this morning that one of the major CPU providers is switching to Rust for a lot of their device drivers and things like that.
00:03:20.590 --> 00:03:22.400
It does seem to be having its day.
00:03:22.740 --> 00:03:23.260
Yeah, absolutely.
00:03:23.780 --> 00:03:28.700
My joke used to be that if you switch to Rust, you're probably going to get VC funding.
00:03:28.930 --> 00:03:30.060
That was like three or four years ago.
00:03:30.720 --> 00:03:34.440
You know, that was when Astral and Pydantic and all that stuff happened.
00:03:34.880 --> 00:03:37.760
Now it needs Rust plus AI, but I think that's still true.
00:03:38.080 --> 00:03:38.620
So, yeah.
00:03:38.900 --> 00:03:39.220
Exactly.
00:03:39.460 --> 00:03:44.000
Now it's AI is the cornerstone, but if you could do Rust and AI, we.
00:03:44.460 --> 00:03:44.860
Why not?
00:03:45.200 --> 00:03:45.260
Yep.
00:03:45.500 --> 00:03:45.980
Why not?
00:03:46.100 --> 00:03:46.900
Just bring them all in.
00:03:47.320 --> 00:03:50.540
No, it's a really cool foundation for Python things.
00:03:51.060 --> 00:03:57.500
So we're going to talk about that and dive into it, compare it to Python, give some examples, give some tools, all those things.
00:03:57.940 --> 00:03:59.240
But it's been a while since you've been on.
00:03:59.460 --> 00:04:02.620
Give everyone a quick introduction of who you are and what you've been up to.
00:04:03.760 --> 00:04:05.760
So yeah, I'm a consultant.
00:04:05.820 --> 00:04:11.220
I mostly spend time working with teams either on architecture or technical processes.
00:04:12.300 --> 00:04:17.000
That tends to mean things like agile and lean and automation, CI/CD, all that kind of good stuff.
00:04:17.480 --> 00:04:21.000
And in my spare time, I still do a fair bit of teaching.
00:04:21.109 --> 00:04:27.700
And sometimes that's in person, sometimes that's virtual, and sometimes that's creating online courses for people.
00:04:28.060 --> 00:04:30.580
I spend a fair amount of my time in the Python space.
00:04:30.870 --> 00:04:32.880
I'm co-host of the Real Python podcast.
00:04:33.220 --> 00:04:36.400
So that tends to be where people, if they know my voice, that's from where.
00:04:36.760 --> 00:04:42.220
And lately I've been getting into Rust and figured you and I could chat about that.
00:04:42.420 --> 00:04:43.520
A lot of really cool things you're doing.
00:04:44.410 --> 00:04:48.220
I guess let's talk about getting into Rust.
00:04:48.760 --> 00:04:50.660
First of all, what was your background?
00:04:51.420 --> 00:04:55.340
Did you do C++, C, other compiled languages?
00:04:55.740 --> 00:04:57.600
Because it's a shift, right?
00:04:57.860 --> 00:04:59.620
Well, so this is it, right?
00:04:59.660 --> 00:05:03.360
You hear the rust is a hard language to grasp thing.
00:05:03.780 --> 00:05:08.800
And I don't, I didn't find it that way, but I don't want to diminish people who are saying that, right?
00:05:08.900 --> 00:05:11.880
Like this isn't because I'm so much smarter or anything along those lines.
00:05:12.380 --> 00:05:13.760
It's because I have that background.
00:05:14.400 --> 00:05:19.480
I was writing C when I was 13 or 14 years old.
00:05:19.640 --> 00:05:22.360
There weren't a lot of choices when I started out.
00:05:22.820 --> 00:05:34.160
So I have a grounding and, you know, I wrote device drivers and I wrote embedded systems uh don't haven't done it in a long time but i have that grounding that rust kind of expects you to
00:05:34.360 --> 00:05:47.360
have and it's closer to the machine there's less virtualization going on uh it's a lower level language than something like python uh in fact uh bob builder russ and i were talking about this
00:05:47.580 --> 00:06:02.540
because he's got into rust recently and he came from php and python so from that it's this whole other kind of experience and he was talking about the fact that he actually thinks it's made him a better Python developer because now he's thinking about memory and stuff like that a little more
00:06:02.820 --> 00:06:13.140
than you necessarily would if you've just come from Python. That's really interesting. I hadn't really thought about it because you and I are, I think, around basically the same age, at least
00:06:13.220 --> 00:06:20.940
technologically speaking. And I remember getting the C++ Primer Plus. This is so nice. C++.
00:06:22.180 --> 00:06:23.520
It's so much better.
00:06:23.980 --> 00:06:24.180
Yes.
00:06:24.360 --> 00:06:28.280
I just loved working in C++ and so on.
00:06:28.600 --> 00:06:38.840
So I've never known a world where I came to Python or JavaScript or other languages where I didn't already have that experience of, you know, void star star.
00:06:39.080 --> 00:06:39.920
What do I do with that?
00:06:40.160 --> 00:06:40.440
Exactly.
00:06:40.900 --> 00:06:41.680
These kinds of things.
00:06:42.060 --> 00:06:43.780
But, of course, that makes sense.
00:06:43.840 --> 00:06:47.800
You come from Python and PHP, and then you're like, whoa, why am I doing all this stuff?
00:06:47.940 --> 00:06:48.540
This is crazy.
00:06:48.940 --> 00:06:49.080
Yeah.
00:06:49.540 --> 00:06:51.660
And it's, you know, a big part of it.
00:06:51.680 --> 00:06:58.060
And I think the thing that folks who are coming to it from languages like Python find difficult is that whole memory management thing.
00:06:58.360 --> 00:07:00.460
And Python basically takes care of that for you.
00:07:00.720 --> 00:07:05.240
And so if you've never had to do that before, all of a sudden it's like, I have to do what?
00:07:05.420 --> 00:07:06.680
And why do I have to do that?
00:07:07.600 --> 00:07:09.600
And it can get a little persnickety.
00:07:11.180 --> 00:07:16.980
It's concept of only one thing can own a value at a time.
00:07:17.620 --> 00:07:25.100
it has objects, but the objects belong to somebody. And in Python, you just pass those things around willy nilly and you don't worry about it. And the garbage collector takes care of it.
00:07:25.500 --> 00:07:35.120
And that often turns into a compile error in Rust. And that's on one hand, it's the beauty because it makes sure that certain kinds of bugs don't happen. On the other hand, if you're not used to
00:07:35.120 --> 00:07:48.040
it, you know, there's a, there's a joke in the Rust world that there are no bugs. It's, it's all your time isn't debugging. All your time is getting it to compile. And that's because there's a lot of that, Oh, I'm just going to pass this around and wait, I can't.
00:07:48.580 --> 00:07:51.160
And so, yeah, that there's a lot of upfront work there.
00:07:51.700 --> 00:07:59.080
And I think for a new developer, that could be very frustrating because, you know, you don't, you can't play as easily.
00:07:59.300 --> 00:08:05.020
There's the threshold to getting started with something is higher because you're constantly kind of fighting the compiler.
00:08:05.440 --> 00:08:09.120
The flip side of it is their compile messages are absolutely fantastic.
00:08:09.860 --> 00:08:12.820
They, so when errors happen, they're very, very explicit.
00:08:13.180 --> 00:08:16.440
they often include something like maybe you need to do this.
00:08:17.040 --> 00:08:21.560
And from what I saw, they were right 80 or 90% of the time.
00:08:22.080 --> 00:08:32.520
So once you figure out the language, I mean like the, not the language of Rust, but the vocabulary they use for error messages, it's very much, oh, oh, okay.
00:08:32.640 --> 00:08:33.919
So that's kicking off the borrow checker.
00:08:33.919 --> 00:08:34.760
Now I understand that.
00:08:34.800 --> 00:08:34.900
Okay.
00:08:34.979 --> 00:08:35.640
I'll go fix it.
00:08:36.080 --> 00:08:39.560
So there's a few things you kind of have to learn to get to that, but it is fairly helpful.
00:08:40.719 --> 00:08:50.940
But again, that could just be my background and remembering days of C where the compile error was being triggered from three lines before it was actually talking about where the error was.
00:08:51.040 --> 00:08:56.980
And you kind of had to zone in around roughly where it was reporting it to figure out what had gone wrong.
00:08:57.600 --> 00:09:03.640
So, yeah, there's been some advances in technology since we were tapping out bits and bytes on rocks.
00:09:03.920 --> 00:09:04.000
Yes.
00:09:04.840 --> 00:09:05.140
Exactly.
00:09:05.340 --> 00:09:06.220
Making sand think.
00:09:07.320 --> 00:09:09.420
So I would like to just acknowledge it.
00:09:09.480 --> 00:09:11.740
Six minutes, 57 seconds into the recording.
00:09:11.940 --> 00:09:12.520
Borrow Checker.
00:09:12.800 --> 00:09:12.860
Yeah.
00:09:13.040 --> 00:09:14.140
Borrow Checker's been shouted out.
00:09:15.680 --> 00:09:15.900
Yes.
00:09:16.400 --> 00:09:16.500
Yeah.
00:09:18.139 --> 00:09:20.260
Maybe we should just do the quick version of that.
00:09:21.260 --> 00:09:22.700
We'll probably dig into it a little bit more.
00:09:22.920 --> 00:09:24.840
Before you do, I just want to wax poetic.
00:09:25.680 --> 00:09:28.740
Think back to the days of back in the 90s.
00:09:29.120 --> 00:09:32.660
I remember when I had my C++ Primer Plus book.
00:09:33.040 --> 00:09:35.820
And yes, folks, it was a book that was like the yellow pages.
00:09:36.520 --> 00:09:38.820
There was no, literally the internet did not exist.
00:09:39.440 --> 00:09:40.280
Well, the internet existed.
00:09:40.450 --> 00:09:46.660
There was Gopher, there was Telnet, but the World Wide Web did not exist at this time, like not for four or five more years.
00:09:46.940 --> 00:09:50.240
Anyway, I remember thinking, oh my gosh, this is so hard.
00:09:50.380 --> 00:09:51.700
This is so much work when I'm learning it.
00:09:51.700 --> 00:09:53.960
And finally, finally I got it to compile.
00:09:54.150 --> 00:09:55.960
Like, oh, we're good at compiles.
00:09:56.140 --> 00:09:58.660
Like, no, no, no, no.
00:09:59.180 --> 00:10:02.960
That's just when the actual real hard debugging, problem solving starts.
00:10:03.400 --> 00:10:08.380
But you mentioned that with Rust, that the compiler checks are a little bit stronger.
00:10:08.700 --> 00:10:13.520
They check more things like proper memory management and variable sharing and things like that.
00:10:13.590 --> 00:10:24.860
So I think while it was a eye-opener that compiling was only the beginning of my suffering when I was learning programming, I think compiling does mean more in Rust than it used to in other languages.
00:10:25.300 --> 00:10:30.060
Yeah, there's a whole family of bugs that have to do with memory management.
00:10:30.480 --> 00:10:33.260
And what's worse is they tend to be a tricky set of bugs.
00:10:33.700 --> 00:10:37.440
They're the kinds of things that will crash sometimes.
00:10:38.280 --> 00:10:47.740
So if you go back to C and how it stores a piece of text in memory, it has the, you know, like, let's say we're storing the word Talk Python.
00:10:48.000 --> 00:10:52.700
Well, we take the bytes for Talk Python and then we put a null on the end of it.
00:10:53.040 --> 00:10:56.940
And the compiler, when the code is working with it, it looks for that null.
00:10:56.980 --> 00:10:59.440
And that's how it knows that the string is finished.
00:10:59.740 --> 00:11:07.140
Well, if you accidentally write something longer than that, there'll be no null and it'll keep walking past that into the next chunk of memory.
00:11:07.540 --> 00:11:11.500
If you free the memory up, but you still have a pointer that points into that memory.
00:11:11.980 --> 00:11:12.080
Yep.
00:11:12.260 --> 00:11:14.680
But your computer will happily read that.
00:11:15.140 --> 00:11:22.740
And if you've got two strings in a row, what'll happen is you'll get the first string and then the lack of the null, and then you'll get the next string.
00:11:23.140 --> 00:11:26.080
And you might get a wrong message on the screen, but it won't crash your program.
00:11:26.460 --> 00:11:34.980
But if you get a string and then some memory that is a little more tricky, then all of a sudden you might actually be doing something like causing your program to fall over.
00:11:35.230 --> 00:11:42.720
So rust isn't bug free, but there is a category of bugs that it just doesn't let you create.
00:11:43.300 --> 00:11:53.980
And that makes it harder to compile, but a beauty to work with in the fact that a lot of the things that you might struggle with that are harder to debug are gone.
00:11:54.170 --> 00:11:54.340
Right.
00:11:54.660 --> 00:12:04.900
You know, I thought the nature of Python is the looseness of the type system and the dynamicism of it means you can get moving very, very quickly.
00:12:05.460 --> 00:12:10.620
But if you're not using a type checker, type mismatches are things you discover at runtime.
00:12:11.780 --> 00:12:15.540
All of that is very strict and very well managed in Rust.
00:12:15.700 --> 00:12:18.260
And so those kinds of problems just don't exist.
00:12:19.440 --> 00:12:20.000
That's awesome.
00:12:20.280 --> 00:12:22.680
It also takes it's also mind bending.
00:12:23.000 --> 00:12:23.360
It is.
00:12:23.360 --> 00:12:24.320
In some ways, right?
00:12:24.420 --> 00:12:37.680
It's the way you think the way a lot of the ways you think about solving problems in C++ or C or Python can be kind of the same in Rust. Some of these limitations sort of change the algorithms
00:12:38.340 --> 00:12:42.620
and the data structures that will work in those worlds. Yeah. Yep. Well, and, you know, take
00:12:42.760 --> 00:12:56.320
something as simple as an integer in Python. They're boundless, right? And if you're doing certain kinds of math, that's fantastic. There's no upper limit. Python takes care of all of that for you. It figures it out. I actually saw an article a couple of weeks ago where somebody was
00:12:56.540 --> 00:13:08.700
building a SIMD machine based on integer, based on, doing bitwise operations on massive integers, right? Thousand byte integers, and you can get away with this. And Python just happily
00:13:08.860 --> 00:13:21.940
goes, yeah, that's a really big integer. No problem. Rust is closer to the machine. So it tends to use integers the way your CPU uses integers. So you have to be aware if you're using an eight bit integer that you can't put nine bits in it.
00:13:22.300 --> 00:13:22.980
Things go wrong.
00:13:23.540 --> 00:13:27.980
Now the compiler, most of the time can catch that depends on how you're getting into that situation.
00:13:28.820 --> 00:13:30.900
And so it, it stops you from doing those things.
00:13:31.000 --> 00:13:33.000
But of course now you have to be conscious of it, right?
00:13:33.080 --> 00:13:35.640
You're making a decision when you're designing your program.
00:13:36.200 --> 00:13:38.120
How many bits am I going to store this in?
00:13:38.340 --> 00:13:45.460
And most of the time that's not a problem, but sometimes that might mean you're hitting boundaries that you wouldn't otherwise expect to hit.
00:13:45.660 --> 00:13:45.780
Yeah.
00:13:45.960 --> 00:13:48.360
And even weird things like it's signed or unsigned.
00:13:48.440 --> 00:13:51.000
Like now you can have negative numbers, not even negative one, not allowed.
00:13:51.340 --> 00:13:51.460
Yeah.
00:13:51.740 --> 00:13:54.160
That means 2.17, two, two, five billion.
00:13:55.639 --> 00:14:00.820
And interesting, like a lot of that stuff is in Python, but it's buried further down.
00:14:01.120 --> 00:14:07.800
So you can get at some of those same concepts inside of Python, but if you're just starting out, you don't go digging for those things.
00:14:08.120 --> 00:14:08.200
Right?
00:14:08.480 --> 00:14:20.660
So if you're, you know, if you're playing with the network and you're trying to pack bytes together, Python has signed and unsigned and it has those sides pieces. And all of that is very, very important if you're constructing the perfect
00:14:21.000 --> 00:14:35.320
packet. But if you're just trying to do math on the command line, well, you don't need to think about that kind of thing. Rust doesn't give you the choice. And that's not Rust specific. That's most compiled languages. They don't give you the choice, right? And it's also where the speed comes
00:14:35.430 --> 00:14:46.780
from, right? So that beauty of Python's limitless integer means there has to be machinery inside of that to handle when you make it bigger than what the current chunk of memory is.
00:14:47.360 --> 00:14:49.260
And rust doesn't have that machinery.
00:14:49.470 --> 00:14:50.720
It just says, okay, I'll crash.
00:14:51.170 --> 00:14:53.600
and so it's, it's a trade-off, right?
00:14:53.740 --> 00:15:00.820
So you don't have to care for as much, but one of the reasons Python is slower is because there's the overhead that handles these kinds of things.
00:15:00.960 --> 00:15:03.660
So one of the reasons, you know, the flip side works as well.
00:15:03.960 --> 00:15:09.340
One of the reasons rust is faster is because it's optimizing for exactly what your CPU does.
00:15:10.040 --> 00:15:12.460
And that less overhead means your code runs faster.
00:15:12.760 --> 00:15:12.840
Right.
00:15:13.000 --> 00:15:17.340
You're never going to get a Python integer into a CPU register.
00:15:17.740 --> 00:15:17.900
Right.
00:15:18.180 --> 00:15:19.860
Like it's just, I don't know.
00:15:20.779 --> 00:15:21.180
Maybe.
00:15:21.460 --> 00:15:31.240
I remember when I came to Python, I did C++ and C#, all languages that care about the shape and size of these variables, numbers, and for 15 years.
00:15:31.360 --> 00:15:34.040
And I came to Python, I'm like, I got to be doing something wrong.
00:15:34.460 --> 00:15:36.320
How do I tell it again how big the number is?
00:15:38.060 --> 00:15:41.340
Because what kind, like, is it just, is it a 64 bit?
00:15:41.540 --> 00:15:44.720
I couldn't figure out like, what is, how do I, it's going to be a problem.
00:15:44.800 --> 00:15:46.000
And then I'm like, wait, it just grows.
00:15:46.180 --> 00:15:46.640
That's crazy.
00:15:46.920 --> 00:15:47.120
Yeah.
00:15:47.440 --> 00:15:51.280
Well, I think I started with Python more as a scripting glue kind of thing.
00:15:51.700 --> 00:15:56.660
And most shell languages don't have, like Python, just don't care about those things.
00:15:56.780 --> 00:15:56.860
Right.
00:15:57.300 --> 00:16:02.120
And so when you're using it loosely to glue other things together, I don't think that really kind of ever crossed my mind.
00:16:02.220 --> 00:16:14.780
And I think I got used to the idea by that time I was doing, you know, web servers and things that were bigger, more interesting projects. And I think a lot of this is where are you coming from and how are you using the tool, right? So I think for the first couple of years I was doing
00:16:14.990 --> 00:16:28.620
Python, I was writing, you know, at max 50 or a hundred line scripts to solve some immediate little problem. And it's nice not to have to worry about that kind of thing, right? So all of this really is, you know, what is the tool and how are you using it for what you're trying to accomplish?
00:16:29.100 --> 00:16:36.880
Yeah. And I was coming from scientific programming, like building UIs and other type of tools for scientist type of thing.
00:16:38.080 --> 00:16:41.320
We care about the size of this number because science.
00:16:41.600 --> 00:16:42.580
That's all what your background is.
00:16:43.940 --> 00:16:46.260
This portion of Talk Python To Me is brought to you by Sentry.
00:16:46.670 --> 00:16:48.800
You know Sentry for their great error monitoring.
00:16:49.150 --> 00:16:50.180
But let's talk about logs.
00:16:50.840 --> 00:16:51.540
Logs are messy.
00:16:52.100 --> 00:16:57.640
Trying to grep through them and line them up with traces and dashboards just to understand one issue isn't easy.
00:16:58.220 --> 00:17:00.260
Did you know that Sentry has logs too?
00:17:00.940 --> 00:17:02.880
And your logs just became way more usable.
00:17:03.440 --> 00:17:09.300
Sentry's logs are trace-connected and structured, so you can follow the request flow and filter by what matters.
00:17:09.900 --> 00:17:18.040
And because Sentry surfaces the context right where you're debugging, the trace, relevant logs, the error, and even the session replay all land in one timeline.
00:17:18.560 --> 00:17:20.640
No timestamp matching, no tool hopping.
00:17:21.240 --> 00:17:27.300
From front-end to mobile to back-end, whatever you're debugging, Sentry gives you the context you need so you can fix the problem and move on.
00:17:27.880 --> 00:17:32.559
More than 4.5 million developers use Sentry, including teams at Anthropic and Disney+.
00:17:33.020 --> 00:17:37.960
Get started with Sentry logs and error monitoring today at talkpython.fm/sentry.
00:17:38.360 --> 00:17:40.620
Be sure to use our code, Talk Python26.
00:17:41.300 --> 00:17:42.860
The link is in your podcast player's show notes.
00:17:43.360 --> 00:17:44.840
Thank you to Sentry for supporting the show.
00:17:46.380 --> 00:17:53.560
I do, before we get too much farther jumping into it, I do want to point out that you wrote the Up and Running with Rust course over at Talk Python.
00:17:53.860 --> 00:17:54.540
So thank you for that.
00:17:54.790 --> 00:17:55.900
I really enjoy this course.
00:17:56.100 --> 00:17:58.280
It's both very educational and funny.
00:17:59.140 --> 00:17:59.660
I try.
00:18:00.120 --> 00:18:00.720
Thank you for that.
00:18:00.840 --> 00:18:05.660
The beauty of doing this kind of stuff with a sense of humor is you don't actually have to be a comedian.
00:18:05.880 --> 00:18:09.780
It's not like everything is a joke, but you can stick some humor in once in a while.
00:18:10.080 --> 00:18:17.520
So I do wonder occasionally whether, again, because of the similar generation, half the jokes might have been aimed specifically at you.
00:18:17.640 --> 00:18:21.060
So just because you find it funny doesn't mean other people will.
00:18:21.500 --> 00:18:23.660
I think they will. At least the lightheartedness.
00:18:23.740 --> 00:18:24.460
We'll see what happens.
00:18:26.460 --> 00:18:27.900
We'll come back to that at the end.
00:18:28.080 --> 00:18:29.800
This is kind of not exactly the same.
00:18:29.940 --> 00:18:33.740
It's not just that we're going to turn the course in the podcast, but it's inspired some of our concepts.
00:18:34.400 --> 00:18:38.380
Now, I want to start by talking about Rust.
00:18:39.240 --> 00:18:44.500
Just some examples before we dive into how is it compared to Python.
00:18:44.860 --> 00:18:47.680
We've touched on a little bit of that, but there's a bunch of differences and so on.
00:18:48.060 --> 00:18:53.100
But let's just appreciate some of the things like Pydantic, Ruff.
00:18:53.540 --> 00:18:56.720
Give me your thoughts on the last five years of these tools.
00:18:56.900 --> 00:19:00.660
have kind of supplanted a lot of things that were very well established in Python.
00:19:01.210 --> 00:19:06.240
So there's, there's, there's kind of three ways that Rust intersects with the Python world.
00:19:06.800 --> 00:19:10.260
And one has almost nothing to do with Python.
00:19:10.680 --> 00:19:14.520
It's they've used Rust to build tools that are Python tools.
00:19:15.310 --> 00:19:19.440
The, they could have just as easily done that for any other language, right?
00:19:19.490 --> 00:19:25.840
So when you talk about things like the linters and those kinds of things, they're, they're useful because they're fast.
00:19:26.200 --> 00:19:30.100
they are not, they're not really integrating with Python.
00:19:30.400 --> 00:19:33.420
They're a third party tool that you're using to make your Python better.
00:19:33.800 --> 00:19:42.860
And I think so some of the, some of the popularity in that has come out of the fact that a lot of the tools we've been using historically in the Python world have been written in Python.
00:19:43.290 --> 00:19:45.280
And so they've been very slow.
00:19:45.720 --> 00:19:48.300
And most of the time that doesn't matter.
00:19:48.680 --> 00:19:55.440
You know, there's that, you know, that programming world of, oh, I'll just go get another cup of coffee and it'll be done when it comes back.
00:19:55.840 --> 00:20:02.120
But your world shifts when you start seeing, you know, orders of magnitude, right?
00:20:02.160 --> 00:20:10.000
Like 10% faster, you're not going to notice it when you're starting to talk multiple zeros times faster, this changes things.
00:20:10.460 --> 00:20:15.740
And I think there were a couple of key libraries that started doing this and everyone kind of went, oh, wait a second.
00:20:16.000 --> 00:20:17.580
There's some, there's some value to this.
00:20:17.940 --> 00:20:24.440
And so I think there's been this real spring up of things written in Rust that make Python development easier.
00:20:24.960 --> 00:20:33.140
Yeah, I think the one that was most stark to me was Ruff because it was just unreasonably fast.
00:20:33.320 --> 00:20:33.460
Yes.
00:20:34.540 --> 00:20:39.180
I remember running on the Talk Python training, all the courses, like that app.
00:20:39.380 --> 00:20:41.360
And that app is much bigger than people think from the outside.
00:20:41.660 --> 00:20:47.520
It's 170,000 lines of Python or something, which is not huge, but it's not a toy, right?
00:20:47.840 --> 00:20:50.960
And so I remember running Ruff on it and it goes, found these four hours.
00:20:50.980 --> 00:20:52.280
I'm like, yeah, no, you didn't.
00:20:52.280 --> 00:20:52.960
Wait, wait.
00:20:54.240 --> 00:20:57.720
Did I not tell it to like go into the subject?
00:20:58.000 --> 00:21:00.660
It's like, did you stop after you found four errors?
00:21:00.780 --> 00:21:01.360
I don't understand.
00:21:01.580 --> 00:21:02.440
How can you be finished?
00:21:02.800 --> 00:21:03.580
How can you be finished?
00:21:03.680 --> 00:21:06.640
You like literally parse the entire thing for a hundred rules.
00:21:07.140 --> 00:21:08.980
And it was like, enter answer.
00:21:09.060 --> 00:21:10.000
I'm like, what?
00:21:10.300 --> 00:21:11.140
I just don't understand.
00:21:11.760 --> 00:21:11.920
Yeah.
00:21:12.160 --> 00:21:12.400
Yeah.
00:21:12.720 --> 00:21:16.820
And then there's something different here, you know?
00:21:17.100 --> 00:21:17.240
Yep.
00:21:17.740 --> 00:21:21.180
I also, I tend to be fairly slow to upgrade my machines.
00:21:21.640 --> 00:21:27.360
So I'm often a couple of generations out processor wise, and it's just that much more, right?
00:21:27.540 --> 00:21:34.460
Because like when you're, when you're operating on a slow machine to begin with, and then you're trying to do something like lint a couple hundred thousand lines of code.
00:21:34.880 --> 00:21:35.060
Yeah.
00:21:35.160 --> 00:21:36.120
It makes a huge difference.
00:21:36.380 --> 00:21:37.200
It makes a huge difference.
00:21:37.400 --> 00:21:37.660
It does.
00:21:37.800 --> 00:21:39.840
So one of the categories is rough, which is really tooling.
00:21:39.980 --> 00:21:41.740
And you can kind of forget that it's rust.
00:21:41.880 --> 00:21:44.680
Like it just doesn't even really, it might as well have been written in some.
00:21:45.060 --> 00:21:45.480
It could have been.
00:21:46.140 --> 00:21:46.480
Yeah.
00:21:46.680 --> 00:21:49.000
And I think that's kind of the key to this category, right?
00:21:49.160 --> 00:21:53.380
whether it's written in rust or C or anything else is kind of indifferent.
00:21:53.700 --> 00:21:54.560
It's, it's a tool.
00:21:55.120 --> 00:22:02.640
they, they're particularly with things like linters, you know, the, the, description of the Python language is publicly available.
00:22:03.180 --> 00:22:08.820
There are tools out there for compiling, for compiling language parsers.
00:22:09.260 --> 00:22:23.820
So like you can, you could have taken something, else and use that to take the definition of Python and built a thing that parses Python in any other language. It's just that Rust seems to be, has, has become the thing that is now the way to
00:22:23.820 --> 00:22:32.280
do some of this stuff. Yeah, absolutely. And just give like other numbers, you know, instead of my own personal example that people can't exactly relate to for parsing for linting and pars,
00:22:33.060 --> 00:22:45.140
evaluating this, the entire CPython code base from scratch is a 0.3 seconds. Yeah. That's, that's like enter the three blinks of an eye. Yeah. You know, that's pretty ridiculous. Yeah.
00:22:45.340 --> 00:22:46.200
So that's one category.
00:22:46.350 --> 00:22:50.980
The other category is closer to our hearts with things like Pydantic and so on.
00:22:51.260 --> 00:22:52.880
So like I said, there's kind of three modes.
00:22:53.680 --> 00:22:58.340
The second mode, and I think it's the most common one, is because Py...
00:22:58.510 --> 00:22:59.260
And this isn't really...
00:22:59.420 --> 00:23:01.900
Again, this is one of those things that's not quite Rust-specific.
00:23:02.380 --> 00:23:09.680
Python was designed from the get-go to integrate well with lower-level languages.
00:23:10.420 --> 00:23:18.100
And in fact, there's a good chunk of the Python standard library, which is really just a thin wrapper on top of the C standard library.
00:23:18.600 --> 00:23:21.460
And in fact, the older stuff in the standard library, you can actually see it.
00:23:21.740 --> 00:23:26.220
It's a little creaky in some of the naming and stuff before they kind of got consistent about how to name things.
00:23:26.330 --> 00:23:29.740
And you look at it and if you're a C programmer, you're just like, oh, I know exactly what that is.
00:23:29.960 --> 00:23:32.040
At least they don't use Hungarian notation.
00:23:32.460 --> 00:23:33.040
There is that.
00:23:33.320 --> 00:23:33.860
There is that.
00:23:34.120 --> 00:23:34.840
S, Z.
00:23:35.220 --> 00:23:36.740
What is going on here?
00:23:37.000 --> 00:23:41.100
So Python has been designed to be able to do this.
00:23:41.560 --> 00:23:50.620
And it just turns out that I think a lot of people are coding in rust have found it easier to code than encoding in c that same interface that c
00:23:50.900 --> 00:24:04.640
extensions can use can be used by rust and so as a result libraries like pydantic libraries like polars they have written their library in rust and then with a very very thin veneer there doesn't
00:24:04.780 --> 00:24:14.700
take it doesn't take a lot of effort to expose that up and then python inside of python you can treat that like any other python module so you don't actually have to be conscious of how they
00:24:14.720 --> 00:24:21.400
And as a result of this, you end up with a lot of speed up because you use that same speed that you were talking about with rough.
00:24:21.760 --> 00:24:26.340
But now Python, which tends to be a slower language, can now access this kind of stuff.
00:24:26.640 --> 00:24:41.460
So something like Polars or Pydantic, where you're doing a lot of crunching and you want them to be fast and performative, this marriage between the dynamic library on the hard drive that is a compiled thing as a Python module,
00:24:41.640 --> 00:24:45.040
that integration has been very, very handy.
00:24:45.420 --> 00:24:57.620
And I think this is the place where Rust is starting to shine because it's a cleaner, although it can be a little frustrating, it's a cleaner language than C.
00:24:59.000 --> 00:25:02.440
There's a learning curve, but there are a lot of things it doesn't let you do.
00:25:02.580 --> 00:25:03.720
There's fewer foot guns.
00:25:04.170 --> 00:25:09.520
And as a result, it's a nice marriage between a low-level language and some higher-level concepts, right?
00:25:09.760 --> 00:25:12.060
So it has things like iterators and collections in it.
00:25:12.380 --> 00:25:15.000
And so if you're coming from Python, that's like, oh, how do I deal with that?
00:25:15.080 --> 00:25:17.760
Oh, it's the same kind of for in loop and it's the exact same thing, right?
00:25:18.200 --> 00:25:27.100
So there's enough similarity to more modern languages that this is becoming a nice sort of collection of pieces that worked well together.
00:25:27.460 --> 00:25:31.700
And in the cases of things that need to be really fast, this is a real answer.
00:25:31.940 --> 00:25:32.900
Yeah, absolutely it is.
00:25:33.300 --> 00:25:44.200
And taking your Rust code and exposing it as a Python package with the tools like Pyotr3 maturing that we're going to talk about obviously they they make it super easy it comes down to just
00:25:44.420 --> 00:25:54.580
okay well you need to build more variants of your wheels rather than just a source only one yeah i think i have an analogy for these types of things so we have one third uh category i guess which i
00:25:54.580 --> 00:26:05.919
would put as granian and other things which is a web application server that runs that is built and runs in rust but then your code and python still runs so i have i have an analogy chris tell me what
00:26:05.880 --> 00:26:16.760
think here we've got the caramel dipped apple where it's caramel is python okay so we've got the caramel dipped apple where python is on the outside with like a rusty core
00:26:17.040 --> 00:26:29.740
yep that would be pydantic we have maybe python maybe it's the way anyway we've got Granian and other things where it's like more like a caramel m&m on the outside it's like a
00:26:30.120 --> 00:26:34.760
hard shell of rust and then the side it's like some sort of crunchy nugget on the outside and
00:26:34.780 --> 00:26:49.040
the caramel's inside yeah the protective hard outside is the rust which is granian and those types of things and then we've got the tools which i'm thinking of is just like a solid piece of caramel but that's maybe a little bit backwards i i would go with the tools are like when
00:26:49.160 --> 00:26:58.840
you've got a slices of apples and a bowl of caramel that you can dip it in so it's a separate thing but you can mix and match so yeah i think we're stretching we're officially stretching this
00:26:59.020 --> 00:27:05.560
analogy and now i'm hungry but i know i know we were stretching but with your your slices of apple You've, you've perfected it.
00:27:05.670 --> 00:27:05.800
Okay.
00:27:06.060 --> 00:27:11.380
So yeah, so that third category is within rust code, you can embed the Python interpreter.
00:27:11.960 --> 00:27:18.180
And so from a rust, program, you can now use an access Python.
00:27:18.590 --> 00:27:32.500
So you can kind of use Python as a scripting or, or configuration language within a larger, mechanism and something like granian where you want to actually run Python code for a web framework, that, you know, so that,
00:27:32.520 --> 00:27:43.960
that inverts the relationship we were talking about before. So yeah, so that's our three, right? So it's separate tools, the using Rust as a module inside of Python. And then the third one
00:27:43.960 --> 00:27:51.080
is using Python as a compiled library, using the interpreter as a compiled library inside of the
00:27:51.140 --> 00:28:02.760
Rust object itself. Yeah, I think that sums it up pretty well. Let's talk differences. I think kind of language differences, you know, syntax differences. It feels pretty familiar, honestly.
00:28:03.320 --> 00:28:16.640
Yeah. And I was about to say, you know, to start with differences, it might actually be easier to start with what's not different. The language itself, there are some things, obviously, if you've never, if you've never seen it before, it takes a little, and that's the same with any language,
00:28:17.220 --> 00:28:27.500
but it's not going to be completely out of nowhere. If, if I hand a Python developer some fairly clean Rust, you're probably going to have an idea of what it's doing. The loop mechanisms are the same.
00:28:27.980 --> 00:28:33.660
The if else is similar. There's no L if you actually use if else. I always scratched my head
00:28:33.780 --> 00:28:37.680
with L if in Python. I never understood it. Why you need a new keyword. It's such a verbose language.
00:28:37.900 --> 00:28:41.760
And then it's like, well, no, this we're going to. Yes. Yeah. Why that one? I have a sneaking
00:28:42.180 --> 00:28:52.680
suspicion. It might've made something early in the early days easier to parse, but rather than parsing two keywords, it gives you a keyword. A lot of the built-in mechanisms, like it's got
00:28:52.840 --> 00:29:07.700
tuples and arrays, it's got iterables and collections. So a lot of the declaration looks like typed Python. So because it is a strictly typed language and you have to specify what everything is, you do have things like the arrow that this function returns something of this
00:29:07.880 --> 00:29:19.300
type, right? So you've got that little arrow designator. But if you're used to coding in typed python which i'm not uh then you uh then then it's readable from that perspective it is yeah
00:29:19.430 --> 00:29:31.800
the types are quite quite similar uh as they you know um for the way you define them right if you have like a function or something then you just say like arrow goes to i always read that as goes
00:29:31.800 --> 00:29:38.200
to pool if it like returns a pool the variables are variable name colon type right yeah yeah and
00:29:38.220 --> 00:29:43.060
And I suspect that's probably because Python type libraries was inspired by some of this stuff.
00:29:43.180 --> 00:29:47.400
I think it probably flowed the other direction, but I'm not sure about that.
00:29:47.680 --> 00:29:55.080
So yeah, it's a lot of mixing in this, in the later, the things that got created later and typed later, like TypeScript is similar.
00:29:55.600 --> 00:29:55.800
Yes.
00:29:56.120 --> 00:29:57.560
Python types are similar.
00:29:58.360 --> 00:29:59.200
Swift is similar.
00:29:59.800 --> 00:30:05.460
I think it's the same that everybody stole from C, you know, C is the granddaddy of most of the languages we use.
00:30:05.560 --> 00:30:08.480
And then I think people started adding these kinds of concepts to it.
00:30:08.580 --> 00:30:12.100
And it's like, well, if you've come from that other language, this makes it simple.
00:30:12.400 --> 00:30:17.120
So yeah, there seems to be a sort of family of how this stuff works now.
00:30:17.440 --> 00:30:17.540
Yeah.
00:30:17.600 --> 00:30:19.220
And someone decided all the types go after.
00:30:19.680 --> 00:30:19.840
Yes.
00:30:20.200 --> 00:30:20.280
Right.
00:30:20.520 --> 00:30:22.740
And see, you would say like int function.
00:30:23.240 --> 00:30:23.320
Yeah.
00:30:23.440 --> 00:30:26.200
That, that, that has taken me a little bit to get used to.
00:30:26.500 --> 00:30:26.580
Yes.
00:30:27.340 --> 00:30:36.840
I presume it me it's meant to be making it more readable and you see the essence, like the function name and the variable names, and then the stuff describes it after.
00:30:37.180 --> 00:30:38.440
But yeah, it's always caught me off guard.
00:30:38.560 --> 00:30:40.300
I'm guessing it's because it's optional.
00:30:40.960 --> 00:30:43.820
It's optional in Python, but it's not optional in Rust.
00:30:44.220 --> 00:30:44.440
True.
00:30:44.620 --> 00:30:45.320
Or Swift, right?
00:30:45.800 --> 00:30:46.260
Yeah, true.
00:30:46.580 --> 00:30:53.200
And I'm pretty sure that Swift was inspired by, like much of Swift was inspired by Python as well.
00:30:53.340 --> 00:30:59.820
Swift's an interesting thing to look at as well, like the Playgrounds, the REPL, a lot of the stuff there.
00:31:00.000 --> 00:31:01.200
But okay, let's keep going.
00:31:01.360 --> 00:31:02.840
Some more similarities, all right?
00:31:03.260 --> 00:31:05.460
No, I think we've hit the limit of the similarities.
00:31:08.000 --> 00:31:09.420
So it doesn't take long.
00:31:10.700 --> 00:31:17.920
It's relatively readable in the same fashion, but it doesn't take long before you have to kind of peel the top layer of that onion and then you're going to get into your differences.
00:31:19.700 --> 00:31:23.560
At the heart of it, one of the fundamental concepts is it is a compiled language.
00:31:24.160 --> 00:31:31.160
This is one of those things that I think I always find sometimes frustrates students because you end up with the, well, Python compiles.
00:31:31.460 --> 00:31:33.240
I can see the code right there.
00:31:33.960 --> 00:31:38.920
Python is a interpreted language that interprets a binary file.
00:31:39.260 --> 00:31:42.540
So when Python is compiling, it's creating a binary target.
00:31:42.860 --> 00:31:45.760
That binary target is not platform specific.
00:31:46.340 --> 00:31:50.640
It is just a, you can think of it as a data file the same way, like Excel is a data file, right?
00:31:50.680 --> 00:31:53.720
So when you, when you write a formula in Excel, you don't think of that.
00:31:53.960 --> 00:31:55.880
It's not quite compiling that formula.
00:31:56.220 --> 00:31:57.180
It's storing it in binary.
00:31:57.420 --> 00:31:59.620
And then Excel is running that formula.
00:31:59.980 --> 00:32:04.120
By contrast, Rust actually compiles to machine code for your platform.
00:32:04.710 --> 00:32:10.120
So when I come, unlike a collection of Python bytecode, I can hand you that.
00:32:10.500 --> 00:32:14.560
And I don't have to worry about what platform you're running on because your interpreter is specific for you.
00:32:14.810 --> 00:32:15.920
The bytecode is not.
00:32:16.180 --> 00:32:19.880
If I hand you my binary, if you're on the same kind of platform I am, it'll run.
00:32:20.140 --> 00:32:21.280
But if you're not, it won't.
00:32:21.560 --> 00:32:27.620
And so what Rust is actually doing there is creating a binary, tight binary file that is specific to your platform.
00:32:28.240 --> 00:32:28.820
And you know what?
00:32:28.860 --> 00:32:29.140
I'm jealous.
00:32:29.680 --> 00:32:32.460
I'm jealous from a Rust and Python perspective.
00:32:32.730 --> 00:32:36.900
You can compile it and hear, hey, I'll give you a file.
00:32:36.990 --> 00:32:37.760
You can run it.
00:32:38.290 --> 00:32:38.800
You know what I mean?
00:32:39.060 --> 00:32:39.380
Yes.
00:32:40.320 --> 00:32:53.460
I know there's a lot of reasons and it's not easy, but wow, would I love a Python --build thing and outcomes just, I don't care what's in the inner core, right?
00:32:53.460 --> 00:33:04.660
You know, back to the like caramel M&Ms, but just a thing that I could put on a server, I could give to a person, I could put in Docker, and it doesn't have to have a bunch of other stuff there to make it possible.
00:33:04.930 --> 00:33:06.360
Yeah, it's a pros and cons thing, right?
00:33:06.480 --> 00:33:10.700
So your distribution is way easier, but it's very specific distribution, right?
00:33:10.740 --> 00:33:21.480
So you end up, if you're trying to aim at multiple platforms, you have to compile across all of those platforms, but the distribution of it is basically, here's the execution file, go nuts, and that's it, you're done.
00:33:22.220 --> 00:33:24.840
Or the collection of them, if you've got dynamically loading libraries.
00:33:25.340 --> 00:33:26.680
So that is definitely easier.
00:33:26.760 --> 00:33:37.180
the flip side of it is things like repls aren't technically possible because it needs to compile stuff and in fact there's some hacks out there that are kind of hilarious that are essentially
00:33:37.940 --> 00:33:49.100
repl like things that are in the background are basically recompiling a program every single time you enter a line in the repl exactly so it's actually somewhere in there yeah it's actually
00:33:49.240 --> 00:34:01.540
maintaining this program for you in order to make it look repl like and as fast as rust is i found painful i played with it once in a while and i sort of gave up and just went back to i'll have
00:34:01.550 --> 00:34:13.379
my foo.rs file and i'll do it that way so yeah i could just see the background that there's like there's a fn main curly you know brace brace curly exactly and every line of rubble is jammed and
00:34:13.460 --> 00:34:17.940
then there's a cargo build cargo run yeah that's exactly what it's doing that's exactly what it's
00:34:18.000 --> 00:34:29.500
doing this portion of talk python in me is brought to you by us i'm excited to talk about my first solo book, Talk Python in Production. It's an inside look at how we host all the Talk Python
00:34:29.720 --> 00:34:44.320
sites, APIs, mobile apps, and way more. Here's the thing. I believe most hosting stories sold to developers and data scientists are way overcomplicated and overpriced. You've heard me say you're not Google, you're not Netflix, so you shouldn't run your infrastructure the way they
00:34:44.480 --> 00:34:55.760
do. But if not that, then what? This book is both a blueprint for what I chose for Talk Python and a story arc of 10 years of running my own infrastructure from a complete newbie,
00:34:56.260 --> 00:35:06.560
apprehensive to Linux, to some pretty neat infrastructures code DevOps. It covers Docker, Nginx, Let's Encrypt, self-hosted analytics and monitoring, CDN setup, framework migrations,
00:35:06.820 --> 00:35:16.540
and a whole philosophy that I've termed stack native, keeping things streamlined, powerful, and free of cloud lock-in. And it's more than just your standard tech book. It comes with
00:35:16.560 --> 00:35:28.500
code and figure galleries on GitHub, a discussion forum, and something unique, over an hour of audio readers briefs, short conversations that bookend each chapter to prime your focus or broaden your
00:35:28.620 --> 00:35:39.640
takeaways. Oh, and 0% of this book was written by AI. Every word is mine, written over the course in high months, for better or worse. I've made the first third of the book available for free online.
00:35:40.260 --> 00:35:50.880
After that, you can grab the DRM-free EPUB and Kindle editions, and I'm working on a paperback edition as well. Please check it out at talkpython.fm/devops, or just click book in the
00:35:50.980 --> 00:35:55.780
nav bar on the website. It's a great way to support the podcast, and I hope it changes a bit how you
00:35:55.830 --> 00:36:05.300
think about running your apps in production. Okay, and so I guess, and that kind of, and we were already sort of talking about this, but this leads us to this idea of the strict typing mechanism,
00:36:05.700 --> 00:36:20.560
and that really comes out of this idea of the hardware, right? So your CPU has an idea of what an integer is. Your CPU has an idea of what a float is. There are different sized integers. How much memory is that integer going to be stored in? How much memory is that float going to be stored
00:36:20.720 --> 00:36:32.540
in? So not only is Rust specific about having these things, and you have to declare them when you're using them, but it also has that mapping to what your hardware does. So you have to make
00:36:32.540 --> 00:36:45.120
a decision between a signed integer versus an unsigned integer. So if you've never played with this kind of stuff before, when you stick a number in memory, that number represents just some bytes
00:36:45.680 --> 00:36:58.480
and your CPU is interpreting those bytes to mean something. And if you could have it, you could have it represent a positive number. And in the case of a single byte to it, that's from
00:36:58.640 --> 00:37:09.860
zero to 255. But if you want to also have negative numbers and store it in the same amount of space, well, then now you have to sort of map something from 0 to 255 into the negative space. And so you
00:37:09.960 --> 00:37:22.980
end up with like minus 127 to a positive 127 or 128. Let's not get into that. But essentially, the computer is interpreting those same eight bytes in a different way to represent a mix of
00:37:23.200 --> 00:37:31.940
negative and positive numbers. The downside of that is you can store less. You can only store up to was half the size of a positive number.
00:37:32.270 --> 00:37:41.960
In Python, you don't care about any of this, again, unless you're doing packets, but in Rust and C and other languages like it, you have to actually explicitly decide which of these you are using.
00:37:42.560 --> 00:37:47.760
The upside is in Python, you don't care, but there is so much indirection.
00:37:48.100 --> 00:37:49.760
Yes, there's a lot of overhead.
00:37:50.260 --> 00:37:50.460
Yes.
00:37:51.460 --> 00:37:53.080
And all of that overhead goes away, yeah.
00:37:53.440 --> 00:38:06.800
Not only is it indirection and that overhead goes away, But can you put a bunch of Python, if I have an array of Python numbers, how are they going to land on like L1 cache?
00:38:07.160 --> 00:38:07.460
Yes.
00:38:07.720 --> 00:38:10.900
They're not going, they're all random places out in the heap.
00:38:11.320 --> 00:38:20.900
So, I mean, there's arenas and blocks and all that stuff to try to like get them closer together, but they're still just out there rather than I've got an array of 10 numbers.
00:38:20.990 --> 00:38:21.580
Well, guess what?
00:38:21.880 --> 00:38:24.780
Those numbers are contiguous in memory sort of thing, right?
00:38:25.460 --> 00:38:29.380
And you've kind of hit on something that is also very explicit in Rust.
00:38:29.920 --> 00:38:35.320
Now, you can start Rust programming without fully understanding this, but you're not going to get very far without it.
00:38:35.820 --> 00:38:39.100
It's fairly explicit about what goes on the stack and what goes on the heap.
00:38:39.250 --> 00:38:46.260
So again, if these are new concepts for you, when your program is written, the stack is where function calls happen.
00:38:46.560 --> 00:38:55.620
So when you move from one place in code into another in memory, what happens is the new address, the place you're going to, gets put onto a stack.
00:38:56.230 --> 00:38:57.520
The old address is there before.
00:38:57.770 --> 00:39:03.680
So when your function returns, it pops off the old stuff and then knows, oh, that's now the thing at the top of the stack.
00:39:03.820 --> 00:39:05.160
That's now the address I'm going to run at.
00:39:05.410 --> 00:39:12.980
And so when you add variables into, when you add parameters to your function, those are also getting put on the stack.
00:39:13.240 --> 00:39:23.860
So you end up with this little stack frame, which is the place you're going to be running and the data that goes with that function. By contrast, the heap is sort of a general space, and that is
00:39:24.040 --> 00:39:38.840
where you allocate things from memory. And longer lived things or things that you're passing around between functions tend to end up being created in the heap. And how Rust does memory management, we'll gloss over it for now, we'll get into it a little more later, I think, but how Rust does
00:39:38.860 --> 00:39:48.380
manage memory management differentiates between these two kinds of things and so again this is one of those things you you know you only think about the stack in python when it fails because
00:39:48.740 --> 00:40:00.500
you get the stack trace but otherwise you more or less ignore it whereas here once you start playing around with passing objects around whether or not you're being explicit about it that concept of am
00:40:00.500 --> 00:40:11.140
i in the stack or am i in the heap and who owns it becomes very very important and and this isn't new to Rust. This has been there in compiled languages. This is a fundamental way how modern
00:40:11.420 --> 00:40:17.840
computing machines work, but it's more exposed in Rust than it is in Python. You know, the thing I
00:40:17.980 --> 00:40:28.780
think is such, to me, it was a little ironic is Python, you don't worry about pointers. You don't worry about that. You just work. And then like other languages like C, Rust, C#, you talk
00:40:29.000 --> 00:40:38.840
stack, you talk heap, you talk pointers, you can dereference. Python is more pointer heavy than any of those languages because literally everything is in the heap. There's nothing that's even a
00:40:38.920 --> 00:40:47.340
number is a pointer to a thing in the heap, right? Well, this is how Python got away with not having pointers. It was everything's a pointer, so we don't have to differentiate. Yeah. Yeah, exactly.
00:40:47.700 --> 00:40:55.760
That's like, if everything is a pointer, we can just treat them all like variables, right? And that made the programming simple and you don't have to think about it. But conceptually, Python,
00:40:56.140 --> 00:41:04.680
everything is in the heap. Everything is a pointer. Even the number one, it's a flywheel pattern. I
00:41:04.700 --> 00:41:05.960
And even that's insane, right?
00:41:06.140 --> 00:41:06.820
Like that, yeah.
00:41:08.060 --> 00:41:12.880
I have three copies of 254, but I only have one copy of two.
00:41:14.120 --> 00:41:14.200
Sure.
00:41:15.880 --> 00:41:16.680
That is really.
00:41:17.020 --> 00:41:19.340
Don't stop to think about it because, yeah.
00:41:20.180 --> 00:41:20.300
Yeah.
00:41:20.480 --> 00:41:22.860
For people listening are like, okay, they've gone off a rail.
00:41:23.100 --> 00:41:25.020
Like they're a little, what are they talking about?
00:41:26.000 --> 00:41:34.180
An optimization in CPython is the numbers, I think maybe negative five to 255, some range like that.
00:41:34.420 --> 00:41:34.520
Yeah.
00:41:34.620 --> 00:41:35.920
They're pre-allocated.
00:41:36.020 --> 00:41:40.460
And every time you type a literal number like 72, it's the same number.
00:41:40.740 --> 00:41:49.620
It just all points at the immutable number 72 rather than creating, you know, like whatever the eight byte or four byte chunk of it is on the stack.
00:41:50.040 --> 00:41:50.180
Yeah.
00:41:50.520 --> 00:41:52.580
I appreciate it makes it faster, but it's just funky.
00:41:52.660 --> 00:41:53.460
Yeah, it's weird.
00:41:53.700 --> 00:41:55.700
Yeah, it's something you don't want to think about too much.
00:41:56.300 --> 00:42:03.920
A couple sort of cosmetic things, which again, if you're from Python and Python's your first language might take a little to get used to.
00:42:04.360 --> 00:42:18.480
one is brace brackets so uh like most programming languages space is not important uh and that takes i i remember it taking me a while to get used to that switching to python so i have uh patience and
00:42:18.660 --> 00:42:24.280
sympathy for people who started in python and have to go the other way this is pretty typical of most
00:42:24.600 --> 00:42:38.140
programming languages uh the it makes the parser's life easier um and i think after having coded in Python for almost two decades, I think I've come down on the side of screw the parser.
00:42:38.600 --> 00:42:43.020
So it's a little bit taking a little used to for me to get back to it.
00:42:43.060 --> 00:42:46.740
But yeah, you, you put things in brace brackets to denote them.
00:42:47.120 --> 00:42:47.180
Yeah.
00:42:47.300 --> 00:42:51.500
I mean, look, the job of the parser is to make your life easy.
00:42:51.840 --> 00:42:52.620
Not the other way around.
00:42:52.760 --> 00:42:59.400
So I get, but I have run into situations where some little bit of formatting has been off.
00:42:59.900 --> 00:43:00.120
Yes.
00:43:00.320 --> 00:43:14.080
On my indentation and a reformat the code broke the code because maybe I had three indentations, three spaces instead of four for who knows, maybe I hit the delete button on accident or something weird like that.
00:43:14.340 --> 00:43:16.800
And I said, oh, well, look, this didn't line up right.
00:43:16.880 --> 00:43:18.480
Like I'll just hit like reformat code.
00:43:18.520 --> 00:43:20.440
And it's like, oh, well, that needs to go back to the left.
00:43:20.840 --> 00:43:23.300
And it's like changed actually how it works.
00:43:23.560 --> 00:43:23.640
Yep.
00:43:23.940 --> 00:43:27.840
So copy and paste is problematic in Python.
00:43:28.080 --> 00:43:28.200
Yeah.
00:43:28.500 --> 00:43:29.400
It's really problematic.
00:43:29.840 --> 00:43:32.740
And with the braces, like it could just have no indentation.
00:43:32.810 --> 00:43:33.900
It could be all gnarly.
00:43:33.910 --> 00:43:34.960
It could be minified, whatever.
00:43:35.050 --> 00:43:39.960
You just hit reformat and boom, it's reliably put back together well.
00:43:40.400 --> 00:43:45.400
So I'm going to give Python an 80% plus, 20% minus.
00:43:45.620 --> 00:43:47.340
I agree that it's nice.
00:43:47.600 --> 00:43:51.260
It's not there, but it's not just there is value to it.
00:43:52.340 --> 00:43:53.940
Structural correctness value to it.
00:43:54.000 --> 00:43:54.100
Yep.
00:43:54.290 --> 00:43:54.400
Yep.
00:43:54.780 --> 00:44:02.660
I also, you know, it forces programmers to behave themselves, which if you don't get your spacing right, your code doesn't work.
00:44:02.820 --> 00:44:04.300
It kind of makes the spacing consistent.
00:44:04.840 --> 00:44:05.240
Yes, exactly.
00:44:05.580 --> 00:44:14.660
That was what it was optimized for is like, you're going to make your code readable because you have to write it in a way that its structure and its readability match.
00:44:14.740 --> 00:44:15.580
And that's beautiful.
00:44:16.080 --> 00:44:18.980
But it is a little, it can have problems.
00:44:19.340 --> 00:44:19.460
Yeah.
00:44:19.680 --> 00:44:28.720
And being a veteran of the tabs versus spaces war of the nineties, eliminating that at the, at the syntax level is kind of interesting.
00:44:29.040 --> 00:44:33.340
It really is like, and you know what, there was a gosh, what PyCon was it?
00:44:33.340 --> 00:44:40.920
I think it was one Cleveland, maybe three, four years ago, there was a PyCon where one of the vendors clearly came.
00:44:41.170 --> 00:44:47.080
It was a tool vendor that came from all the, they weren't Python specific, but they made tools for Python people.
00:44:47.200 --> 00:44:51.800
and I would even maybe shout them out, or I'd call them out, but I don't even remember what it was.
00:44:52.280 --> 00:44:55.760
But they were giving away t-shirts that said tabs versus spaces.
00:44:55.890 --> 00:44:58.180
And you had to pick, I'm team tab, I'm team spaces.
00:44:58.760 --> 00:44:59.800
I'm like, what are you doing?
00:44:59.960 --> 00:45:04.460
Does nobody know that this literally is not even a choice in this language?
00:45:04.740 --> 00:45:05.660
Why are you here?
00:45:06.420 --> 00:45:12.280
It's a fun gag, but anyone on not team spaces is not going to run.
00:45:12.360 --> 00:45:13.280
What is wrong with you?
00:45:14.320 --> 00:45:18.920
Yeah. That's a team spaces versus teams. My code won't compile. Yeah.
00:45:21.440 --> 00:45:21.960
Yeah.
00:45:22.530 --> 00:45:32.660
An interesting side effect of this that I kind of like in this language. I don't know if I've seen it elsewhere. So like most languages, it has this rust has this concept of a statement versus
00:45:32.770 --> 00:45:44.640
an expression. Most things are expressions. And in fact, your brace bracket is the definition of a new expression. And as a result of that, the end of the brace bracket can return something. So you
00:45:44.670 --> 00:45:57.580
can do an assignment to a collection of code in a brace bracket. So this ends up being kind of like an inline function. and so that's kind of interesting to me and it, it, compiles down
00:45:57.800 --> 00:46:04.100
beautifully. it's, it's got that, and then it does this weird thing where it's got implicit
00:46:04.100 --> 00:46:16.780
returns. And so I really wish they had not done the implicit return. I am never ever going to be on team implicit return. I just can't. It drives me nuts. and, but the idea of having,
00:46:16.900 --> 00:46:27.840
arbitrary expressions through the brace brackets is kind of elegant. So, so yeah, one point up, one point down, whatever. and then, you know, there's some odd odds and ends, right? It's, it's,
00:46:27.900 --> 00:46:38.280
uh, FN instead of def, which quite frankly, as soon as I saw it was like, yeah, that actually makes an awful lot more sense. That tells me what it is. Def for define, define what? What am I
00:46:38.380 --> 00:46:43.880
defining? FN? It's a function. That makes sense. And then one of the other things that I kind of
00:46:44.040 --> 00:46:55.520
liked a lot is, so they release a lot more frequently in Rust. So it's, there's a new, a new version coming out every six weeks, which when you come from the Python world,
00:46:55.620 --> 00:47:06.140
that sounds insane, right? Like how do you stay on top of this? But they've got this separate concept from versions that they call additions. And an addition is a three-year cycle and things
00:47:06.440 --> 00:47:18.220
stay compatible within the addition. And what's more, not only do they do that, but the compiler is able to compile to older additions. So when you compile the code, you can actually say,
00:47:18.300 --> 00:47:30.140
I want to be using an older addition. And so they have basically this forever concept of backward compatibility. So now it's still a young enough language. I suspect at some point they may
00:47:30.210 --> 00:47:36.040
give up on that. cause this, this to me smells of maintenance hell. It's fine when there's three
00:47:36.280 --> 00:47:41.440
editions. What if there were 35? Yeah. but for the, for the time being, although there's been a
00:47:41.580 --> 00:47:53.480
fair amount of change in the language, in the last few years, you're not screwed by it. And it's not this constant race to stay on top of it. You can just change the edition target and you're
00:47:53.520 --> 00:48:06.820
fine. So I kind of like the idea. I think it would be kind of neat if the Python compiler, maybe, you know, if I was, I guess the changes in Python aren't as bad, so maybe it's not as extreme,
00:48:07.200 --> 00:48:21.859
but I don't know. This just sort of appealed to me. Yeah, it does to me as well. I love the freshness of it. I just got a new version of Rust this morning. I was trying to update my libraries and tools, and it said there's a new version of Rust. Yes. Okay. So I think that might be a good
00:48:21.880 --> 00:48:29.980
good time to maybe talk about like getting started and so on as maybe start by installing yeah uh so
00:48:30.480 --> 00:48:40.200
uh the good news is if you're in the unix world uh some sort of Linux or mac os this is uh this is a breeze you go off to the website you copy and paste the command onto the terminal and you're
00:48:40.280 --> 00:48:50.380
more or less done uh we do the thing that we normally do we run arbitrary code from the internet that's right as root on our machine i'm sure it's fine yeah it's fine uh if you go off to
00:48:50.200 --> 00:48:51.740
So rest up, rustling.org.
00:48:51.940 --> 00:48:53.920
there is right on the front page.
00:48:53.980 --> 00:48:56.480
There is a little shell command that you install.
00:48:56.960 --> 00:49:03.020
This actually installs a tool called rust up rust up is kind of like pie M and that it handles installation updates of the language.
00:49:03.480 --> 00:49:10.220
It install, it installs, rust C, which is the compiler and more importantly, cargo, which is the tool.
00:49:10.420 --> 00:49:13.340
That's kind of like uv that is what you actually use.
00:49:13.360 --> 00:49:15.400
You almost never call rust C directly.
00:49:15.700 --> 00:49:19.300
So rust up handles the version management of all that kind of stuff.
00:49:19.960 --> 00:49:26.000
And once you've got that going, then you use cargo to create a new project.
00:49:26.760 --> 00:49:28.660
Again, very uv-esque here.
00:49:28.700 --> 00:49:31.980
So you would say, you know, if I'm doing hello world, it would be cargo new hello.
00:49:32.660 --> 00:49:36.800
That creates a cargo.toml, which is the equivalent of pyproject.toml.
00:49:36.960 --> 00:49:38.400
It creates a source directory.
00:49:39.260 --> 00:49:43.880
By default, it creates a git repo and a git ignore file, which drives me nuts.
00:49:43.920 --> 00:49:45.420
And I turned that off as soon as I could.
00:49:45.620 --> 00:49:46.880
I want to be in control of that.
00:49:47.080 --> 00:49:47.620
Don't do it for me.
00:49:48.260 --> 00:49:53.140
And it creates a little stub main file, which actually has a function in it.
00:49:53.610 --> 00:49:58.000
So you actually can run cargo new hello and you get a compilable program.
00:49:58.390 --> 00:50:05.400
Then you write your rest and you run cargo run and cargo run builds and runs the code for you.
00:50:05.550 --> 00:50:12.160
Now, because it's a compiled language, the result is a target that goes into the target directory.
00:50:12.690 --> 00:50:16.920
You could run that explicitly, but it's buried like three directories down.
00:50:17.200 --> 00:50:20.260
So rather than do that, you just call run and it does it for you.
00:50:20.980 --> 00:50:25.100
And there are flags you can use it to go from debug mode to release version.
00:50:25.780 --> 00:50:30.480
Your debug tends to be about 30% larger because it includes debug information.
00:50:32.100 --> 00:50:32.820
While the production mode...
00:50:32.820 --> 00:50:35.540
That's par for the course for people who use those things.
00:50:35.720 --> 00:50:39.140
Yeah. And in fact, on Windows, it produces...
00:50:39.140 --> 00:50:41.080
I think in Windows, it's packaged as a separate file.
00:50:42.060 --> 00:50:46.800
The debug info is in a separate file, which is, again, a standard sort of Windows thing to do.
00:50:47.100 --> 00:50:55.820
Yeah, Windows often you can put, I forgot what they're called, but there's like a debug symbols that is a file that you can put like next to a DLL or an exe and it'll pull that in.
00:50:56.030 --> 00:50:58.600
And so it handles all of that kind of good stuff for you.
00:50:59.780 --> 00:51:04.540
And then this is then the thing that you would distribute if you were trying to distribute it.
00:51:05.599 --> 00:51:10.380
There's a command for building on its own and then the command for run both builds it and runs it.
00:51:10.680 --> 00:51:18.440
One of the things I'm still not quite used to is it outputs some information from the build before it actually runs the code.
00:51:18.710 --> 00:51:23.280
So you get two or three lines of info before you actually see the output from your program, which drives me nuts.
00:51:23.800 --> 00:51:29.920
But there is a dash queue to tell it not to do that so that if I'm running it, I don't want to see your compiler stuff.
00:51:29.990 --> 00:51:32.180
I want to actually have it run unless something went wrong.
00:51:32.480 --> 00:51:36.500
So yeah, cargo really is the key to doing all of this kind of stuff.
00:51:36.840 --> 00:51:42.660
Like uv, it also manages what they call crates, which are the Rust equivalent of wheels.
00:51:43.200 --> 00:51:48.300
There is a crates.io is the equivalent of PyPI.
00:51:49.040 --> 00:51:51.480
And you can write libraries and upload them there.
00:51:51.880 --> 00:51:59.760
And like with Python, this is a fairly robust community that's writing and trading code here.
00:52:01.780 --> 00:52:04.520
331,019 crates in stock.
00:52:04.920 --> 00:52:05.920
We look at PyPI.
00:52:06.600 --> 00:52:09.440
think we're at 750 the last time I looked.
00:52:09.790 --> 00:52:10.580
I haven't looked for either.
00:52:12.140 --> 00:52:14.280
889,000, 890,000.
00:52:14.570 --> 00:52:18.440
So there are more, but I don't think that is necessarily the core metric.
00:52:18.650 --> 00:52:29.140
No, and it's also not a fair comparison because proportionately the number in crates would actually seem smaller to a Python developer.
00:52:29.230 --> 00:52:34.380
And what I mean by that is if when you're coming from the batteries included world, yeah, there aren't a lot of batteries in Rust.
00:52:34.920 --> 00:52:39.000
So something as simple as like a random number, that's a crate.
00:52:39.860 --> 00:52:44.100
And they've done this to try and keep the footprint small, which I kind of understand.
00:52:44.900 --> 00:52:51.480
For somebody who's starting out, this can be a little, so like I had this, I'm paranoid, right?
00:52:51.700 --> 00:52:54.280
So I want to know where my code is coming from.
00:52:54.680 --> 00:52:57.460
If I'm in the Python world, I trust the standard library.
00:52:57.530 --> 00:53:00.180
If I stick to the standard library, I know I have a degree of safety.
00:53:00.520 --> 00:53:05.360
Once I step outside of the standard library, I want somebody to tell me they've used it and they trust it.
00:53:05.820 --> 00:53:09.840
And, you know, for certain kinds of libraries, there's enough press that you can kind of get the idea.
00:53:10.150 --> 00:53:14.880
I haven't yet quite figured out how to get that information in the Rust world.
00:53:15.480 --> 00:53:26.660
And because things like random, which you use all the time, are actually crates, you kind of have to do a little bit of the, there's a little more rolling the dice on do I trust this code to use it kind of thing going on there.
00:53:27.140 --> 00:53:29.880
But I suspect that's still my newness to the community.
00:53:30.140 --> 00:53:35.540
Yeah, perhaps. You know, Chris, just because you're paranoid doesn't mean they're not after you.
00:53:35.800 --> 00:53:38.160
Yep, that's right. That's exactly right.
00:53:38.500 --> 00:53:43.020
And with the supply chain stuff, it means, I mean, it's crazy.
00:53:43.380 --> 00:53:46.280
In the world of the internet, they are out to get you. Yes, without a doubt.
00:53:47.500 --> 00:53:59.220
Oh my gosh. And sometimes you hear the pounding on the door. You're like, oh my gosh, go away, please don't do that. Let's just like reflect for a minute. We talked about like cargo crates and all
00:53:59.200 --> 00:54:13.440
all these things, we've seen a big revolution in Python packaging, deployment, flexibility, project management, all of those things. And much of that has actually come from the Rust side. A
00:54:13.600 --> 00:54:27.180
lot of the tools like uv and others are seriously inspired by cargo, the crates, and these types of things. But this was built in a world where PyPI already existed and npm already existed. And they
00:54:26.980 --> 00:54:37.040
could go really good. Ooh, that's not good. Let's do it this way. Right. So there's like this sort of interplay or this circling of these two worlds. Yeah. It's, you know, without,
00:54:37.410 --> 00:54:49.800
I'm not trying to start a flame war, but the decision that the PSF made that, managing packages wasn't really part of the language and that we should have this plethora of third-party
00:54:50.020 --> 00:55:03.160
tools to do that. I think that was a mistake. And I think the Rust people recognize that and decided to bundle this in. it's, it's a lot cleaner and there's a lot less wondering of what's
00:55:03.260 --> 00:55:16.620
going on. and, now in defense of rust, sorry, in defense, I don't know who I'm defending. Nevermind. I'm not sure whatever I'm going to defend. I'm not going to defend. Uh,
00:55:16.950 --> 00:55:28.440
the, I think the target for rust is simpler. And, part of the thing that happened in the python world is because of that dynamicism it creates all these other kinds of complications
00:55:29.170 --> 00:55:35.500
um so yeah it's right my package also requires a fortran compiler exactly yeah right whereas
00:55:35.650 --> 00:55:41.140
because you're compiling these things down you some of that stuff goes away so so yeah it's it's
00:55:41.300 --> 00:55:55.780
it's a challenge i agree but also wheels do exist now yep in the python world created them and they didn't before and that was like a super hard problem because yeah everything needed like all these bespoke tools just to install something interesting. And then they said, no, no, no,
00:55:55.900 --> 00:56:08.860
let's just make wheels. You can just have like, why do we have to make everyone recompile everything from source? So they kind of got there. Another thing I think- They're making progress. Yeah, no, they're making progress. Yeah. Another thing I think is interesting around this is
00:56:08.860 --> 00:56:21.160
you talked about the sparseness of the standard library equivalent of Rust. I feel like Python batteries included the richer standard library. It is that way because PyPI didn't exist.
00:56:21.560 --> 00:56:27.220
The concept of a package manager didn't exist when Python, you know, and honestly, like what was 91?
00:56:27.660 --> 00:56:28.520
Like the web didn't exist.
00:56:28.690 --> 00:56:32.640
Like getting stuff afterwards was really, really hard.
00:56:32.840 --> 00:56:34.920
If it were easier, they may have made different choices.
00:56:35.400 --> 00:56:35.520
Yeah.
00:56:35.660 --> 00:56:38.360
It's, it's a consequence of this language being around since the nineties.
00:56:38.480 --> 00:56:38.540
Right.
00:56:38.760 --> 00:56:45.160
So the decisions up front were, and what, and what it was designed for versus what it's grown into.
00:56:45.360 --> 00:56:57.980
you know, that's, we should all be, as software developers, we should all be so lucky as having our initial designs become questionable because 35 years later, people are still using our software
00:56:58.480 --> 00:57:03.260
all over the planet. Yeah. If people want to criticize mine because it's so popular in 30
00:57:03.380 --> 00:57:14.780
years, I'd be happy as well. Yeah, exactly. All right. We've got a little bit of time left, but it's not a ton. I think let's focus on one more section and that would be, how do I go from
00:57:15.180 --> 00:57:20.760
Rust land to Python land. So there are different libraries for doing this. The most common one out
00:57:20.900 --> 00:57:28.480
there is a crate called Py03. And essentially what this does is provide you with the tools
00:57:29.060 --> 00:57:36.420
to align your Rust code as if they are Python objects. And then there are a couple other tools
00:57:36.920 --> 00:57:51.480
that you can use to actually do the packaging part. So what Py03 does is it defines the interface the compiled object, which is a dynamic library, so a.so file or a.dll, and then does that in
00:57:51.850 --> 00:58:02.780
compliance with Python's ABI. And then there are tools out there that you can use, which will put those inside of a virtual environment so that Python can see them. And then in Python, you can
00:58:03.020 --> 00:58:08.380
load that code that you wrote as if it were a regular Python module written in Python.
00:58:09.000 --> 00:58:12.600
The how Py03 does this is a couple different things.
00:58:12.940 --> 00:58:17.600
One, it has Rust objects that are compatible with the Python objects.
00:58:17.920 --> 00:58:22.220
So as an example, Pyint is a Rust object that represents a Python integer.
00:58:22.580 --> 00:58:30.840
So if you need access inside of your Rust code to the integer inside of the Python space, this acts as a mechanism to get at it.
00:58:31.100 --> 00:58:33.680
It will also map Rust concepts.
00:58:34.240 --> 00:58:47.000
So rather than using pyint, you can just use, say, a int32, and py03 will take care of mapping that up to the Python integer when Python's using it in the Python side of the world.
00:58:47.400 --> 00:58:55.240
The other thing that it does is Rust has a mechanism that is macros for changing how things get compiled.
00:58:55.740 --> 00:59:00.760
And py03 ships with a bunch of macros that essentially you attach to something like a function.
00:59:01.140 --> 00:59:06.340
So if you want the function or a class to be available to Python, you wrap it with one of these macros.
00:59:06.860 --> 00:59:12.780
It's just a regular Rust function, but the macro is what does the mapping and makes it available.
00:59:13.130 --> 00:59:18.120
So with the right use of the macro, you can say things like, you know, this is my function.
00:59:18.280 --> 00:59:19.060
It's got three arguments.
00:59:19.720 --> 00:59:21.620
These arguments need to map to this, et cetera.
00:59:22.120 --> 00:59:26.960
And essentially what happens when you compile it is all of this gets put into a.so.
00:59:27.420 --> 00:59:38.500
And then you use tools like Maturin or others that then put that into a virtual environment and to handle the packaging side of things so that your Python code can use it.
00:59:38.860 --> 00:59:47.840
And from Python's perspective, once that's installed in the right place, you just import foo from bar as you would with any other module and you've got access to it all.
00:59:48.180 --> 00:59:48.400
Interesting.
00:59:48.680 --> 00:59:51.480
Now, it doesn't have to be all or nothing as well.
00:59:51.820 --> 00:59:54.720
For example, remind me how to do this because I forgot how to do it.
00:59:54.820 --> 01:00:01.260
but you can create a project that has some Rust code and some Python code and then build that into a wheel.
01:00:01.760 --> 01:00:09.440
But you could say only part of my code is gonna be Rust and the rest of it that's not performance critical, that's all Python all day long.
01:00:09.700 --> 01:00:22.540
Yeah, so for example, if you look at, if you pay close attention when you install Polars, you're actually getting two wheels, one of which is a universal wheel, which is because it's universal, it only contains Python code.
01:00:22.860 --> 01:00:37.500
And the other of which is it's figured out what platform you're on and gives you the actual compiled Rust version of the Polars library. So they've kind of got these two things going on. Now, I don't know Polars well enough. I've never looked at their source code, so I don't know what they've
01:00:37.560 --> 01:00:47.520
got in each one of those packages, but they've built something that is comprised of both of those things. In their case, it's in two separate wheels. It doesn't have to be. And essentially,
01:00:47.820 --> 01:01:02.360
you're using a tool like Mature and it takes care of this for you. So if you're after a, if you're after building a library where there's a part of it that has to be very performant, but you want to write most of it in Python because, you know, it's easier to code in,
01:01:03.140 --> 01:01:06.480
then there's, you basically do that and Maturin will let you bundle all of that up.
01:01:07.380 --> 01:01:21.380
And this is no different than any other plugin mechanism. It's just that these are the tools that Rust provides to build those kinds of plugins. So if you think of tools like Polars or NumPy or any others that do this kind of concept where some of it's written in a lower
01:01:21.400 --> 01:01:23.740
level language, I O three just lets you do that.
01:01:23.920 --> 01:01:33.320
I think there's a lot of, a lot of low hanging fruit for people to go apply a profiler to their code and say, no, it really only matters at least 20 lines of code here.
01:01:33.460 --> 01:01:33.520
Yeah.
01:01:33.700 --> 01:01:34.220
What if?
01:01:34.580 --> 01:01:34.740
Yeah.
01:01:35.160 --> 01:01:42.580
The challenge you have to pay is every time you do this, you're crossing a boundary and there is a cost to crossing that boundary.
01:01:43.020 --> 01:01:56.140
So, there, if you're writing the code in such a fashion that you're constantly going back and forth or your objects are constantly going back and there's overhead to that so writing in and rust doesn't guarantee that it will be faster
01:01:56.740 --> 01:02:10.300
could make it slower it could make it slower like with everything uh but if you're doing something you know it's something like polar's where you're doing big number crunching uh and you're you know you're calling into the api and then letting it crunch and then it spit another answer out then
01:02:10.500 --> 01:02:20.920
yeah you can you can see a significant speed up yeah or pydantic where it comes in as json anyway and it's got to be transformed to something, let that happen in Rust and then talk to it.
01:02:21.260 --> 01:02:23.080
So yeah, this is really good.
01:02:23.500 --> 01:02:29.860
I'm going to have Pablo and Laszlo on to talk about the new profiler that's in 3.15.
01:02:30.140 --> 01:02:31.540
That's really interesting, the profiling module.
01:02:31.980 --> 01:02:37.200
One of the things that's fascinating about that, I don't have anything in production in 3.15.
01:02:37.360 --> 01:02:40.900
All my stuff's in 3.14 or lower, like older.
01:02:41.280 --> 01:02:49.760
Now, one of the things that's cool about the new profiler is you can attach it to stuff running in production, profile it, and then walk away.
01:02:49.850 --> 01:02:52.120
You know, like, hey, let's just go, it's running.
01:02:52.280 --> 01:02:54.760
A bunch of people are using this app, like it's an API or something.
01:02:55.140 --> 01:02:58.880
Let's just hook onto it for 30 seconds, get some data and step back.
01:02:59.150 --> 01:03:05.200
And then maybe you could look at, oh, actually, if we could just make this one part faster, that would really be a big deal.
01:03:05.290 --> 01:03:08.100
So I think the possibility for this is just getting easier.
01:03:08.420 --> 01:03:16.380
Yeah, well, and, you know, the general advice I give folks when I talk about optimization is don't and then measure, right?
01:03:16.760 --> 01:03:21.320
So when you're trying to figure it out upfront, it doesn't matter how good you are at this.
01:03:21.420 --> 01:03:24.640
You tend to make the wrong assumptions eventually.
01:03:25.200 --> 01:03:29.940
And so, yeah, build something, then profile it, and then figure out where you're spending all your time.
01:03:30.260 --> 01:03:32.660
Yeah, I've had a couple of experiences.
01:03:32.940 --> 01:03:39.740
I won't go into the details of it, but I've told it a time or two way, way back in the day where I was so wrong.
01:03:40.040 --> 01:03:40.100
Yep.
01:03:40.580 --> 01:03:43.060
So wrong about what was slow and what was fast.
01:03:43.170 --> 01:03:47.200
And if I had just pursued my intuition, it would have been months of bad choices.
01:03:47.670 --> 01:03:47.860
Yeah.
01:03:48.400 --> 01:03:58.700
And there's a concept called Amdahl's Law, which is essentially, I'm going to oversimplify it, but if your code is spending 10% of its time in that place,
01:03:59.859 --> 01:04:06.720
speeding that up by 2x is only ever going to get you a 10% gain because your code's spending the other 90.
01:04:07.380 --> 01:04:10.260
There's a diminishing return aspect to it as well.
01:04:10.600 --> 01:04:20.860
And as programmers, I think we often get tied up in the, oh, wouldn't it be cool if I made this code three times harder to read and it'll be, you know, half a millisecond faster.
01:04:20.970 --> 01:04:22.240
And how often do you call that?
01:04:22.440 --> 01:04:22.940
Once a year.
01:04:23.170 --> 01:04:23.720
Oh, okay.
01:04:23.980 --> 01:04:30.160
Well, there's a month of your life you got back in order to optimize by a millisecond, right?
01:04:30.380 --> 01:04:33.060
Where you got to find the stuff that is actually causing the problem.
01:04:33.600 --> 01:04:33.740
Yeah.
01:04:34.050 --> 01:04:36.100
You gave a 50% speed up example.
01:04:36.320 --> 01:04:38.860
Like, let's take it to an insane level.
01:04:39.120 --> 01:04:42.880
20% of your code, 20% of time you spend in some bit of code.
01:04:43.120 --> 01:04:49.620
If you could make it infinitely faster, the best you're going to achieve is your program is going to be 20% faster.
01:04:50.260 --> 01:04:53.660
You know, maybe, oh, I was running this on a single CPU thread.
01:04:54.040 --> 01:04:59.540
I'm going to actually get a GPU machine with a crazy thing and do a bunch of GPU programming.
01:04:59.660 --> 01:05:03.160
And I can parallelize this and I'll get it down to a thousand times faster.
01:05:03.600 --> 01:05:05.660
Is that worth a 20% speed up?
01:05:05.700 --> 01:05:08.800
If it takes five milliseconds, you've saved one millisecond.
01:05:09.000 --> 01:05:18.640
hooray look how much harder your life and how much more expensive deployment is and so on right yeah yeah so it's certainly uh something that people should keep in mind all right well i think
01:05:19.300 --> 01:05:30.540
let's let's wrap things up here rust is super interesting i think it's got a place in python and even if you don't want to write rust a lot of these really important libraries are
01:05:31.080 --> 01:05:41.260
somewhat backed by rust so you want to read them and maybe contribute to the to the caramely shell or the noogity inner, but you still kind of want to understand the bits. I think maybe a quick
01:05:41.440 --> 01:05:51.720
shout out to your course. People should definitely give this a listen or a watch. Just talkpython.fm, click on course at the top. Rust will be, the Rust course will be right at the top of that list.
01:05:52.060 --> 01:05:53.940
Yeah, it was fun to build. I hope people enjoy it.
01:05:54.260 --> 01:06:02.980
Yeah, I think they will. And more importantly, more broadly, I suppose, people want to get started with Rust. You've inspired them, Chris. They're ready. What do you tell them?
01:06:04.160 --> 01:06:06.580
Rustlang.org is pretty much the place to start.
01:06:08.040 --> 01:06:10.040
It's remarkably well documented.
01:06:10.340 --> 01:06:11.980
There's a lot of good guides and things out there.
01:06:13.880 --> 01:06:18.060
The documentation right on that site, they've got the Rust book right there.
01:06:18.660 --> 01:06:20.580
It's quite easy to follow.
01:06:20.940 --> 01:06:23.620
It has a lot of really, really good examples in it.
01:06:24.100 --> 01:06:25.980
So that's definitely a place to go.
01:06:26.460 --> 01:06:33.480
The other space, just a bit of a shout out would be, there's a awesome list called Awesome Python RS.
01:06:33.980 --> 01:06:39.380
And it's just a massive list of the tools and libraries that use Rust in the Python space.
01:06:39.870 --> 01:06:50.280
So if you're looking for, rather than like education book examples, you're looking for places that actually use it and you want to, and you want to troll through some code, that's a great
01:06:50.370 --> 01:06:55.040
place to go looking for interesting libraries to take a look at. Yeah. I second that. I'm,
01:06:55.160 --> 01:07:03.660
I'm such a sucker for awesome lists. Yes. That could be, you want to watch a movie? I found a new awesome list. I'm just going to poke around this for like the next half hour, if you don't
01:07:03.800 --> 01:07:15.140
mind, you know? Yeah. And, you know, there's some very classic examples on this list of like drop-in replacement for speed things, right? So there's a cryptography library and there's a JSON library,
01:07:15.420 --> 01:07:30.020
both of which are basically drop-in replacements for stuff from the standard library. And because they're written in Rust, they're screamingly faster. So, you know, that example of looking for the thing that you need to optimize, there's some good ideas in there that you can dig into.
01:07:30.240 --> 01:07:38.880
Yeah. And you know, I gave you the example of like, well, we could just rewrite this bit of your slow code and rust. It might already be written as a library.
01:07:38.880 --> 01:07:40.200
Someone else may have done it as well. Yes.
01:07:40.460 --> 01:07:43.400
Yeah. Just swap, swap your JSON parsing library or whatever. Right.
01:07:43.600 --> 01:07:54.360
And, and a lot of the, Python things that are like Python libraries that use rust, a lot of them are actually just thin wrappers to existing rust libraries.
01:07:54.760 --> 01:08:03.480
So that somebody is rather than writing something from scratch, they're like, Hey, there's this neat library in Rust that does this thing that I like, and I wish it was in Python.
01:08:03.660 --> 01:08:10.600
And they write like four lines of code that are essentially the API wrapper down to make it, expose it as a module.
01:08:10.740 --> 01:08:16.180
And now we can take advantage of the fact that there's this whole other community that's trying to do these efficient things.
01:08:16.640 --> 01:08:24.839
And we don't have to trust the suitability and correctness of somebody saying, hey, I spent a weekend rewriting the JSON parsing.
01:08:24.920 --> 01:08:26.880
Like, ah, brightening.
01:08:26.920 --> 01:08:32.960
These are things with thousands of stars and many contributors because the Rust community themselves are using them, right?
01:08:33.240 --> 01:08:33.580
Right, right.
01:08:33.580 --> 01:08:35.799
And if you just wrap it, you're pretty safe.
01:08:36.420 --> 01:08:37.620
Polars is an example, right?
01:08:37.799 --> 01:08:39.819
Polars is a Rust library for Rust programmers.
01:08:40.400 --> 01:08:43.100
And then there's a Python thing on top of it, right?
01:08:43.359 --> 01:08:48.259
So you're getting not just the Python people using it, but the Rust people using it as well.
01:08:48.680 --> 01:08:49.319
What is that?
01:08:49.319 --> 01:08:52.359
A caramel dipped apple equivalent version or something like that?
01:08:52.500 --> 01:08:52.620
Yes.
01:08:53.040 --> 01:08:53.680
I don't know.
01:08:53.900 --> 01:08:55.540
There's caramel everywhere by the time we're done.
01:08:55.600 --> 01:08:59.220
So it's a messy, messy kitchen.
01:09:00.600 --> 01:09:01.440
It was delicious.
01:09:01.680 --> 01:09:02.980
It was a delicious episode, Chris.
01:09:03.259 --> 01:09:03.839
Thank you for being here.
01:09:03.920 --> 01:09:04.160
That's all right.
01:09:04.580 --> 01:09:05.060
Happy to be here.
01:09:05.400 --> 01:09:05.779
Yeah, bye-bye.
01:09:06.759 --> 01:09:08.940
This has been another episode of Talk Python To Me.
01:09:09.319 --> 01:09:10.040
Thank you to our sponsors.
01:09:10.279 --> 01:09:11.540
Be sure to check out what they're offering.
01:09:11.740 --> 01:09:13.100
It really helps support the show.
01:09:14.000 --> 01:09:15.500
This episode is brought to you by Sentry.
01:09:16.319 --> 01:09:19.319
You know Sentry for the error monitoring, but they now have logs too.
01:09:19.680 --> 01:09:26.680
And with Sentry, your logs become way more usable, interleaving into your error reports to enhance debugging and understanding.
01:09:27.299 --> 01:09:30.420
Get started today at talkpython.fm/sentry.
01:09:31.180 --> 01:09:38.980
And it's brought to you by the Talk Python in Production Book, an inside look at 10 years of the real-world DevOps behind the Talk Python sites and apps.
01:09:39.319 --> 01:09:42.040
Check it out at talkpython.fm/DevOps book.
01:09:42.720 --> 01:09:54.860
If you or your team needs to learn Python, we have over 270 hours of beginner and advanced courses on topics ranging from complete beginners to async code, Flask, Django, HTML, and even LLMs.
01:09:55.180 --> 01:09:57.540
Best of all, there's no subscription in sight.
01:09:58.020 --> 01:09:59.680
Browse the catalog at talkpython.fm.
01:10:00.380 --> 01:10:05.060
And if you're not already subscribed to the show on your favorite podcast player, what are you waiting for?
01:10:05.740 --> 01:10:07.480
Just search for Python in your podcast player.
01:10:07.580 --> 01:10:08.460
We should be right at the top.
01:10:08.900 --> 01:10:11.660
If you enjoyed that geeky rap song, you can download the full track.
01:10:11.860 --> 01:10:13.780
The link is actually in your podcast blur show notes.
01:10:14.580 --> 01:10:15.940
This is your host, Michael Kennedy.
01:10:16.340 --> 01:10:17.400
Thank you so much for listening.
01:10:17.600 --> 01:10:18.400
I really appreciate it.
01:10:18.860 --> 01:10:19.540
I'll see you next time.
01:10:45.320 --> 01:10:47.120
I think is the norm.
01:11:16.360 --> 01:11:16.380
Продолжение следует...
00:00:00.220 --> 00:00:02.400
Lent the entire CPython code base from scratch.
00:00:02.950 --> 00:00:06.460
It takes 0.3 seconds, three blinks of an eye.
00:00:06.860 --> 00:00:08.900
That is rough, and it's written in Rust.
00:00:09.250 --> 00:00:11.800
So are Pydantic, Polars, uv, and Granian.
00:00:12.300 --> 00:00:14.620
Rust shows up in Python in three ways.
00:00:15.140 --> 00:00:24.280
Tools that happen to be written in Rust, libraries Python itself imports and runs, and servers that themselves run Python inside of Rust.
00:00:24.840 --> 00:00:27.160
This episode is Rust for Python developers.
00:00:27.740 --> 00:00:33.160
And Christopher Trudeau is back on Talk Python to discuss Rust and his latest course up and running with Rust.
00:00:34.060 --> 00:00:38.800
The core rule is that only one thing can own a value or variable at a time.
00:00:39.240 --> 00:00:42.860
Pass it around freely in Python and the garbage collector cleans it up.
00:00:43.220 --> 00:00:45.400
Do that in Rust and you get a compiler error.
00:00:46.000 --> 00:00:52.620
This is Talk Python To Me, episode 563, recorded Wednesday, September 9th, 2026.
00:01:10.020 --> 00:01:14.720
Welcome to Talk Python To Me, the number one Python podcast for developers and data scientists.
00:01:15.240 --> 00:01:20.560
This is your host, Michael Kennedy. I'm a PSF fellow who's been coding for over 25 years.
00:01:21.100 --> 00:01:22.300
Let's connect on social media.
00:01:22.720 --> 00:01:25.780
You'll find me and Talk Python on Mastodon, Bluesky, and X.
00:01:25.960 --> 00:01:27.900
The social links are all in your show notes.
00:01:28.660 --> 00:01:32.180
You can find over 10 years of past episodes at talkpython.fm.
00:01:32.360 --> 00:01:35.600
And if you want to be part of the show, you can join our recording live streams.
00:01:35.920 --> 00:01:36.380
That's right.
00:01:36.600 --> 00:01:39.840
We live stream the raw uncut version of each episode on YouTube.
00:01:40.420 --> 00:01:44.760
Just visit talkpython.fm/youtube to see the schedule of upcoming events.
00:01:45.100 --> 00:01:48.720
Be sure to subscribe there and press the bell so you'll get notified anytime we're recording.
00:01:49.000 --> 00:01:50.560
This episode is brought to you by Sentry.
00:01:51.320 --> 00:01:54.320
You know Sentry for the error monitoring, but they now have logs too.
00:01:54.540 --> 00:02:01.680
And with Sentry, your logs become way more usable, interleaving into your error reports to enhance debugging and understanding.
00:02:02.220 --> 00:02:05.380
Get started today at talkpython.fm/sentry.
00:02:06.300 --> 00:02:14.100
And it's brought to you by the Talk Python in Production Book, an inside look at 10 years of the real-world DevOps behind the Talk Python sites and apps.
00:02:14.420 --> 00:02:17.160
Check it out at talkpython.fm/DevOpsBook.
00:02:19.560 --> 00:02:22.900
Christopher, welcome back to Talk Python To Me. Always nice to hang out with you.
00:02:23.120 --> 00:02:24.380
Yeah, thanks for having me back.
00:02:24.660 --> 00:02:27.400
I feel it's going to be a little old-fashioned, a little rusty.
00:02:30.280 --> 00:02:33.720
Yes, let's just start with the crap jokes and get them out of the way, yes.
00:02:34.160 --> 00:02:47.200
Yeah, oh yeah, this might not actually be the final Ferris joke or whatever, but no, we're going to talk about Rust for Python devs, specifically not for Rust experts,
00:02:47.740 --> 00:02:57.600
But I want to know enough Rust so that things like Pydantic, ty, if I ended up poking around them or some other extension, it would make sense, right?
00:02:57.760 --> 00:03:00.500
Or maybe write a little bit of Rust to speed up some of your Python code.
00:03:00.700 --> 00:03:07.260
It's obviously the most influential way to make Python extensions or core faster pieces, right?
00:03:07.500 --> 00:03:09.220
It seems to be the new way of doing things.
00:03:09.580 --> 00:03:20.520
And in fact, I saw something in the news this morning that one of the major CPU providers is switching to Rust for a lot of their device drivers and things like that.
00:03:20.590 --> 00:03:22.400
It does seem to be having its day.
00:03:22.740 --> 00:03:23.260
Yeah, absolutely.
00:03:23.780 --> 00:03:28.700
My joke used to be that if you switch to Rust, you're probably going to get VC funding.
00:03:28.930 --> 00:03:30.060
That was like three or four years ago.
00:03:30.720 --> 00:03:34.440
You know, that was when Astral and Pydantic and all that stuff happened.
00:03:34.880 --> 00:03:37.760
Now it needs Rust plus AI, but I think that's still true.
00:03:38.080 --> 00:03:38.620
So, yeah.
00:03:38.900 --> 00:03:39.220
Exactly.
00:03:39.460 --> 00:03:44.000
Now it's AI is the cornerstone, but if you could do Rust and AI, we.
00:03:44.460 --> 00:03:44.860
Why not?
00:03:45.200 --> 00:03:45.260
Yep.
00:03:45.500 --> 00:03:45.980
Why not?
00:03:46.100 --> 00:03:46.900
Just bring them all in.
00:03:47.320 --> 00:03:50.540
No, it's a really cool foundation for Python things.
00:03:51.060 --> 00:03:57.500
So we're going to talk about that and dive into it, compare it to Python, give some examples, give some tools, all those things.
00:03:57.940 --> 00:03:59.240
But it's been a while since you've been on.
00:03:59.460 --> 00:04:02.620
Give everyone a quick introduction of who you are and what you've been up to.
00:04:03.760 --> 00:04:05.760
So yeah, I'm a consultant.
00:04:05.820 --> 00:04:11.220
I mostly spend time working with teams either on architecture or technical processes.
00:04:12.300 --> 00:04:17.000
That tends to mean things like agile and lean and automation, CI/CD, all that kind of good stuff.
00:04:17.480 --> 00:04:21.000
And in my spare time, I still do a fair bit of teaching.
00:04:21.109 --> 00:04:27.700
And sometimes that's in person, sometimes that's virtual, and sometimes that's creating online courses for people.
00:04:28.060 --> 00:04:30.580
I spend a fair amount of my time in the Python space.
00:04:30.870 --> 00:04:32.880
I'm co-host of the Real Python podcast.
00:04:33.220 --> 00:04:36.400
So that tends to be where people, if they know my voice, that's from where.
00:04:36.760 --> 00:04:42.220
And lately I've been getting into Rust and figured you and I could chat about that.
00:04:42.420 --> 00:04:43.520
A lot of really cool things you're doing.
00:04:44.410 --> 00:04:48.220
I guess let's talk about getting into Rust.
00:04:48.760 --> 00:04:50.660
First of all, what was your background?
00:04:51.420 --> 00:04:55.340
Did you do C++, C, other compiled languages?
00:04:55.740 --> 00:04:57.600
Because it's a shift, right?
00:04:57.860 --> 00:04:59.620
Well, so this is it, right?
00:04:59.660 --> 00:05:03.360
You hear the rust is a hard language to grasp thing.
00:05:03.780 --> 00:05:08.800
And I don't, I didn't find it that way, but I don't want to diminish people who are saying that, right?
00:05:08.900 --> 00:05:11.880
Like this isn't because I'm so much smarter or anything along those lines.
00:05:12.380 --> 00:05:13.760
It's because I have that background.
00:05:14.400 --> 00:05:19.480
I was writing C when I was 13 or 14 years old.
00:05:19.640 --> 00:05:22.360
There weren't a lot of choices when I started out.
00:05:22.820 --> 00:05:34.160
So I have a grounding and, you know, I wrote device drivers and I wrote embedded systems uh don't haven't done it in a long time but i have that grounding that rust kind of expects you to
00:05:34.360 --> 00:05:47.360
have and it's closer to the machine there's less virtualization going on uh it's a lower level language than something like python uh in fact uh bob builder russ and i were talking about this
00:05:47.580 --> 00:06:02.540
because he's got into rust recently and he came from php and python so from that it's this whole other kind of experience and he was talking about the fact that he actually thinks it's made him a better Python developer because now he's thinking about memory and stuff like that a little more
00:06:02.820 --> 00:06:13.140
than you necessarily would if you've just come from Python. That's really interesting. I hadn't really thought about it because you and I are, I think, around basically the same age, at least
00:06:13.220 --> 00:06:20.940
technologically speaking. And I remember getting the C++ Primer Plus. This is so nice. C++.
00:06:22.180 --> 00:06:23.520
It's so much better.
00:06:23.980 --> 00:06:24.180
Yes.
00:06:24.360 --> 00:06:28.280
I just loved working in C++ and so on.
00:06:28.600 --> 00:06:38.840
So I've never known a world where I came to Python or JavaScript or other languages where I didn't already have that experience of, you know, void star star.
00:06:39.080 --> 00:06:39.920
What do I do with that?
00:06:40.160 --> 00:06:40.440
Exactly.
00:06:40.900 --> 00:06:41.680
These kinds of things.
00:06:42.060 --> 00:06:43.780
But, of course, that makes sense.
00:06:43.840 --> 00:06:47.800
You come from Python and PHP, and then you're like, whoa, why am I doing all this stuff?
00:06:47.940 --> 00:06:48.540
This is crazy.
00:06:48.940 --> 00:06:49.080
Yeah.
00:06:49.540 --> 00:06:51.660
And it's, you know, a big part of it.
00:06:51.680 --> 00:06:58.060
And I think the thing that folks who are coming to it from languages like Python find difficult is that whole memory management thing.
00:06:58.360 --> 00:07:00.460
And Python basically takes care of that for you.
00:07:00.720 --> 00:07:05.240
And so if you've never had to do that before, all of a sudden it's like, I have to do what?
00:07:05.420 --> 00:07:06.680
And why do I have to do that?
00:07:07.600 --> 00:07:09.600
And it can get a little persnickety.
00:07:11.180 --> 00:07:16.980
It's concept of only one thing can own a value at a time.
00:07:17.620 --> 00:07:25.100
it has objects, but the objects belong to somebody. And in Python, you just pass those things around willy nilly and you don't worry about it. And the garbage collector takes care of it.
00:07:25.500 --> 00:07:35.120
And that often turns into a compile error in Rust. And that's on one hand, it's the beauty because it makes sure that certain kinds of bugs don't happen. On the other hand, if you're not used to
00:07:35.120 --> 00:07:48.040
it, you know, there's a, there's a joke in the Rust world that there are no bugs. It's, it's all your time isn't debugging. All your time is getting it to compile. And that's because there's a lot of that, Oh, I'm just going to pass this around and wait, I can't.
00:07:48.580 --> 00:07:51.160
And so, yeah, that there's a lot of upfront work there.
00:07:51.700 --> 00:07:59.080
And I think for a new developer, that could be very frustrating because, you know, you don't, you can't play as easily.
00:07:59.300 --> 00:08:05.020
There's the threshold to getting started with something is higher because you're constantly kind of fighting the compiler.
00:08:05.440 --> 00:08:09.120
The flip side of it is their compile messages are absolutely fantastic.
00:08:09.860 --> 00:08:12.820
They, so when errors happen, they're very, very explicit.
00:08:13.180 --> 00:08:16.440
they often include something like maybe you need to do this.
00:08:17.040 --> 00:08:21.560
And from what I saw, they were right 80 or 90% of the time.
00:08:22.080 --> 00:08:32.520
So once you figure out the language, I mean like the, not the language of Rust, but the vocabulary they use for error messages, it's very much, oh, oh, okay.
00:08:32.640 --> 00:08:33.919
So that's kicking off the borrow checker.
00:08:33.919 --> 00:08:34.760
Now I understand that.
00:08:34.800 --> 00:08:34.900
Okay.
00:08:34.979 --> 00:08:35.640
I'll go fix it.
00:08:36.080 --> 00:08:39.560
So there's a few things you kind of have to learn to get to that, but it is fairly helpful.
00:08:40.719 --> 00:08:50.940
But again, that could just be my background and remembering days of C where the compile error was being triggered from three lines before it was actually talking about where the error was.
00:08:51.040 --> 00:08:56.980
And you kind of had to zone in around roughly where it was reporting it to figure out what had gone wrong.
00:08:57.600 --> 00:09:03.640
So, yeah, there's been some advances in technology since we were tapping out bits and bytes on rocks.
00:09:03.920 --> 00:09:04.000
Yes.
00:09:04.840 --> 00:09:05.140
Exactly.
00:09:05.340 --> 00:09:06.220
Making sand think.
00:09:07.320 --> 00:09:09.420
So I would like to just acknowledge it.
00:09:09.480 --> 00:09:11.740
Six minutes, 57 seconds into the recording.
00:09:11.940 --> 00:09:12.520
Borrow Checker.
00:09:12.800 --> 00:09:12.860
Yeah.
00:09:13.040 --> 00:09:14.140
Borrow Checker's been shouted out.
00:09:15.680 --> 00:09:15.900
Yes.
00:09:16.400 --> 00:09:16.500
Yeah.
00:09:18.139 --> 00:09:20.260
Maybe we should just do the quick version of that.
00:09:21.260 --> 00:09:22.700
We'll probably dig into it a little bit more.
00:09:22.920 --> 00:09:24.840
Before you do, I just want to wax poetic.
00:09:25.680 --> 00:09:28.740
Think back to the days of back in the 90s.
00:09:29.120 --> 00:09:32.660
I remember when I had my C++ Primer Plus book.
00:09:33.040 --> 00:09:35.820
And yes, folks, it was a book that was like the yellow pages.
00:09:36.520 --> 00:09:38.820
There was no, literally the internet did not exist.
00:09:39.440 --> 00:09:40.280
Well, the internet existed.
00:09:40.450 --> 00:09:46.660
There was Gopher, there was Telnet, but the World Wide Web did not exist at this time, like not for four or five more years.
00:09:46.940 --> 00:09:50.240
Anyway, I remember thinking, oh my gosh, this is so hard.
00:09:50.380 --> 00:09:51.700
This is so much work when I'm learning it.
00:09:51.700 --> 00:09:53.960
And finally, finally I got it to compile.
00:09:54.150 --> 00:09:55.960
Like, oh, we're good at compiles.
00:09:56.140 --> 00:09:58.660
Like, no, no, no, no.
00:09:59.180 --> 00:10:02.960
That's just when the actual real hard debugging, problem solving starts.
00:10:03.400 --> 00:10:08.380
But you mentioned that with Rust, that the compiler checks are a little bit stronger.
00:10:08.700 --> 00:10:13.520
They check more things like proper memory management and variable sharing and things like that.
00:10:13.590 --> 00:10:24.860
So I think while it was a eye-opener that compiling was only the beginning of my suffering when I was learning programming, I think compiling does mean more in Rust than it used to in other languages.
00:10:25.300 --> 00:10:30.060
Yeah, there's a whole family of bugs that have to do with memory management.
00:10:30.480 --> 00:10:33.260
And what's worse is they tend to be a tricky set of bugs.
00:10:33.700 --> 00:10:37.440
They're the kinds of things that will crash sometimes.
00:10:38.280 --> 00:10:47.740
So if you go back to C and how it stores a piece of text in memory, it has the, you know, like, let's say we're storing the word Talk Python.
00:10:48.000 --> 00:10:52.700
Well, we take the bytes for Talk Python and then we put a null on the end of it.
00:10:53.040 --> 00:10:56.940
And the compiler, when the code is working with it, it looks for that null.
00:10:56.980 --> 00:10:59.440
And that's how it knows that the string is finished.
00:10:59.740 --> 00:11:07.140
Well, if you accidentally write something longer than that, there'll be no null and it'll keep walking past that into the next chunk of memory.
00:11:07.540 --> 00:11:11.500
If you free the memory up, but you still have a pointer that points into that memory.
00:11:11.980 --> 00:11:12.080
Yep.
00:11:12.260 --> 00:11:14.680
But your computer will happily read that.
00:11:15.140 --> 00:11:22.740
And if you've got two strings in a row, what'll happen is you'll get the first string and then the lack of the null, and then you'll get the next string.
00:11:23.140 --> 00:11:26.080
And you might get a wrong message on the screen, but it won't crash your program.
00:11:26.460 --> 00:11:34.980
But if you get a string and then some memory that is a little more tricky, then all of a sudden you might actually be doing something like causing your program to fall over.
00:11:35.230 --> 00:11:42.720
So rust isn't bug free, but there is a category of bugs that it just doesn't let you create.
00:11:43.300 --> 00:11:53.980
And that makes it harder to compile, but a beauty to work with in the fact that a lot of the things that you might struggle with that are harder to debug are gone.
00:11:54.170 --> 00:11:54.340
Right.
00:11:54.660 --> 00:12:04.900
You know, I thought the nature of Python is the looseness of the type system and the dynamicism of it means you can get moving very, very quickly.
00:12:05.460 --> 00:12:10.620
But if you're not using a type checker, type mismatches are things you discover at runtime.
00:12:11.780 --> 00:12:15.540
All of that is very strict and very well managed in Rust.
00:12:15.700 --> 00:12:18.260
And so those kinds of problems just don't exist.
00:12:19.440 --> 00:12:20.000
That's awesome.
00:12:20.280 --> 00:12:22.680
It also takes it's also mind bending.
00:12:23.000 --> 00:12:23.360
It is.
00:12:23.360 --> 00:12:24.320
In some ways, right?
00:12:24.420 --> 00:12:37.680
It's the way you think the way a lot of the ways you think about solving problems in C++ or C or Python can be kind of the same in Rust. Some of these limitations sort of change the algorithms
00:12:38.340 --> 00:12:42.620
and the data structures that will work in those worlds. Yeah. Yep. Well, and, you know, take
00:12:42.760 --> 00:12:56.320
something as simple as an integer in Python. They're boundless, right? And if you're doing certain kinds of math, that's fantastic. There's no upper limit. Python takes care of all of that for you. It figures it out. I actually saw an article a couple of weeks ago where somebody was
00:12:56.540 --> 00:13:08.700
building a SIMD machine based on integer, based on, doing bitwise operations on massive integers, right? Thousand byte integers, and you can get away with this. And Python just happily
00:13:08.860 --> 00:13:21.940
goes, yeah, that's a really big integer. No problem. Rust is closer to the machine. So it tends to use integers the way your CPU uses integers. So you have to be aware if you're using an eight bit integer that you can't put nine bits in it.
00:13:22.300 --> 00:13:22.980
Things go wrong.
00:13:23.540 --> 00:13:27.980
Now the compiler, most of the time can catch that depends on how you're getting into that situation.
00:13:28.820 --> 00:13:30.900
And so it, it stops you from doing those things.
00:13:31.000 --> 00:13:33.000
But of course now you have to be conscious of it, right?
00:13:33.080 --> 00:13:35.640
You're making a decision when you're designing your program.
00:13:36.200 --> 00:13:38.120
How many bits am I going to store this in?
00:13:38.340 --> 00:13:45.460
And most of the time that's not a problem, but sometimes that might mean you're hitting boundaries that you wouldn't otherwise expect to hit.
00:13:45.660 --> 00:13:45.780
Yeah.
00:13:45.960 --> 00:13:48.360
And even weird things like it's signed or unsigned.
00:13:48.440 --> 00:13:51.000
Like now you can have negative numbers, not even negative one, not allowed.
00:13:51.340 --> 00:13:51.460
Yeah.
00:13:51.740 --> 00:13:54.160
That means 2.17, two, two, five billion.
00:13:55.639 --> 00:14:00.820
And interesting, like a lot of that stuff is in Python, but it's buried further down.
00:14:01.120 --> 00:14:07.800
So you can get at some of those same concepts inside of Python, but if you're just starting out, you don't go digging for those things.
00:14:08.120 --> 00:14:08.200
Right?
00:14:08.480 --> 00:14:20.660
So if you're, you know, if you're playing with the network and you're trying to pack bytes together, Python has signed and unsigned and it has those sides pieces. And all of that is very, very important if you're constructing the perfect
00:14:21.000 --> 00:14:35.320
packet. But if you're just trying to do math on the command line, well, you don't need to think about that kind of thing. Rust doesn't give you the choice. And that's not Rust specific. That's most compiled languages. They don't give you the choice, right? And it's also where the speed comes
00:14:35.430 --> 00:14:46.780
from, right? So that beauty of Python's limitless integer means there has to be machinery inside of that to handle when you make it bigger than what the current chunk of memory is.
00:14:47.360 --> 00:14:49.260
And rust doesn't have that machinery.
00:14:49.470 --> 00:14:50.720
It just says, okay, I'll crash.
00:14:51.170 --> 00:14:53.600
and so it's, it's a trade-off, right?
00:14:53.740 --> 00:15:00.820
So you don't have to care for as much, but one of the reasons Python is slower is because there's the overhead that handles these kinds of things.
00:15:00.960 --> 00:15:03.660
So one of the reasons, you know, the flip side works as well.
00:15:03.960 --> 00:15:09.340
One of the reasons rust is faster is because it's optimizing for exactly what your CPU does.
00:15:10.040 --> 00:15:12.460
And that less overhead means your code runs faster.
00:15:12.760 --> 00:15:12.840
Right.
00:15:13.000 --> 00:15:17.340
You're never going to get a Python integer into a CPU register.
00:15:17.740 --> 00:15:17.900
Right.
00:15:18.180 --> 00:15:19.860
Like it's just, I don't know.
00:15:20.779 --> 00:15:21.180
Maybe.
00:15:21.460 --> 00:15:31.240
I remember when I came to Python, I did C++ and C#, all languages that care about the shape and size of these variables, numbers, and for 15 years.
00:15:31.360 --> 00:15:34.040
And I came to Python, I'm like, I got to be doing something wrong.
00:15:34.460 --> 00:15:36.320
How do I tell it again how big the number is?
00:15:38.060 --> 00:15:41.340
Because what kind, like, is it just, is it a 64 bit?
00:15:41.540 --> 00:15:44.720
I couldn't figure out like, what is, how do I, it's going to be a problem.
00:15:44.800 --> 00:15:46.000
And then I'm like, wait, it just grows.
00:15:46.180 --> 00:15:46.640
That's crazy.
00:15:46.920 --> 00:15:47.120
Yeah.
00:15:47.440 --> 00:15:51.280
Well, I think I started with Python more as a scripting glue kind of thing.
00:15:51.700 --> 00:15:56.660
And most shell languages don't have, like Python, just don't care about those things.
00:15:56.780 --> 00:15:56.860
Right.
00:15:57.300 --> 00:16:02.120
And so when you're using it loosely to glue other things together, I don't think that really kind of ever crossed my mind.
00:16:02.220 --> 00:16:14.780
And I think I got used to the idea by that time I was doing, you know, web servers and things that were bigger, more interesting projects. And I think a lot of this is where are you coming from and how are you using the tool, right? So I think for the first couple of years I was doing
00:16:14.990 --> 00:16:28.620
Python, I was writing, you know, at max 50 or a hundred line scripts to solve some immediate little problem. And it's nice not to have to worry about that kind of thing, right? So all of this really is, you know, what is the tool and how are you using it for what you're trying to accomplish?
00:16:29.100 --> 00:16:36.880
Yeah. And I was coming from scientific programming, like building UIs and other type of tools for scientist type of thing.
00:16:38.080 --> 00:16:41.320
We care about the size of this number because science.
00:16:41.600 --> 00:16:42.580
That's all what your background is.
00:16:43.940 --> 00:16:46.260
This portion of Talk Python To Me is brought to you by Sentry.
00:16:46.670 --> 00:16:48.800
You know Sentry for their great error monitoring.
00:16:49.150 --> 00:16:50.180
But let's talk about logs.
00:16:50.840 --> 00:16:51.540
Logs are messy.
00:16:52.100 --> 00:16:57.640
Trying to grep through them and line them up with traces and dashboards just to understand one issue isn't easy.
00:16:58.220 --> 00:17:00.260
Did you know that Sentry has logs too?
00:17:00.940 --> 00:17:02.880
And your logs just became way more usable.
00:17:03.440 --> 00:17:09.300
Sentry's logs are trace-connected and structured, so you can follow the request flow and filter by what matters.
00:17:09.900 --> 00:17:18.040
And because Sentry surfaces the context right where you're debugging, the trace, relevant logs, the error, and even the session replay all land in one timeline.
00:17:18.560 --> 00:17:20.640
No timestamp matching, no tool hopping.
00:17:21.240 --> 00:17:27.300
From front-end to mobile to back-end, whatever you're debugging, Sentry gives you the context you need so you can fix the problem and move on.
00:17:27.880 --> 00:17:32.559
More than 4.5 million developers use Sentry, including teams at Anthropic and Disney+.
00:17:33.020 --> 00:17:37.960
Get started with Sentry logs and error monitoring today at talkpython.fm/sentry.
00:17:38.360 --> 00:17:40.620
Be sure to use our code, Talk Python26.
00:17:41.300 --> 00:17:42.860
The link is in your podcast player's show notes.
00:17:43.360 --> 00:17:44.840
Thank you to Sentry for supporting the show.
00:17:46.380 --> 00:17:53.560
I do, before we get too much farther jumping into it, I do want to point out that you wrote the Up and Running with Rust course over at Talk Python.
00:17:53.860 --> 00:17:54.540
So thank you for that.
00:17:54.790 --> 00:17:55.900
I really enjoy this course.
00:17:56.100 --> 00:17:58.280
It's both very educational and funny.
00:17:59.140 --> 00:17:59.660
I try.
00:18:00.120 --> 00:18:00.720
Thank you for that.
00:18:00.840 --> 00:18:05.660
The beauty of doing this kind of stuff with a sense of humor is you don't actually have to be a comedian.
00:18:05.880 --> 00:18:09.780
It's not like everything is a joke, but you can stick some humor in once in a while.
00:18:10.080 --> 00:18:17.520
So I do wonder occasionally whether, again, because of the similar generation, half the jokes might have been aimed specifically at you.
00:18:17.640 --> 00:18:21.060
So just because you find it funny doesn't mean other people will.
00:18:21.500 --> 00:18:23.660
I think they will. At least the lightheartedness.
00:18:23.740 --> 00:18:24.460
We'll see what happens.
00:18:26.460 --> 00:18:27.900
We'll come back to that at the end.
00:18:28.080 --> 00:18:29.800
This is kind of not exactly the same.
00:18:29.940 --> 00:18:33.740
It's not just that we're going to turn the course in the podcast, but it's inspired some of our concepts.
00:18:34.400 --> 00:18:38.380
Now, I want to start by talking about Rust.
00:18:39.240 --> 00:18:44.500
Just some examples before we dive into how is it compared to Python.
00:18:44.860 --> 00:18:47.680
We've touched on a little bit of that, but there's a bunch of differences and so on.
00:18:48.060 --> 00:18:53.100
But let's just appreciate some of the things like Pydantic, Ruff.
00:18:53.540 --> 00:18:56.720
Give me your thoughts on the last five years of these tools.
00:18:56.900 --> 00:19:00.660
have kind of supplanted a lot of things that were very well established in Python.
00:19:01.210 --> 00:19:06.240
So there's, there's, there's kind of three ways that Rust intersects with the Python world.
00:19:06.800 --> 00:19:10.260
And one has almost nothing to do with Python.
00:19:10.680 --> 00:19:14.520
It's they've used Rust to build tools that are Python tools.
00:19:15.310 --> 00:19:19.440
The, they could have just as easily done that for any other language, right?
00:19:19.490 --> 00:19:25.840
So when you talk about things like the linters and those kinds of things, they're, they're useful because they're fast.
00:19:26.200 --> 00:19:30.100
they are not, they're not really integrating with Python.
00:19:30.400 --> 00:19:33.420
They're a third party tool that you're using to make your Python better.
00:19:33.800 --> 00:19:42.860
And I think so some of the, some of the popularity in that has come out of the fact that a lot of the tools we've been using historically in the Python world have been written in Python.
00:19:43.290 --> 00:19:45.280
And so they've been very slow.
00:19:45.720 --> 00:19:48.300
And most of the time that doesn't matter.
00:19:48.680 --> 00:19:55.440
You know, there's that, you know, that programming world of, oh, I'll just go get another cup of coffee and it'll be done when it comes back.
00:19:55.840 --> 00:20:02.120
But your world shifts when you start seeing, you know, orders of magnitude, right?
00:20:02.160 --> 00:20:10.000
Like 10% faster, you're not going to notice it when you're starting to talk multiple zeros times faster, this changes things.
00:20:10.460 --> 00:20:15.740
And I think there were a couple of key libraries that started doing this and everyone kind of went, oh, wait a second.
00:20:16.000 --> 00:20:17.580
There's some, there's some value to this.
00:20:17.940 --> 00:20:24.440
And so I think there's been this real spring up of things written in Rust that make Python development easier.
00:20:24.960 --> 00:20:33.140
Yeah, I think the one that was most stark to me was Ruff because it was just unreasonably fast.
00:20:33.320 --> 00:20:33.460
Yes.
00:20:34.540 --> 00:20:39.180
I remember running on the Talk Python training, all the courses, like that app.
00:20:39.380 --> 00:20:41.360
And that app is much bigger than people think from the outside.
00:20:41.660 --> 00:20:47.520
It's 170,000 lines of Python or something, which is not huge, but it's not a toy, right?
00:20:47.840 --> 00:20:50.960
And so I remember running Ruff on it and it goes, found these four hours.
00:20:50.980 --> 00:20:52.280
I'm like, yeah, no, you didn't.
00:20:52.280 --> 00:20:52.960
Wait, wait.
00:20:54.240 --> 00:20:57.720
Did I not tell it to like go into the subject?
00:20:58.000 --> 00:21:00.660
It's like, did you stop after you found four errors?
00:21:00.780 --> 00:21:01.360
I don't understand.
00:21:01.580 --> 00:21:02.440
How can you be finished?
00:21:02.800 --> 00:21:03.580
How can you be finished?
00:21:03.680 --> 00:21:06.640
You like literally parse the entire thing for a hundred rules.
00:21:07.140 --> 00:21:08.980
And it was like, enter answer.
00:21:09.060 --> 00:21:10.000
I'm like, what?
00:21:10.300 --> 00:21:11.140
I just don't understand.
00:21:11.760 --> 00:21:11.920
Yeah.
00:21:12.160 --> 00:21:12.400
Yeah.
00:21:12.720 --> 00:21:16.820
And then there's something different here, you know?
00:21:17.100 --> 00:21:17.240
Yep.
00:21:17.740 --> 00:21:21.180
I also, I tend to be fairly slow to upgrade my machines.
00:21:21.640 --> 00:21:27.360
So I'm often a couple of generations out processor wise, and it's just that much more, right?
00:21:27.540 --> 00:21:34.460
Because like when you're, when you're operating on a slow machine to begin with, and then you're trying to do something like lint a couple hundred thousand lines of code.
00:21:34.880 --> 00:21:35.060
Yeah.
00:21:35.160 --> 00:21:36.120
It makes a huge difference.
00:21:36.380 --> 00:21:37.200
It makes a huge difference.
00:21:37.400 --> 00:21:37.660
It does.
00:21:37.800 --> 00:21:39.840
So one of the categories is rough, which is really tooling.
00:21:39.980 --> 00:21:41.740
And you can kind of forget that it's rust.
00:21:41.880 --> 00:21:44.680
Like it just doesn't even really, it might as well have been written in some.
00:21:45.060 --> 00:21:45.480
It could have been.
00:21:46.140 --> 00:21:46.480
Yeah.
00:21:46.680 --> 00:21:49.000
And I think that's kind of the key to this category, right?
00:21:49.160 --> 00:21:53.380
whether it's written in rust or C or anything else is kind of indifferent.
00:21:53.700 --> 00:21:54.560
It's, it's a tool.
00:21:55.120 --> 00:22:02.640
they, they're particularly with things like linters, you know, the, the, description of the Python language is publicly available.
00:22:03.180 --> 00:22:08.820
There are tools out there for compiling, for compiling language parsers.
00:22:09.260 --> 00:22:23.820
So like you can, you could have taken something, else and use that to take the definition of Python and built a thing that parses Python in any other language. It's just that Rust seems to be, has, has become the thing that is now the way to
00:22:23.820 --> 00:22:32.280
do some of this stuff. Yeah, absolutely. And just give like other numbers, you know, instead of my own personal example that people can't exactly relate to for parsing for linting and pars,
00:22:33.060 --> 00:22:45.140
evaluating this, the entire CPython code base from scratch is a 0.3 seconds. Yeah. That's, that's like enter the three blinks of an eye. Yeah. You know, that's pretty ridiculous. Yeah.
00:22:45.340 --> 00:22:46.200
So that's one category.
00:22:46.350 --> 00:22:50.980
The other category is closer to our hearts with things like Pydantic and so on.
00:22:51.260 --> 00:22:52.880
So like I said, there's kind of three modes.
00:22:53.680 --> 00:22:58.340
The second mode, and I think it's the most common one, is because Py...
00:22:58.510 --> 00:22:59.260
And this isn't really...
00:22:59.420 --> 00:23:01.900
Again, this is one of those things that's not quite Rust-specific.
00:23:02.380 --> 00:23:09.680
Python was designed from the get-go to integrate well with lower-level languages.
00:23:10.420 --> 00:23:18.100
And in fact, there's a good chunk of the Python standard library, which is really just a thin wrapper on top of the C standard library.
00:23:18.600 --> 00:23:21.460
And in fact, the older stuff in the standard library, you can actually see it.
00:23:21.740 --> 00:23:26.220
It's a little creaky in some of the naming and stuff before they kind of got consistent about how to name things.
00:23:26.330 --> 00:23:29.740
And you look at it and if you're a C programmer, you're just like, oh, I know exactly what that is.
00:23:29.960 --> 00:23:32.040
At least they don't use Hungarian notation.
00:23:32.460 --> 00:23:33.040
There is that.
00:23:33.320 --> 00:23:33.860
There is that.
00:23:34.120 --> 00:23:34.840
S, Z.
00:23:35.220 --> 00:23:36.740
What is going on here?
00:23:37.000 --> 00:23:41.100
So Python has been designed to be able to do this.
00:23:41.560 --> 00:23:50.620
And it just turns out that I think a lot of people are coding in rust have found it easier to code than encoding in c that same interface that c
00:23:50.900 --> 00:24:04.640
extensions can use can be used by rust and so as a result libraries like pydantic libraries like polars they have written their library in rust and then with a very very thin veneer there doesn't
00:24:04.780 --> 00:24:14.700
take it doesn't take a lot of effort to expose that up and then python inside of python you can treat that like any other python module so you don't actually have to be conscious of how they
00:24:14.720 --> 00:24:21.400
And as a result of this, you end up with a lot of speed up because you use that same speed that you were talking about with rough.
00:24:21.760 --> 00:24:26.340
But now Python, which tends to be a slower language, can now access this kind of stuff.
00:24:26.640 --> 00:24:41.460
So something like Polars or Pydantic, where you're doing a lot of crunching and you want them to be fast and performative, this marriage between the dynamic library on the hard drive that is a compiled thing as a Python module,
00:24:41.640 --> 00:24:45.040
that integration has been very, very handy.
00:24:45.420 --> 00:24:57.620
And I think this is the place where Rust is starting to shine because it's a cleaner, although it can be a little frustrating, it's a cleaner language than C.
00:24:59.000 --> 00:25:02.440
There's a learning curve, but there are a lot of things it doesn't let you do.
00:25:02.580 --> 00:25:03.720
There's fewer foot guns.
00:25:04.170 --> 00:25:09.520
And as a result, it's a nice marriage between a low-level language and some higher-level concepts, right?
00:25:09.760 --> 00:25:12.060
So it has things like iterators and collections in it.
00:25:12.380 --> 00:25:15.000
And so if you're coming from Python, that's like, oh, how do I deal with that?
00:25:15.080 --> 00:25:17.760
Oh, it's the same kind of for in loop and it's the exact same thing, right?
00:25:18.200 --> 00:25:27.100
So there's enough similarity to more modern languages that this is becoming a nice sort of collection of pieces that worked well together.
00:25:27.460 --> 00:25:31.700
And in the cases of things that need to be really fast, this is a real answer.
00:25:31.940 --> 00:25:32.900
Yeah, absolutely it is.
00:25:33.300 --> 00:25:44.200
And taking your Rust code and exposing it as a Python package with the tools like Pyotr3 maturing that we're going to talk about obviously they they make it super easy it comes down to just
00:25:44.420 --> 00:25:54.580
okay well you need to build more variants of your wheels rather than just a source only one yeah i think i have an analogy for these types of things so we have one third uh category i guess which i
00:25:54.580 --> 00:26:05.919
would put as granian and other things which is a web application server that runs that is built and runs in rust but then your code and python still runs so i have i have an analogy chris tell me what
00:26:05.880 --> 00:26:16.760
think here we've got the caramel dipped apple where it's caramel is python okay so we've got the caramel dipped apple where python is on the outside with like a rusty core
00:26:17.040 --> 00:26:29.740
yep that would be pydantic we have maybe python maybe it's the way anyway we've got Granian and other things where it's like more like a caramel m&m on the outside it's like a
00:26:30.120 --> 00:26:34.760
hard shell of rust and then the side it's like some sort of crunchy nugget on the outside and
00:26:34.780 --> 00:26:49.040
the caramel's inside yeah the protective hard outside is the rust which is granian and those types of things and then we've got the tools which i'm thinking of is just like a solid piece of caramel but that's maybe a little bit backwards i i would go with the tools are like when
00:26:49.160 --> 00:26:58.840
you've got a slices of apples and a bowl of caramel that you can dip it in so it's a separate thing but you can mix and match so yeah i think we're stretching we're officially stretching this
00:26:59.020 --> 00:27:05.560
analogy and now i'm hungry but i know i know we were stretching but with your your slices of apple You've, you've perfected it.
00:27:05.670 --> 00:27:05.800
Okay.
00:27:06.060 --> 00:27:11.380
So yeah, so that third category is within rust code, you can embed the Python interpreter.
00:27:11.960 --> 00:27:18.180
And so from a rust, program, you can now use an access Python.
00:27:18.590 --> 00:27:32.500
So you can kind of use Python as a scripting or, or configuration language within a larger, mechanism and something like granian where you want to actually run Python code for a web framework, that, you know, so that,
00:27:32.520 --> 00:27:43.960
that inverts the relationship we were talking about before. So yeah, so that's our three, right? So it's separate tools, the using Rust as a module inside of Python. And then the third one
00:27:43.960 --> 00:27:51.080
is using Python as a compiled library, using the interpreter as a compiled library inside of the
00:27:51.140 --> 00:28:02.760
Rust object itself. Yeah, I think that sums it up pretty well. Let's talk differences. I think kind of language differences, you know, syntax differences. It feels pretty familiar, honestly.
00:28:03.320 --> 00:28:16.640
Yeah. And I was about to say, you know, to start with differences, it might actually be easier to start with what's not different. The language itself, there are some things, obviously, if you've never, if you've never seen it before, it takes a little, and that's the same with any language,
00:28:17.220 --> 00:28:27.500
but it's not going to be completely out of nowhere. If, if I hand a Python developer some fairly clean Rust, you're probably going to have an idea of what it's doing. The loop mechanisms are the same.
00:28:27.980 --> 00:28:33.660
The if else is similar. There's no L if you actually use if else. I always scratched my head
00:28:33.780 --> 00:28:37.680
with L if in Python. I never understood it. Why you need a new keyword. It's such a verbose language.
00:28:37.900 --> 00:28:41.760
And then it's like, well, no, this we're going to. Yes. Yeah. Why that one? I have a sneaking
00:28:42.180 --> 00:28:52.680
suspicion. It might've made something early in the early days easier to parse, but rather than parsing two keywords, it gives you a keyword. A lot of the built-in mechanisms, like it's got
00:28:52.840 --> 00:29:07.700
tuples and arrays, it's got iterables and collections. So a lot of the declaration looks like typed Python. So because it is a strictly typed language and you have to specify what everything is, you do have things like the arrow that this function returns something of this
00:29:07.880 --> 00:29:19.300
type, right? So you've got that little arrow designator. But if you're used to coding in typed python which i'm not uh then you uh then then it's readable from that perspective it is yeah
00:29:19.430 --> 00:29:31.800
the types are quite quite similar uh as they you know um for the way you define them right if you have like a function or something then you just say like arrow goes to i always read that as goes
00:29:31.800 --> 00:29:38.200
to pool if it like returns a pool the variables are variable name colon type right yeah yeah and
00:29:38.220 --> 00:29:43.060
And I suspect that's probably because Python type libraries was inspired by some of this stuff.
00:29:43.180 --> 00:29:47.400
I think it probably flowed the other direction, but I'm not sure about that.
00:29:47.680 --> 00:29:55.080
So yeah, it's a lot of mixing in this, in the later, the things that got created later and typed later, like TypeScript is similar.
00:29:55.600 --> 00:29:55.800
Yes.
00:29:56.120 --> 00:29:57.560
Python types are similar.
00:29:58.360 --> 00:29:59.200
Swift is similar.
00:29:59.800 --> 00:30:05.460
I think it's the same that everybody stole from C, you know, C is the granddaddy of most of the languages we use.
00:30:05.560 --> 00:30:08.480
And then I think people started adding these kinds of concepts to it.
00:30:08.580 --> 00:30:12.100
And it's like, well, if you've come from that other language, this makes it simple.
00:30:12.400 --> 00:30:17.120
So yeah, there seems to be a sort of family of how this stuff works now.
00:30:17.440 --> 00:30:17.540
Yeah.
00:30:17.600 --> 00:30:19.220
And someone decided all the types go after.
00:30:19.680 --> 00:30:19.840
Yes.
00:30:20.200 --> 00:30:20.280
Right.
00:30:20.520 --> 00:30:22.740
And see, you would say like int function.
00:30:23.240 --> 00:30:23.320
Yeah.
00:30:23.440 --> 00:30:26.200
That, that, that has taken me a little bit to get used to.
00:30:26.500 --> 00:30:26.580
Yes.
00:30:27.340 --> 00:30:36.840
I presume it me it's meant to be making it more readable and you see the essence, like the function name and the variable names, and then the stuff describes it after.
00:30:37.180 --> 00:30:38.440
But yeah, it's always caught me off guard.
00:30:38.560 --> 00:30:40.300
I'm guessing it's because it's optional.
00:30:40.960 --> 00:30:43.820
It's optional in Python, but it's not optional in Rust.
00:30:44.220 --> 00:30:44.440
True.
00:30:44.620 --> 00:30:45.320
Or Swift, right?
00:30:45.800 --> 00:30:46.260
Yeah, true.
00:30:46.580 --> 00:30:53.200
And I'm pretty sure that Swift was inspired by, like much of Swift was inspired by Python as well.
00:30:53.340 --> 00:30:59.820
Swift's an interesting thing to look at as well, like the Playgrounds, the REPL, a lot of the stuff there.
00:31:00.000 --> 00:31:01.200
But okay, let's keep going.
00:31:01.360 --> 00:31:02.840
Some more similarities, all right?
00:31:03.260 --> 00:31:05.460
No, I think we've hit the limit of the similarities.
00:31:08.000 --> 00:31:09.420
So it doesn't take long.
00:31:10.700 --> 00:31:17.920
It's relatively readable in the same fashion, but it doesn't take long before you have to kind of peel the top layer of that onion and then you're going to get into your differences.
00:31:19.700 --> 00:31:23.560
At the heart of it, one of the fundamental concepts is it is a compiled language.
00:31:24.160 --> 00:31:31.160
This is one of those things that I think I always find sometimes frustrates students because you end up with the, well, Python compiles.
00:31:31.460 --> 00:31:33.240
I can see the code right there.
00:31:33.960 --> 00:31:38.920
Python is a interpreted language that interprets a binary file.
00:31:39.260 --> 00:31:42.540
So when Python is compiling, it's creating a binary target.
00:31:42.860 --> 00:31:45.760
That binary target is not platform specific.
00:31:46.340 --> 00:31:50.640
It is just a, you can think of it as a data file the same way, like Excel is a data file, right?
00:31:50.680 --> 00:31:53.720
So when you, when you write a formula in Excel, you don't think of that.
00:31:53.960 --> 00:31:55.880
It's not quite compiling that formula.
00:31:56.220 --> 00:31:57.180
It's storing it in binary.
00:31:57.420 --> 00:31:59.620
And then Excel is running that formula.
00:31:59.980 --> 00:32:04.120
By contrast, Rust actually compiles to machine code for your platform.
00:32:04.710 --> 00:32:10.120
So when I come, unlike a collection of Python bytecode, I can hand you that.
00:32:10.500 --> 00:32:14.560
And I don't have to worry about what platform you're running on because your interpreter is specific for you.
00:32:14.810 --> 00:32:15.920
The bytecode is not.
00:32:16.180 --> 00:32:19.880
If I hand you my binary, if you're on the same kind of platform I am, it'll run.
00:32:20.140 --> 00:32:21.280
But if you're not, it won't.
00:32:21.560 --> 00:32:27.620
And so what Rust is actually doing there is creating a binary, tight binary file that is specific to your platform.
00:32:28.240 --> 00:32:28.820
And you know what?
00:32:28.860 --> 00:32:29.140
I'm jealous.
00:32:29.680 --> 00:32:32.460
I'm jealous from a Rust and Python perspective.
00:32:32.730 --> 00:32:36.900
You can compile it and hear, hey, I'll give you a file.
00:32:36.990 --> 00:32:37.760
You can run it.
00:32:38.290 --> 00:32:38.800
You know what I mean?
00:32:39.060 --> 00:32:39.380
Yes.
00:32:40.320 --> 00:32:53.460
I know there's a lot of reasons and it's not easy, but wow, would I love a Python --build thing and outcomes just, I don't care what's in the inner core, right?
00:32:53.460 --> 00:33:04.660
You know, back to the like caramel M&Ms, but just a thing that I could put on a server, I could give to a person, I could put in Docker, and it doesn't have to have a bunch of other stuff there to make it possible.
00:33:04.930 --> 00:33:06.360
Yeah, it's a pros and cons thing, right?
00:33:06.480 --> 00:33:10.700
So your distribution is way easier, but it's very specific distribution, right?
00:33:10.740 --> 00:33:21.480
So you end up, if you're trying to aim at multiple platforms, you have to compile across all of those platforms, but the distribution of it is basically, here's the execution file, go nuts, and that's it, you're done.
00:33:22.220 --> 00:33:24.840
Or the collection of them, if you've got dynamically loading libraries.
00:33:25.340 --> 00:33:26.680
So that is definitely easier.
00:33:26.760 --> 00:33:37.180
the flip side of it is things like repls aren't technically possible because it needs to compile stuff and in fact there's some hacks out there that are kind of hilarious that are essentially
00:33:37.940 --> 00:33:49.100
repl like things that are in the background are basically recompiling a program every single time you enter a line in the repl exactly so it's actually somewhere in there yeah it's actually
00:33:49.240 --> 00:34:01.540
maintaining this program for you in order to make it look repl like and as fast as rust is i found painful i played with it once in a while and i sort of gave up and just went back to i'll have
00:34:01.550 --> 00:34:13.379
my foo.rs file and i'll do it that way so yeah i could just see the background that there's like there's a fn main curly you know brace brace curly exactly and every line of rubble is jammed and
00:34:13.460 --> 00:34:17.940
then there's a cargo build cargo run yeah that's exactly what it's doing that's exactly what it's
00:34:18.000 --> 00:34:29.500
doing this portion of talk python in me is brought to you by us i'm excited to talk about my first solo book, Talk Python in Production. It's an inside look at how we host all the Talk Python
00:34:29.720 --> 00:34:44.320
sites, APIs, mobile apps, and way more. Here's the thing. I believe most hosting stories sold to developers and data scientists are way overcomplicated and overpriced. You've heard me say you're not Google, you're not Netflix, so you shouldn't run your infrastructure the way they
00:34:44.480 --> 00:34:55.760
do. But if not that, then what? This book is both a blueprint for what I chose for Talk Python and a story arc of 10 years of running my own infrastructure from a complete newbie,
00:34:56.260 --> 00:35:06.560
apprehensive to Linux, to some pretty neat infrastructures code DevOps. It covers Docker, Nginx, Let's Encrypt, self-hosted analytics and monitoring, CDN setup, framework migrations,
00:35:06.820 --> 00:35:16.540
and a whole philosophy that I've termed stack native, keeping things streamlined, powerful, and free of cloud lock-in. And it's more than just your standard tech book. It comes with
00:35:16.560 --> 00:35:28.500
code and figure galleries on GitHub, a discussion forum, and something unique, over an hour of audio readers briefs, short conversations that bookend each chapter to prime your focus or broaden your
00:35:28.620 --> 00:35:39.640
takeaways. Oh, and 0% of this book was written by AI. Every word is mine, written over the course in high months, for better or worse. I've made the first third of the book available for free online.
00:35:40.260 --> 00:35:50.880
After that, you can grab the DRM-free EPUB and Kindle editions, and I'm working on a paperback edition as well. Please check it out at talkpython.fm/devops, or just click book in the
00:35:50.980 --> 00:35:55.780
nav bar on the website. It's a great way to support the podcast, and I hope it changes a bit how you
00:35:55.830 --> 00:36:05.300
think about running your apps in production. Okay, and so I guess, and that kind of, and we were already sort of talking about this, but this leads us to this idea of the strict typing mechanism,
00:36:05.700 --> 00:36:20.560
and that really comes out of this idea of the hardware, right? So your CPU has an idea of what an integer is. Your CPU has an idea of what a float is. There are different sized integers. How much memory is that integer going to be stored in? How much memory is that float going to be stored
00:36:20.720 --> 00:36:32.540
in? So not only is Rust specific about having these things, and you have to declare them when you're using them, but it also has that mapping to what your hardware does. So you have to make
00:36:32.540 --> 00:36:45.120
a decision between a signed integer versus an unsigned integer. So if you've never played with this kind of stuff before, when you stick a number in memory, that number represents just some bytes
00:36:45.680 --> 00:36:58.480
and your CPU is interpreting those bytes to mean something. And if you could have it, you could have it represent a positive number. And in the case of a single byte to it, that's from
00:36:58.640 --> 00:37:09.860
zero to 255. But if you want to also have negative numbers and store it in the same amount of space, well, then now you have to sort of map something from 0 to 255 into the negative space. And so you
00:37:09.960 --> 00:37:22.980
end up with like minus 127 to a positive 127 or 128. Let's not get into that. But essentially, the computer is interpreting those same eight bytes in a different way to represent a mix of
00:37:23.200 --> 00:37:31.940
negative and positive numbers. The downside of that is you can store less. You can only store up to was half the size of a positive number.
00:37:32.270 --> 00:37:41.960
In Python, you don't care about any of this, again, unless you're doing packets, but in Rust and C and other languages like it, you have to actually explicitly decide which of these you are using.
00:37:42.560 --> 00:37:47.760
The upside is in Python, you don't care, but there is so much indirection.
00:37:48.100 --> 00:37:49.760
Yes, there's a lot of overhead.
00:37:50.260 --> 00:37:50.460
Yes.
00:37:51.460 --> 00:37:53.080
And all of that overhead goes away, yeah.
00:37:53.440 --> 00:38:06.800
Not only is it indirection and that overhead goes away, But can you put a bunch of Python, if I have an array of Python numbers, how are they going to land on like L1 cache?
00:38:07.160 --> 00:38:07.460
Yes.
00:38:07.720 --> 00:38:10.900
They're not going, they're all random places out in the heap.
00:38:11.320 --> 00:38:20.900
So, I mean, there's arenas and blocks and all that stuff to try to like get them closer together, but they're still just out there rather than I've got an array of 10 numbers.
00:38:20.990 --> 00:38:21.580
Well, guess what?
00:38:21.880 --> 00:38:24.780
Those numbers are contiguous in memory sort of thing, right?
00:38:25.460 --> 00:38:29.380
And you've kind of hit on something that is also very explicit in Rust.
00:38:29.920 --> 00:38:35.320
Now, you can start Rust programming without fully understanding this, but you're not going to get very far without it.
00:38:35.820 --> 00:38:39.100
It's fairly explicit about what goes on the stack and what goes on the heap.
00:38:39.250 --> 00:38:46.260
So again, if these are new concepts for you, when your program is written, the stack is where function calls happen.
00:38:46.560 --> 00:38:55.620
So when you move from one place in code into another in memory, what happens is the new address, the place you're going to, gets put onto a stack.
00:38:56.230 --> 00:38:57.520
The old address is there before.
00:38:57.770 --> 00:39:03.680
So when your function returns, it pops off the old stuff and then knows, oh, that's now the thing at the top of the stack.
00:39:03.820 --> 00:39:05.160
That's now the address I'm going to run at.
00:39:05.410 --> 00:39:12.980
And so when you add variables into, when you add parameters to your function, those are also getting put on the stack.
00:39:13.240 --> 00:39:23.860
So you end up with this little stack frame, which is the place you're going to be running and the data that goes with that function. By contrast, the heap is sort of a general space, and that is
00:39:24.040 --> 00:39:38.840
where you allocate things from memory. And longer lived things or things that you're passing around between functions tend to end up being created in the heap. And how Rust does memory management, we'll gloss over it for now, we'll get into it a little more later, I think, but how Rust does
00:39:38.860 --> 00:39:48.380
manage memory management differentiates between these two kinds of things and so again this is one of those things you you know you only think about the stack in python when it fails because
00:39:48.740 --> 00:40:00.500
you get the stack trace but otherwise you more or less ignore it whereas here once you start playing around with passing objects around whether or not you're being explicit about it that concept of am
00:40:00.500 --> 00:40:11.140
i in the stack or am i in the heap and who owns it becomes very very important and and this isn't new to Rust. This has been there in compiled languages. This is a fundamental way how modern
00:40:11.420 --> 00:40:17.840
computing machines work, but it's more exposed in Rust than it is in Python. You know, the thing I
00:40:17.980 --> 00:40:28.780
think is such, to me, it was a little ironic is Python, you don't worry about pointers. You don't worry about that. You just work. And then like other languages like C, Rust, C#, you talk
00:40:29.000 --> 00:40:38.840
stack, you talk heap, you talk pointers, you can dereference. Python is more pointer heavy than any of those languages because literally everything is in the heap. There's nothing that's even a
00:40:38.920 --> 00:40:47.340
number is a pointer to a thing in the heap, right? Well, this is how Python got away with not having pointers. It was everything's a pointer, so we don't have to differentiate. Yeah. Yeah, exactly.
00:40:47.700 --> 00:40:55.760
That's like, if everything is a pointer, we can just treat them all like variables, right? And that made the programming simple and you don't have to think about it. But conceptually, Python,
00:40:56.140 --> 00:41:04.680
everything is in the heap. Everything is a pointer. Even the number one, it's a flywheel pattern. I
00:41:04.700 --> 00:41:05.960
And even that's insane, right?
00:41:06.140 --> 00:41:06.820
Like that, yeah.
00:41:08.060 --> 00:41:12.880
I have three copies of 254, but I only have one copy of two.
00:41:14.120 --> 00:41:14.200
Sure.
00:41:15.880 --> 00:41:16.680
That is really.
00:41:17.020 --> 00:41:19.340
Don't stop to think about it because, yeah.
00:41:20.180 --> 00:41:20.300
Yeah.
00:41:20.480 --> 00:41:22.860
For people listening are like, okay, they've gone off a rail.
00:41:23.100 --> 00:41:25.020
Like they're a little, what are they talking about?
00:41:26.000 --> 00:41:34.180
An optimization in CPython is the numbers, I think maybe negative five to 255, some range like that.
00:41:34.420 --> 00:41:34.520
Yeah.
00:41:34.620 --> 00:41:35.920
They're pre-allocated.
00:41:36.020 --> 00:41:40.460
And every time you type a literal number like 72, it's the same number.
00:41:40.740 --> 00:41:49.620
It just all points at the immutable number 72 rather than creating, you know, like whatever the eight byte or four byte chunk of it is on the stack.
00:41:50.040 --> 00:41:50.180
Yeah.
00:41:50.520 --> 00:41:52.580
I appreciate it makes it faster, but it's just funky.
00:41:52.660 --> 00:41:53.460
Yeah, it's weird.
00:41:53.700 --> 00:41:55.700
Yeah, it's something you don't want to think about too much.
00:41:56.300 --> 00:42:03.920
A couple sort of cosmetic things, which again, if you're from Python and Python's your first language might take a little to get used to.
00:42:04.360 --> 00:42:18.480
one is brace brackets so uh like most programming languages space is not important uh and that takes i i remember it taking me a while to get used to that switching to python so i have uh patience and
00:42:18.660 --> 00:42:24.280
sympathy for people who started in python and have to go the other way this is pretty typical of most
00:42:24.600 --> 00:42:38.140
programming languages uh the it makes the parser's life easier um and i think after having coded in Python for almost two decades, I think I've come down on the side of screw the parser.
00:42:38.600 --> 00:42:43.020
So it's a little bit taking a little used to for me to get back to it.
00:42:43.060 --> 00:42:46.740
But yeah, you, you put things in brace brackets to denote them.
00:42:47.120 --> 00:42:47.180
Yeah.
00:42:47.300 --> 00:42:51.500
I mean, look, the job of the parser is to make your life easy.
00:42:51.840 --> 00:42:52.620
Not the other way around.
00:42:52.760 --> 00:42:59.400
So I get, but I have run into situations where some little bit of formatting has been off.
00:42:59.900 --> 00:43:00.120
Yes.
00:43:00.320 --> 00:43:14.080
On my indentation and a reformat the code broke the code because maybe I had three indentations, three spaces instead of four for who knows, maybe I hit the delete button on accident or something weird like that.
00:43:14.340 --> 00:43:16.800
And I said, oh, well, look, this didn't line up right.
00:43:16.880 --> 00:43:18.480
Like I'll just hit like reformat code.
00:43:18.520 --> 00:43:20.440
And it's like, oh, well, that needs to go back to the left.
00:43:20.840 --> 00:43:23.300
And it's like changed actually how it works.
00:43:23.560 --> 00:43:23.640
Yep.
00:43:23.940 --> 00:43:27.840
So copy and paste is problematic in Python.
00:43:28.080 --> 00:43:28.200
Yeah.
00:43:28.500 --> 00:43:29.400
It's really problematic.
00:43:29.840 --> 00:43:32.740
And with the braces, like it could just have no indentation.
00:43:32.810 --> 00:43:33.900
It could be all gnarly.
00:43:33.910 --> 00:43:34.960
It could be minified, whatever.
00:43:35.050 --> 00:43:39.960
You just hit reformat and boom, it's reliably put back together well.
00:43:40.400 --> 00:43:45.400
So I'm going to give Python an 80% plus, 20% minus.
00:43:45.620 --> 00:43:47.340
I agree that it's nice.
00:43:47.600 --> 00:43:51.260
It's not there, but it's not just there is value to it.
00:43:52.340 --> 00:43:53.940
Structural correctness value to it.
00:43:54.000 --> 00:43:54.100
Yep.
00:43:54.290 --> 00:43:54.400
Yep.
00:43:54.780 --> 00:44:02.660
I also, you know, it forces programmers to behave themselves, which if you don't get your spacing right, your code doesn't work.
00:44:02.820 --> 00:44:04.300
It kind of makes the spacing consistent.
00:44:04.840 --> 00:44:05.240
Yes, exactly.
00:44:05.580 --> 00:44:14.660
That was what it was optimized for is like, you're going to make your code readable because you have to write it in a way that its structure and its readability match.
00:44:14.740 --> 00:44:15.580
And that's beautiful.
00:44:16.080 --> 00:44:18.980
But it is a little, it can have problems.
00:44:19.340 --> 00:44:19.460
Yeah.
00:44:19.680 --> 00:44:28.720
And being a veteran of the tabs versus spaces war of the nineties, eliminating that at the, at the syntax level is kind of interesting.
00:44:29.040 --> 00:44:33.340
It really is like, and you know what, there was a gosh, what PyCon was it?
00:44:33.340 --> 00:44:40.920
I think it was one Cleveland, maybe three, four years ago, there was a PyCon where one of the vendors clearly came.
00:44:41.170 --> 00:44:47.080
It was a tool vendor that came from all the, they weren't Python specific, but they made tools for Python people.
00:44:47.200 --> 00:44:51.800
and I would even maybe shout them out, or I'd call them out, but I don't even remember what it was.
00:44:52.280 --> 00:44:55.760
But they were giving away t-shirts that said tabs versus spaces.
00:44:55.890 --> 00:44:58.180
And you had to pick, I'm team tab, I'm team spaces.
00:44:58.760 --> 00:44:59.800
I'm like, what are you doing?
00:44:59.960 --> 00:45:04.460
Does nobody know that this literally is not even a choice in this language?
00:45:04.740 --> 00:45:05.660
Why are you here?
00:45:06.420 --> 00:45:12.280
It's a fun gag, but anyone on not team spaces is not going to run.
00:45:12.360 --> 00:45:13.280
What is wrong with you?
00:45:14.320 --> 00:45:18.920
Yeah. That's a team spaces versus teams. My code won't compile. Yeah.
00:45:21.440 --> 00:45:21.960
Yeah.
00:45:22.530 --> 00:45:32.660
An interesting side effect of this that I kind of like in this language. I don't know if I've seen it elsewhere. So like most languages, it has this rust has this concept of a statement versus
00:45:32.770 --> 00:45:44.640
an expression. Most things are expressions. And in fact, your brace bracket is the definition of a new expression. And as a result of that, the end of the brace bracket can return something. So you
00:45:44.670 --> 00:45:57.580
can do an assignment to a collection of code in a brace bracket. So this ends up being kind of like an inline function. and so that's kind of interesting to me and it, it, compiles down
00:45:57.800 --> 00:46:04.100
beautifully. it's, it's got that, and then it does this weird thing where it's got implicit
00:46:04.100 --> 00:46:16.780
returns. And so I really wish they had not done the implicit return. I am never ever going to be on team implicit return. I just can't. It drives me nuts. and, but the idea of having,
00:46:16.900 --> 00:46:27.840
arbitrary expressions through the brace brackets is kind of elegant. So, so yeah, one point up, one point down, whatever. and then, you know, there's some odd odds and ends, right? It's, it's,
00:46:27.900 --> 00:46:38.280
uh, FN instead of def, which quite frankly, as soon as I saw it was like, yeah, that actually makes an awful lot more sense. That tells me what it is. Def for define, define what? What am I
00:46:38.380 --> 00:46:43.880
defining? FN? It's a function. That makes sense. And then one of the other things that I kind of
00:46:44.040 --> 00:46:55.520
liked a lot is, so they release a lot more frequently in Rust. So it's, there's a new, a new version coming out every six weeks, which when you come from the Python world,
00:46:55.620 --> 00:47:06.140
that sounds insane, right? Like how do you stay on top of this? But they've got this separate concept from versions that they call additions. And an addition is a three-year cycle and things
00:47:06.440 --> 00:47:18.220
stay compatible within the addition. And what's more, not only do they do that, but the compiler is able to compile to older additions. So when you compile the code, you can actually say,
00:47:18.300 --> 00:47:30.140
I want to be using an older addition. And so they have basically this forever concept of backward compatibility. So now it's still a young enough language. I suspect at some point they may
00:47:30.210 --> 00:47:36.040
give up on that. cause this, this to me smells of maintenance hell. It's fine when there's three
00:47:36.280 --> 00:47:41.440
editions. What if there were 35? Yeah. but for the, for the time being, although there's been a
00:47:41.580 --> 00:47:53.480
fair amount of change in the language, in the last few years, you're not screwed by it. And it's not this constant race to stay on top of it. You can just change the edition target and you're
00:47:53.520 --> 00:48:06.820
fine. So I kind of like the idea. I think it would be kind of neat if the Python compiler, maybe, you know, if I was, I guess the changes in Python aren't as bad, so maybe it's not as extreme,
00:48:07.200 --> 00:48:21.859
but I don't know. This just sort of appealed to me. Yeah, it does to me as well. I love the freshness of it. I just got a new version of Rust this morning. I was trying to update my libraries and tools, and it said there's a new version of Rust. Yes. Okay. So I think that might be a good
00:48:21.880 --> 00:48:29.980
good time to maybe talk about like getting started and so on as maybe start by installing yeah uh so
00:48:30.480 --> 00:48:40.200
uh the good news is if you're in the unix world uh some sort of Linux or mac os this is uh this is a breeze you go off to the website you copy and paste the command onto the terminal and you're
00:48:40.280 --> 00:48:50.380
more or less done uh we do the thing that we normally do we run arbitrary code from the internet that's right as root on our machine i'm sure it's fine yeah it's fine uh if you go off to
00:48:50.200 --> 00:48:51.740
So rest up, rustling.org.
00:48:51.940 --> 00:48:53.920
there is right on the front page.
00:48:53.980 --> 00:48:56.480
There is a little shell command that you install.
00:48:56.960 --> 00:49:03.020
This actually installs a tool called rust up rust up is kind of like pie M and that it handles installation updates of the language.
00:49:03.480 --> 00:49:10.220
It install, it installs, rust C, which is the compiler and more importantly, cargo, which is the tool.
00:49:10.420 --> 00:49:13.340
That's kind of like uv that is what you actually use.
00:49:13.360 --> 00:49:15.400
You almost never call rust C directly.
00:49:15.700 --> 00:49:19.300
So rust up handles the version management of all that kind of stuff.
00:49:19.960 --> 00:49:26.000
And once you've got that going, then you use cargo to create a new project.
00:49:26.760 --> 00:49:28.660
Again, very uv-esque here.
00:49:28.700 --> 00:49:31.980
So you would say, you know, if I'm doing hello world, it would be cargo new hello.
00:49:32.660 --> 00:49:36.800
That creates a cargo.toml, which is the equivalent of pyproject.toml.
00:49:36.960 --> 00:49:38.400
It creates a source directory.
00:49:39.260 --> 00:49:43.880
By default, it creates a git repo and a git ignore file, which drives me nuts.
00:49:43.920 --> 00:49:45.420
And I turned that off as soon as I could.
00:49:45.620 --> 00:49:46.880
I want to be in control of that.
00:49:47.080 --> 00:49:47.620
Don't do it for me.
00:49:48.260 --> 00:49:53.140
And it creates a little stub main file, which actually has a function in it.
00:49:53.610 --> 00:49:58.000
So you actually can run cargo new hello and you get a compilable program.
00:49:58.390 --> 00:50:05.400
Then you write your rest and you run cargo run and cargo run builds and runs the code for you.
00:50:05.550 --> 00:50:12.160
Now, because it's a compiled language, the result is a target that goes into the target directory.
00:50:12.690 --> 00:50:16.920
You could run that explicitly, but it's buried like three directories down.
00:50:17.200 --> 00:50:20.260
So rather than do that, you just call run and it does it for you.
00:50:20.980 --> 00:50:25.100
And there are flags you can use it to go from debug mode to release version.
00:50:25.780 --> 00:50:30.480
Your debug tends to be about 30% larger because it includes debug information.
00:50:32.100 --> 00:50:32.820
While the production mode...
00:50:32.820 --> 00:50:35.540
That's par for the course for people who use those things.
00:50:35.720 --> 00:50:39.140
Yeah. And in fact, on Windows, it produces...
00:50:39.140 --> 00:50:41.080
I think in Windows, it's packaged as a separate file.
00:50:42.060 --> 00:50:46.800
The debug info is in a separate file, which is, again, a standard sort of Windows thing to do.
00:50:47.100 --> 00:50:55.820
Yeah, Windows often you can put, I forgot what they're called, but there's like a debug symbols that is a file that you can put like next to a DLL or an exe and it'll pull that in.
00:50:56.030 --> 00:50:58.600
And so it handles all of that kind of good stuff for you.
00:50:59.780 --> 00:51:04.540
And then this is then the thing that you would distribute if you were trying to distribute it.
00:51:05.599 --> 00:51:10.380
There's a command for building on its own and then the command for run both builds it and runs it.
00:51:10.680 --> 00:51:18.440
One of the things I'm still not quite used to is it outputs some information from the build before it actually runs the code.
00:51:18.710 --> 00:51:23.280
So you get two or three lines of info before you actually see the output from your program, which drives me nuts.
00:51:23.800 --> 00:51:29.920
But there is a dash queue to tell it not to do that so that if I'm running it, I don't want to see your compiler stuff.
00:51:29.990 --> 00:51:32.180
I want to actually have it run unless something went wrong.
00:51:32.480 --> 00:51:36.500
So yeah, cargo really is the key to doing all of this kind of stuff.
00:51:36.840 --> 00:51:42.660
Like uv, it also manages what they call crates, which are the Rust equivalent of wheels.
00:51:43.200 --> 00:51:48.300
There is a crates.io is the equivalent of PyPI.
00:51:49.040 --> 00:51:51.480
And you can write libraries and upload them there.
00:51:51.880 --> 00:51:59.760
And like with Python, this is a fairly robust community that's writing and trading code here.
00:52:01.780 --> 00:52:04.520
331,019 crates in stock.
00:52:04.920 --> 00:52:05.920
We look at PyPI.
00:52:06.600 --> 00:52:09.440
think we're at 750 the last time I looked.
00:52:09.790 --> 00:52:10.580
I haven't looked for either.
00:52:12.140 --> 00:52:14.280
889,000, 890,000.
00:52:14.570 --> 00:52:18.440
So there are more, but I don't think that is necessarily the core metric.
00:52:18.650 --> 00:52:29.140
No, and it's also not a fair comparison because proportionately the number in crates would actually seem smaller to a Python developer.
00:52:29.230 --> 00:52:34.380
And what I mean by that is if when you're coming from the batteries included world, yeah, there aren't a lot of batteries in Rust.
00:52:34.920 --> 00:52:39.000
So something as simple as like a random number, that's a crate.
00:52:39.860 --> 00:52:44.100
And they've done this to try and keep the footprint small, which I kind of understand.
00:52:44.900 --> 00:52:51.480
For somebody who's starting out, this can be a little, so like I had this, I'm paranoid, right?
00:52:51.700 --> 00:52:54.280
So I want to know where my code is coming from.
00:52:54.680 --> 00:52:57.460
If I'm in the Python world, I trust the standard library.
00:52:57.530 --> 00:53:00.180
If I stick to the standard library, I know I have a degree of safety.
00:53:00.520 --> 00:53:05.360
Once I step outside of the standard library, I want somebody to tell me they've used it and they trust it.
00:53:05.820 --> 00:53:09.840
And, you know, for certain kinds of libraries, there's enough press that you can kind of get the idea.
00:53:10.150 --> 00:53:14.880
I haven't yet quite figured out how to get that information in the Rust world.
00:53:15.480 --> 00:53:26.660
And because things like random, which you use all the time, are actually crates, you kind of have to do a little bit of the, there's a little more rolling the dice on do I trust this code to use it kind of thing going on there.
00:53:27.140 --> 00:53:29.880
But I suspect that's still my newness to the community.
00:53:30.140 --> 00:53:35.540
Yeah, perhaps. You know, Chris, just because you're paranoid doesn't mean they're not after you.
00:53:35.800 --> 00:53:38.160
Yep, that's right. That's exactly right.
00:53:38.500 --> 00:53:43.020
And with the supply chain stuff, it means, I mean, it's crazy.
00:53:43.380 --> 00:53:46.280
In the world of the internet, they are out to get you. Yes, without a doubt.
00:53:47.500 --> 00:53:59.220
Oh my gosh. And sometimes you hear the pounding on the door. You're like, oh my gosh, go away, please don't do that. Let's just like reflect for a minute. We talked about like cargo crates and all
00:53:59.200 --> 00:54:13.440
all these things, we've seen a big revolution in Python packaging, deployment, flexibility, project management, all of those things. And much of that has actually come from the Rust side. A
00:54:13.600 --> 00:54:27.180
lot of the tools like uv and others are seriously inspired by cargo, the crates, and these types of things. But this was built in a world where PyPI already existed and npm already existed. And they
00:54:26.980 --> 00:54:37.040
could go really good. Ooh, that's not good. Let's do it this way. Right. So there's like this sort of interplay or this circling of these two worlds. Yeah. It's, you know, without,
00:54:37.410 --> 00:54:49.800
I'm not trying to start a flame war, but the decision that the PSF made that, managing packages wasn't really part of the language and that we should have this plethora of third-party
00:54:50.020 --> 00:55:03.160
tools to do that. I think that was a mistake. And I think the Rust people recognize that and decided to bundle this in. it's, it's a lot cleaner and there's a lot less wondering of what's
00:55:03.260 --> 00:55:16.620
going on. and, now in defense of rust, sorry, in defense, I don't know who I'm defending. Nevermind. I'm not sure whatever I'm going to defend. I'm not going to defend. Uh,
00:55:16.950 --> 00:55:28.440
the, I think the target for rust is simpler. And, part of the thing that happened in the python world is because of that dynamicism it creates all these other kinds of complications
00:55:29.170 --> 00:55:35.500
um so yeah it's right my package also requires a fortran compiler exactly yeah right whereas
00:55:35.650 --> 00:55:41.140
because you're compiling these things down you some of that stuff goes away so so yeah it's it's
00:55:41.300 --> 00:55:55.780
it's a challenge i agree but also wheels do exist now yep in the python world created them and they didn't before and that was like a super hard problem because yeah everything needed like all these bespoke tools just to install something interesting. And then they said, no, no, no,
00:55:55.900 --> 00:56:08.860
let's just make wheels. You can just have like, why do we have to make everyone recompile everything from source? So they kind of got there. Another thing I think- They're making progress. Yeah, no, they're making progress. Yeah. Another thing I think is interesting around this is
00:56:08.860 --> 00:56:21.160
you talked about the sparseness of the standard library equivalent of Rust. I feel like Python batteries included the richer standard library. It is that way because PyPI didn't exist.
00:56:21.560 --> 00:56:27.220
The concept of a package manager didn't exist when Python, you know, and honestly, like what was 91?
00:56:27.660 --> 00:56:28.520
Like the web didn't exist.
00:56:28.690 --> 00:56:32.640
Like getting stuff afterwards was really, really hard.
00:56:32.840 --> 00:56:34.920
If it were easier, they may have made different choices.
00:56:35.400 --> 00:56:35.520
Yeah.
00:56:35.660 --> 00:56:38.360
It's, it's a consequence of this language being around since the nineties.
00:56:38.480 --> 00:56:38.540
Right.
00:56:38.760 --> 00:56:45.160
So the decisions up front were, and what, and what it was designed for versus what it's grown into.
00:56:45.360 --> 00:56:57.980
you know, that's, we should all be, as software developers, we should all be so lucky as having our initial designs become questionable because 35 years later, people are still using our software
00:56:58.480 --> 00:57:03.260
all over the planet. Yeah. If people want to criticize mine because it's so popular in 30
00:57:03.380 --> 00:57:14.780
years, I'd be happy as well. Yeah, exactly. All right. We've got a little bit of time left, but it's not a ton. I think let's focus on one more section and that would be, how do I go from
00:57:15.180 --> 00:57:20.760
Rust land to Python land. So there are different libraries for doing this. The most common one out
00:57:20.900 --> 00:57:28.480
there is a crate called Py03. And essentially what this does is provide you with the tools
00:57:29.060 --> 00:57:36.420
to align your Rust code as if they are Python objects. And then there are a couple other tools
00:57:36.920 --> 00:57:51.480
that you can use to actually do the packaging part. So what Py03 does is it defines the interface the compiled object, which is a dynamic library, so a.so file or a.dll, and then does that in
00:57:51.850 --> 00:58:02.780
compliance with Python's ABI. And then there are tools out there that you can use, which will put those inside of a virtual environment so that Python can see them. And then in Python, you can
00:58:03.020 --> 00:58:08.380
load that code that you wrote as if it were a regular Python module written in Python.
00:58:09.000 --> 00:58:12.600
The how Py03 does this is a couple different things.
00:58:12.940 --> 00:58:17.600
One, it has Rust objects that are compatible with the Python objects.
00:58:17.920 --> 00:58:22.220
So as an example, Pyint is a Rust object that represents a Python integer.
00:58:22.580 --> 00:58:30.840
So if you need access inside of your Rust code to the integer inside of the Python space, this acts as a mechanism to get at it.
00:58:31.100 --> 00:58:33.680
It will also map Rust concepts.
00:58:34.240 --> 00:58:47.000
So rather than using pyint, you can just use, say, a int32, and py03 will take care of mapping that up to the Python integer when Python's using it in the Python side of the world.
00:58:47.400 --> 00:58:55.240
The other thing that it does is Rust has a mechanism that is macros for changing how things get compiled.
00:58:55.740 --> 00:59:00.760
And py03 ships with a bunch of macros that essentially you attach to something like a function.
00:59:01.140 --> 00:59:06.340
So if you want the function or a class to be available to Python, you wrap it with one of these macros.
00:59:06.860 --> 00:59:12.780
It's just a regular Rust function, but the macro is what does the mapping and makes it available.
00:59:13.130 --> 00:59:18.120
So with the right use of the macro, you can say things like, you know, this is my function.
00:59:18.280 --> 00:59:19.060
It's got three arguments.
00:59:19.720 --> 00:59:21.620
These arguments need to map to this, et cetera.
00:59:22.120 --> 00:59:26.960
And essentially what happens when you compile it is all of this gets put into a.so.
00:59:27.420 --> 00:59:38.500
And then you use tools like Maturin or others that then put that into a virtual environment and to handle the packaging side of things so that your Python code can use it.
00:59:38.860 --> 00:59:47.840
And from Python's perspective, once that's installed in the right place, you just import foo from bar as you would with any other module and you've got access to it all.
00:59:48.180 --> 00:59:48.400
Interesting.
00:59:48.680 --> 00:59:51.480
Now, it doesn't have to be all or nothing as well.
00:59:51.820 --> 00:59:54.720
For example, remind me how to do this because I forgot how to do it.
00:59:54.820 --> 01:00:01.260
but you can create a project that has some Rust code and some Python code and then build that into a wheel.
01:00:01.760 --> 01:00:09.440
But you could say only part of my code is gonna be Rust and the rest of it that's not performance critical, that's all Python all day long.
01:00:09.700 --> 01:00:22.540
Yeah, so for example, if you look at, if you pay close attention when you install Polars, you're actually getting two wheels, one of which is a universal wheel, which is because it's universal, it only contains Python code.
01:00:22.860 --> 01:00:37.500
And the other of which is it's figured out what platform you're on and gives you the actual compiled Rust version of the Polars library. So they've kind of got these two things going on. Now, I don't know Polars well enough. I've never looked at their source code, so I don't know what they've
01:00:37.560 --> 01:00:47.520
got in each one of those packages, but they've built something that is comprised of both of those things. In their case, it's in two separate wheels. It doesn't have to be. And essentially,
01:00:47.820 --> 01:01:02.360
you're using a tool like Mature and it takes care of this for you. So if you're after a, if you're after building a library where there's a part of it that has to be very performant, but you want to write most of it in Python because, you know, it's easier to code in,
01:01:03.140 --> 01:01:06.480
then there's, you basically do that and Maturin will let you bundle all of that up.
01:01:07.380 --> 01:01:21.380
And this is no different than any other plugin mechanism. It's just that these are the tools that Rust provides to build those kinds of plugins. So if you think of tools like Polars or NumPy or any others that do this kind of concept where some of it's written in a lower
01:01:21.400 --> 01:01:23.740
level language, I O three just lets you do that.
01:01:23.920 --> 01:01:33.320
I think there's a lot of, a lot of low hanging fruit for people to go apply a profiler to their code and say, no, it really only matters at least 20 lines of code here.
01:01:33.460 --> 01:01:33.520
Yeah.
01:01:33.700 --> 01:01:34.220
What if?
01:01:34.580 --> 01:01:34.740
Yeah.
01:01:35.160 --> 01:01:42.580
The challenge you have to pay is every time you do this, you're crossing a boundary and there is a cost to crossing that boundary.
01:01:43.020 --> 01:01:56.140
So, there, if you're writing the code in such a fashion that you're constantly going back and forth or your objects are constantly going back and there's overhead to that so writing in and rust doesn't guarantee that it will be faster
01:01:56.740 --> 01:02:10.300
could make it slower it could make it slower like with everything uh but if you're doing something you know it's something like polar's where you're doing big number crunching uh and you're you know you're calling into the api and then letting it crunch and then it spit another answer out then
01:02:10.500 --> 01:02:20.920
yeah you can you can see a significant speed up yeah or pydantic where it comes in as json anyway and it's got to be transformed to something, let that happen in Rust and then talk to it.
01:02:21.260 --> 01:02:23.080
So yeah, this is really good.
01:02:23.500 --> 01:02:29.860
I'm going to have Pablo and Laszlo on to talk about the new profiler that's in 3.15.
01:02:30.140 --> 01:02:31.540
That's really interesting, the profiling module.
01:02:31.980 --> 01:02:37.200
One of the things that's fascinating about that, I don't have anything in production in 3.15.
01:02:37.360 --> 01:02:40.900
All my stuff's in 3.14 or lower, like older.
01:02:41.280 --> 01:02:49.760
Now, one of the things that's cool about the new profiler is you can attach it to stuff running in production, profile it, and then walk away.
01:02:49.850 --> 01:02:52.120
You know, like, hey, let's just go, it's running.
01:02:52.280 --> 01:02:54.760
A bunch of people are using this app, like it's an API or something.
01:02:55.140 --> 01:02:58.880
Let's just hook onto it for 30 seconds, get some data and step back.
01:02:59.150 --> 01:03:05.200
And then maybe you could look at, oh, actually, if we could just make this one part faster, that would really be a big deal.
01:03:05.290 --> 01:03:08.100
So I think the possibility for this is just getting easier.
01:03:08.420 --> 01:03:16.380
Yeah, well, and, you know, the general advice I give folks when I talk about optimization is don't and then measure, right?
01:03:16.760 --> 01:03:21.320
So when you're trying to figure it out upfront, it doesn't matter how good you are at this.
01:03:21.420 --> 01:03:24.640
You tend to make the wrong assumptions eventually.
01:03:25.200 --> 01:03:29.940
And so, yeah, build something, then profile it, and then figure out where you're spending all your time.
01:03:30.260 --> 01:03:32.660
Yeah, I've had a couple of experiences.
01:03:32.940 --> 01:03:39.740
I won't go into the details of it, but I've told it a time or two way, way back in the day where I was so wrong.
01:03:40.040 --> 01:03:40.100
Yep.
01:03:40.580 --> 01:03:43.060
So wrong about what was slow and what was fast.
01:03:43.170 --> 01:03:47.200
And if I had just pursued my intuition, it would have been months of bad choices.
01:03:47.670 --> 01:03:47.860
Yeah.
01:03:48.400 --> 01:03:58.700
And there's a concept called Amdahl's Law, which is essentially, I'm going to oversimplify it, but if your code is spending 10% of its time in that place,
01:03:59.859 --> 01:04:06.720
speeding that up by 2x is only ever going to get you a 10% gain because your code's spending the other 90.
01:04:07.380 --> 01:04:10.260
There's a diminishing return aspect to it as well.
01:04:10.600 --> 01:04:20.860
And as programmers, I think we often get tied up in the, oh, wouldn't it be cool if I made this code three times harder to read and it'll be, you know, half a millisecond faster.
01:04:20.970 --> 01:04:22.240
And how often do you call that?
01:04:22.440 --> 01:04:22.940
Once a year.
01:04:23.170 --> 01:04:23.720
Oh, okay.
01:04:23.980 --> 01:04:30.160
Well, there's a month of your life you got back in order to optimize by a millisecond, right?
01:04:30.380 --> 01:04:33.060
Where you got to find the stuff that is actually causing the problem.
01:04:33.600 --> 01:04:33.740
Yeah.
01:04:34.050 --> 01:04:36.100
You gave a 50% speed up example.
01:04:36.320 --> 01:04:38.860
Like, let's take it to an insane level.
01:04:39.120 --> 01:04:42.880
20% of your code, 20% of time you spend in some bit of code.
01:04:43.120 --> 01:04:49.620
If you could make it infinitely faster, the best you're going to achieve is your program is going to be 20% faster.
01:04:50.260 --> 01:04:53.660
You know, maybe, oh, I was running this on a single CPU thread.
01:04:54.040 --> 01:04:59.540
I'm going to actually get a GPU machine with a crazy thing and do a bunch of GPU programming.
01:04:59.660 --> 01:05:03.160
And I can parallelize this and I'll get it down to a thousand times faster.
01:05:03.600 --> 01:05:05.660
Is that worth a 20% speed up?
01:05:05.700 --> 01:05:08.800
If it takes five milliseconds, you've saved one millisecond.
01:05:09.000 --> 01:05:18.640
hooray look how much harder your life and how much more expensive deployment is and so on right yeah yeah so it's certainly uh something that people should keep in mind all right well i think
01:05:19.300 --> 01:05:30.540
let's let's wrap things up here rust is super interesting i think it's got a place in python and even if you don't want to write rust a lot of these really important libraries are
01:05:31.080 --> 01:05:41.260
somewhat backed by rust so you want to read them and maybe contribute to the to the caramely shell or the noogity inner, but you still kind of want to understand the bits. I think maybe a quick
01:05:41.440 --> 01:05:51.720
shout out to your course. People should definitely give this a listen or a watch. Just talkpython.fm, click on course at the top. Rust will be, the Rust course will be right at the top of that list.
01:05:52.060 --> 01:05:53.940
Yeah, it was fun to build. I hope people enjoy it.
01:05:54.260 --> 01:06:02.980
Yeah, I think they will. And more importantly, more broadly, I suppose, people want to get started with Rust. You've inspired them, Chris. They're ready. What do you tell them?
01:06:04.160 --> 01:06:06.580
Rustlang.org is pretty much the place to start.
01:06:08.040 --> 01:06:10.040
It's remarkably well documented.
01:06:10.340 --> 01:06:11.980
There's a lot of good guides and things out there.
01:06:13.880 --> 01:06:18.060
The documentation right on that site, they've got the Rust book right there.
01:06:18.660 --> 01:06:20.580
It's quite easy to follow.
01:06:20.940 --> 01:06:23.620
It has a lot of really, really good examples in it.
01:06:24.100 --> 01:06:25.980
So that's definitely a place to go.
01:06:26.460 --> 01:06:33.480
The other space, just a bit of a shout out would be, there's a awesome list called Awesome Python RS.
01:06:33.980 --> 01:06:39.380
And it's just a massive list of the tools and libraries that use Rust in the Python space.
01:06:39.870 --> 01:06:50.280
So if you're looking for, rather than like education book examples, you're looking for places that actually use it and you want to, and you want to troll through some code, that's a great
01:06:50.370 --> 01:06:55.040
place to go looking for interesting libraries to take a look at. Yeah. I second that. I'm,
01:06:55.160 --> 01:07:03.660
I'm such a sucker for awesome lists. Yes. That could be, you want to watch a movie? I found a new awesome list. I'm just going to poke around this for like the next half hour, if you don't
01:07:03.800 --> 01:07:15.140
mind, you know? Yeah. And, you know, there's some very classic examples on this list of like drop-in replacement for speed things, right? So there's a cryptography library and there's a JSON library,
01:07:15.420 --> 01:07:30.020
both of which are basically drop-in replacements for stuff from the standard library. And because they're written in Rust, they're screamingly faster. So, you know, that example of looking for the thing that you need to optimize, there's some good ideas in there that you can dig into.
01:07:30.240 --> 01:07:38.880
Yeah. And you know, I gave you the example of like, well, we could just rewrite this bit of your slow code and rust. It might already be written as a library.
01:07:38.880 --> 01:07:40.200
Someone else may have done it as well. Yes.
01:07:40.460 --> 01:07:43.400
Yeah. Just swap, swap your JSON parsing library or whatever. Right.
01:07:43.600 --> 01:07:54.360
And, and a lot of the, Python things that are like Python libraries that use rust, a lot of them are actually just thin wrappers to existing rust libraries.
01:07:54.760 --> 01:08:03.480
So that somebody is rather than writing something from scratch, they're like, Hey, there's this neat library in Rust that does this thing that I like, and I wish it was in Python.
01:08:03.660 --> 01:08:10.600
And they write like four lines of code that are essentially the API wrapper down to make it, expose it as a module.
01:08:10.740 --> 01:08:16.180
And now we can take advantage of the fact that there's this whole other community that's trying to do these efficient things.
01:08:16.640 --> 01:08:24.839
And we don't have to trust the suitability and correctness of somebody saying, hey, I spent a weekend rewriting the JSON parsing.
01:08:24.920 --> 01:08:26.880
Like, ah, brightening.
01:08:26.920 --> 01:08:32.960
These are things with thousands of stars and many contributors because the Rust community themselves are using them, right?
01:08:33.240 --> 01:08:33.580
Right, right.
01:08:33.580 --> 01:08:35.799
And if you just wrap it, you're pretty safe.
01:08:36.420 --> 01:08:37.620
Polars is an example, right?
01:08:37.799 --> 01:08:39.819
Polars is a Rust library for Rust programmers.
01:08:40.400 --> 01:08:43.100
And then there's a Python thing on top of it, right?
01:08:43.359 --> 01:08:48.259
So you're getting not just the Python people using it, but the Rust people using it as well.
01:08:48.680 --> 01:08:49.319
What is that?
01:08:49.319 --> 01:08:52.359
A caramel dipped apple equivalent version or something like that?
01:08:52.500 --> 01:08:52.620
Yes.
01:08:53.040 --> 01:08:53.680
I don't know.
01:08:53.900 --> 01:08:55.540
There's caramel everywhere by the time we're done.
01:08:55.600 --> 01:08:59.220
So it's a messy, messy kitchen.
01:09:00.600 --> 01:09:01.440
It was delicious.
01:09:01.680 --> 01:09:02.980
It was a delicious episode, Chris.
01:09:03.259 --> 01:09:03.839
Thank you for being here.
01:09:03.920 --> 01:09:04.160
That's all right.
01:09:04.580 --> 01:09:05.060
Happy to be here.
01:09:05.400 --> 01:09:05.779
Yeah, bye-bye.
01:09:06.759 --> 01:09:08.940
This has been another episode of Talk Python To Me.
01:09:09.319 --> 01:09:10.040
Thank you to our sponsors.
01:09:10.279 --> 01:09:11.540
Be sure to check out what they're offering.
01:09:11.740 --> 01:09:13.100
It really helps support the show.
01:09:14.000 --> 01:09:15.500
This episode is brought to you by Sentry.
01:09:16.319 --> 01:09:19.319
You know Sentry for the error monitoring, but they now have logs too.
01:09:19.680 --> 01:09:26.680
And with Sentry, your logs become way more usable, interleaving into your error reports to enhance debugging and understanding.
01:09:27.299 --> 01:09:30.420
Get started today at talkpython.fm/sentry.
01:09:31.180 --> 01:09:38.980
And it's brought to you by the Talk Python in Production Book, an inside look at 10 years of the real-world DevOps behind the Talk Python sites and apps.
01:09:39.319 --> 01:09:42.040
Check it out at talkpython.fm/DevOps book.
01:09:42.720 --> 01:09:54.860
If you or your team needs to learn Python, we have over 270 hours of beginner and advanced courses on topics ranging from complete beginners to async code, Flask, Django, HTML, and even LLMs.
01:09:55.180 --> 01:09:57.540
Best of all, there's no subscription in sight.
01:09:58.020 --> 01:09:59.680
Browse the catalog at talkpython.fm.
01:10:00.380 --> 01:10:05.060
And if you're not already subscribed to the show on your favorite podcast player, what are you waiting for?
01:10:05.740 --> 01:10:07.480
Just search for Python in your podcast player.
01:10:07.580 --> 01:10:08.460
We should be right at the top.
01:10:08.900 --> 01:10:11.660
If you enjoyed that geeky rap song, you can download the full track.
01:10:11.860 --> 01:10:13.780
The link is actually in your podcast blur show notes.
01:10:14.580 --> 01:10:15.940
This is your host, Michael Kennedy.
01:10:16.340 --> 01:10:17.400
Thank you so much for listening.
01:10:17.600 --> 01:10:18.400
I really appreciate it.
01:10:18.860 --> 01:10:19.540
I'll see you next time.
01:10:45.320 --> 01:10:47.120
I think is the norm.
01:11:16.360 --> 01:11:16.380
Продолжение следует...