Hello and welcome to Python Bytes, where we deliver news and headlines directly to your earbuds.
This is episode 180, I can't believe it, recorded April 29th, 2020. It's almost Mayday.
I am Brian Okken.
And I'm Michael Kennedy.
And this episode is brought to you by DigitalOcean, and we'll talk more about them a little later.
Well, I have some very timely news, because not very long ago, a couple days ago, Ubuntu 20.04 is out.
What?
That's cool, right?
Yeah, the new Ubuntu.
And it's, why is this big news?
Well, there's a lot of releases of Ubuntu and whatnot.
But this is the first new LTS long-term support version in two years.
So basically, this is the first real production-grade version of Ubuntu that's been out in two years.
So that's a big deal, I think.
Oh, yeah, really big deal.
And it's got something special in it.
It does.
It hates legacy Python, but it loves modern Python.
So one of the things that's bugged me about 1804, which is what I've been using for production, is it was stuck on 3.6.
I mean, imagine April 2018.
It's using Python 3.6.
It didn't change.
Well, what's the current version now?
Well, that's Python 3.8.
Sadly, 3.9 is going to be out really soon.
And this is 3.8.
But nonetheless, hey, 3.8 is awesome.
It has a bunch of cool new features that we can use.
And yeah, it comes included.
I don't even think you have to pip install Python.
I think 3.8 is already there.
That's really cool.
Yeah.
And to get legacy Python, you can get it, but you have to go like apt install it explicitly to say, no, no, I want the old one.
Yeah.
Python 3.8.
Automatic.
It is now.
F-strings everywhere.
That's right.
Like, it's time to hit all your code with flint and auto F-string all the things.
So I upgraded all of the servers for Python bytes.
The servers are pretty small and simple.
But if you look at all the stuff that I'm running, there's actually a ton of servers.
And I actually talked about that with Dan Bader on Talk Python episode 215.
So people really want to look at what we're doing, what I'm doing here, what we're doing for Python bytes.
In terms of infrastructure, they could do that.
But upgraded a bunch of servers to 20.04.
There's a bunch of stuff that kind of built up cruft.
And I'm like, oh, we could do this way better.
Redid all that stuff over the weekend.
And so now everything's on the shiny new versions of Python 3.8 and Ubuntu 20.04.
And it went really well for me.
So that's great.
Yeah.
And the kernel has been upgraded to 5.4, which adds support for WireGuard, VPNs, better support for like Raspberry Pis and Intel and AMD hardware.
New version of GNOME.
You can install the desktop on top of the ZFS file system if you care about that.
And you talked about DigitalOcean at the top.
You can go to DigitalOcean right now and just check off.
I want a new 20.04 droplet.
Boom.
Off it goes.
That's how I got ours.
Oh, that's great.
Nice.
Yeah.
And actually, we've already had the kernel upgraded.
The 5.4 kernel upgraded to like a new version.
I just had to like apply some patches.
So I guess it's pretty active.
But here you go.
So yeah, different topic.
But for our servers, you have to like pay attention to kernel upgrades and stuff?
Yeah.
Apparently, yeah.
They're not like on a platform as a service type of thing.
It's not a big deal.
It's pretty regularly like once a month or whatever.
I'm usually logged in to one of them every couple of days doing something.
And it'll say, oh, like either it's already applied.
It says you got a reboot.
It'll be like obvious that there's an update when you log in.
And then I'm like, oh, I should just run that thing that upgrades all of them.
Okay.
Once I notice it.
Yeah.
So pretty much.
Yeah.
Okay.
Neat.
Yeah.
Okay.
Well, I'm going to switch hats.
So I want to talk about warnings.
So warning, I'm going to switch a hat.
And so Reuven Lerner is a friend of the show and great guy, teaches Python.
And we wrote an article called Working with Warnings in Python.
And I like this because I don't think we've talked about warnings much.
No, not much at all, actually.
It's a good introduction, but he talks about exceptions and the class hierarchy and printouts
and stuff.
But if you want to like, if something goes wrong, you kind of want, you've got options
of like printing out to the user or throwing an exception, but you also have warnings.
And how should you treat those?
And I love what he wrote.
He said, most of the time, warnings are aimed at developers rather than users.
Warnings in Python are sort of like the service needed light on a car.
The user might know that something is wrong, but only a qualified repair person will know
what to do.
Developers should avoid showing warnings to end users.
But one of the things that the warning system is used for is deprecation warnings.
A lot of projects do this where they kind of want to get rid of a feature so they can
refactor some stuff and or just doesn't fit in the API very well.
So they'll deprecate it and they'll issue a deprecation warning when somebody uses it.
So it's an alert.
It doesn't stop working, but it alerts people to that.
There's a warning.
One of the things I love about warnings is by default, pytest turns on warnings.
And so you can see those and you can also make them make pytest so that it fails on warnings.
So this is a good thing to pay attention to, but it doesn't stop your project.
That's cool.
I didn't know you can make pytest, like observe and use the warnings as an error.
Yeah.
The warning system gives you a whole bunch of stuff.
Python's warning system, it treats warnings as separate types of output so that we don't
confuse them with either exceptions or printed texts.
It lets us indicate what kind of warning we're sending the user.
So we have different types.
It's like the exception hierarchy.
You can have a warning.
There's a warning hierarchy.
You can create your own and you can filter on them so that you can screen out stuff that
you don't care about, selectively fix things.
Anyway, it's a very powerful system.
People should use it when they need it.
The article goes on to give specifics on the syntax of how to use them, how to create
custom warnings, and how to filter on them.
And it's a good intro.
Yeah, this looks super interesting and like something I should be paying more attention to
than I have so far.
Is this something I'm not really using?
I'm more a consumer of warnings.
I'm like, oh, that library, it started issuing warnings about something.
And sometimes it's really frustrating because it's like the library being used by the library
I'm actually trying to use is doing something wrong.
It says, well, this is going to be deprecated and now you've got to do this.
I'm like, well, but I'm not doing that.
I don't want to see this.
But nonetheless, it looks like way simpler than maybe.
I just haven't looked at it.
It looks great.
So I should use this more.
One of the cool use cases that I heard recently is using pytest warnings or pytest's knowledge
of warnings and testing your system when you're upgrading Python so that you can say,
oh, when we're, because Python will deprecate things too.
And then you can have a heads up that you need to start fixing your code because it'll
pinpoint you exactly.
It's kind of like the exception system.
It tells you exactly where it's coming from.
So yeah, that is really nice.
Do you want to know something else that's nice?
DigitalOcean.
DigitalOcean is very nice.
And DigitalOcean just launched their virtual private cloud or VPC system and new trust platform.
Ooh, a trust platform.
Together, these make it easier to architect and run serious business applications with
even stronger security and confidence.
VPC allows you to create multiple private networks for your account or your team instead of having
just one private network.
DigitalOcean can auto-generate your private networks, IP address range, or you can specify
your own IPs.
You can now configure droplets to have, to behave as internet gateways.
That's cool.
Yeah.
It's like your own little baby internet.
Yeah.
That's neat.
And a trust platform is a new microsite that provides one place to get all your security
and privacy questions answered and download our available security certifications.
DigitalOcean is your trusted partner in the cloud.
Visit pythonbytes.fm/DigitalOcean to get $100 credit for new users to build something
awesome.
Yeah.
We love it.
Like I just said at the outset, put Ubuntu 20.04 on there, and it's been working great
for so many years.
Now, one thing that I ran across, there's a few little libraries that are so simple, and
yet when you come across them, you're like, oh yes, this is so cool.
One of those that I go on and on about is unsync, how that unifies all the different APIs that
do asynchronous programming, like asyncio, threaded stuff, multiprocessing stuff, and whatnot.
Right?
So this is one I think that kind of is like that.
It's not about unification, but it's about solving a problem in a way that's kind of transparent
to the user, but is really, really awesome because it just adds some nice durability to
your code.
So there's different levels of like exception handling if you look at it, right?
So if you look at code, there's probably like the beginner level that has no try except blocks
anywhere in the code.
It's just like, I don't know what you call it.
Is that optimistic programming?
Like I don't need to do error handling.
It's going to be fine.
Everything's fine.
This is fine.
That's one way.
The next level would be to say, okay, I'm going to have some exception handling.
I'm going to do a try, do a bunch of stuff, except handle the error, right?
That's good.
And maybe you're catching different errors.
Like maybe that's another level.
I don't know what the making of these levels up a little bit, but even if you are catching
an error, something could have gone terribly, terribly wrong and corrupted your data along
the way.
So there's like durable error handling and there's, it isn't technically crashing at the moment
error handling, right?
So the durable error handling, I don't think a lot of people think about nearly as much.
So simple example is what you would maybe use a transaction for in a database is like,
I'm going to transfer money from this account to that account.
But what happens if the transfer to the second account fails?
I want to make sure I don't actually take the money from the first account, right?
Or I want to write some piece of data to a file.
So I'm going to open the file and I'm going to make sure there's a try accept.
I'm going to put it in a width block.
So the file pointer gets closed.
Everything's going to be good.
I'm going to make one change and another change.
And then a third change, like write these three things to the file.
What if the exception happens after the second line?
You've half written to the file.
Now what?
I don't know.
Wow.
That's bad, right?
Yeah.
So there's all these ways in which, like you still have a try accept.
You still catch it.
You still close the file pointer.
It doesn't matter.
It's corrupted, right?
So there's like this another level of error handling of like kind of treating memory and
files and whatnot as transaction, transactional type things, right?
If there's an error, they just go back the way they were.
And so this thing that this long winded introduction is about is called safer.
So a safer file writer.
And it's this cool, simple little thing.
Instead of saying with open file name as file pointer, you say with safer dot open.
File name as file pointer.
And then otherwise all your code is identical.
Okay.
Here's what it actually does.
So as you write to the file pointer, it's writing to a temporary file behind the scenes.
And then if, you know, when you exit a width block, the width block, the exit, the dunder exit
takes whether or not there was an error on the way out the door.
So, you know, as you exit the width block, did as, am I leaving because a crash or am I leaving
because everything is cool and we're done?
So it uses that information to either throw away the temp file or move the temp file over
top the thing you thought you were writing on.
Oh.
Isn't that cool?
So if there's an exception in your width block, it still closes up the file pointer and everything,
but your data is unchanged.
It's kind of like a transaction with a roll auto rollback for files.
That's pretty cool.
Isn't that cool?
And it's like 28 lines of code that does that little bit.
Yeah.
Is it any idea what the time hit is?
It's got to be a little bit, but.
It's pretty small because it just uses shutil to replace the file.
Like it writes to the file just as you would write to the file.
Okay.
And then at the very end, it goes, move this file to this destination and overwrite.
So it's basically adds a file move, which in an SSD is like nothing, right?
Okay.
It doesn't matter how big it is.
It probably just like updates the, I don't know, like the table in the drive, whatever
that means.
Yeah.
Isn't that cool?
That is very cool.
I like it.
Yeah.
So it seems so easy to use.
It looks like something that might be worth looking at.
So I'm linking to a couple of things.
I'm linking to an article that introduces this.
And in the beginning, apparently there was like some edge case where something wasn't
working quite right.
If you passed like an integer representing a file handle or something funky like that, it
didn't deal with that.
Right.
So there's a, another, like an updated article that doesn't have all the motivation, but then
talks about this fix.
And there's also a GitHub repo and you can just pip install it.
So all those things are good.
And the final in this section, I'm linking to the actual 28 lines of code.
Do you have that open?
I did.
Click on that really quick.
Cause I want to talk about a couple of really interesting patterns here.
Like if you wanted to study 28 lines of code that took and brought together a bunch of interesting
ideas, like, Whoa, this is pretty crazy.
So it has a generator expression on an infinite sequence of numbers to find the temporary file,
which is pretty interesting because it just says, I'm going to call it dot one, dot two,
dot three.
And in case those exist, we're just going to go through all of them until one doesn't.
Isn't this crazy?
So that's pretty fun.
And that uses shutil to copy the file over, which is pretty cool.
It uses yield to automatically return the inner file pointer.
So when you say with thing as whatever, even though you said safer dot open, it actually
yields out the underlying pointer file pointer that came from open.
And there's just a bunch of different layers of, Oh, that's interesting.
Oh, that's neat.
Yeah.
Anyway, I think this is really clever.
And it seems like a cool little library.
The reason I think it would probably be useful and not going to give you a big hit.
It's like, this is literally it.
You can see it's creating the temp file.
It writes to the temp file and then it uses OS dot rename the temp file to the actual thing.
So, you know, not a whole lot of magic going on, but really quite useful.
I think not a lot of code either.
Yeah.
Just.
Yeah.
Isn't that crazy?
Yeah.
That's pretty cool.
I love it.
Useful gives you that sort of durable error handling, almost like transactional files.
And yet super simple.
Very good.
Uses unit test as its test runner, though.
Oh, my God.
Well, all right.
I retract all of my endorsements of this thing.
All right.
What's the next one?
Okay.
I'm on the other tab.
So did I distract you?
Oh, yeah, you did.
And new article, new hat.
So code spell.
So I got this from Christian Klaus, that silly little project I play with on the side called
Cards.
I got a pull request against the project to add a pre-commit hook to run code spell.
And I had never heard of code spell.
So I was excited to have a new topic for the podcast.
Also, just it's as neat.
So code spell.
What it does is it fixes common misspellings in text files.
And specifically, it's designed primarily for checking misspelled words in source code.
But it can be used as other files as well.
When Christian applied this to the cards project, it noticed that in one of the documentation files I've got, one of the markdown files, I had spelled arguments with an extra U in the middle of it.
And one of the problems with spelling, I mean, it's embarrassing to do and distracting to have spelling errors in your code or your comments or anything.
It's hard to deal with because a lot of source code doesn't have, you can't just throw normal spell checkers at source code because it'll just, it'll warn you on your variable names and all sorts of stuff.
Right.
You can't drop it in grammarly.
That's not going to go well.
It's not going to work.
But so I'm really excited to try this and to start using it because if it can work for just about anything, it might be able to work for, you know, non-Python programs too as well.
Why not?
So yeah, it's pretty cool.
Yeah, all sorts of documentation.
That's cool.
It's an open source project.
The GitHub repo has the entire dictionary so you can scan through it.
And there's ways to ignore certain words if you're like, no, that's the correct spelling and it keeps doing stuff.
You can ignore it.
Nice.
Well, that's a really good one.
The most embarrassing misspelling I've ever done in code was I'd misspelled like a namespace or a class name or package name or something like that.
I can't remember quite where it was.
But it was on a project I had been working on for like a year and I misspelled it, but everything was autocomplete.
And so I don't care.
I'm like, da, da, da.
It is just like, okay, autocomplete.
I'm not even like ever typing that again.
Right.
Yeah.
I guess I just wasn't paying attention to like that.
I kind of suck at spelling.
That was like an extra bad case.
Some new person came on the team and said, dude, why is this misspelled all over the place?
And I'm like, oh, we got to fix it.
But it was like other applications depended on that library and they used the misspelling.
It was so bad because it was like it had become pervasive throughout like all these different things.
So like we may have to leave that misspelled.
I think we eventually fixed it.
But it was like it was quite a bit of work considering what it should have been.
That's funny.
That's awesome.
Well, at least you didn't have like both of the spellings be valid symbols in your program and mean completely different things.
That's true.
Yeah.
So one of the things that's awesome about this podcast is we'll say we'll find some random thing or maybe somebody will send it to us and we'll say, oh, did you even know that this was a thing?
I had never heard of this.
And then like five other people shoot us a message and say, yeah, and this variation or this other thing.
And that's cool.
But there's also X, Y and Z.
Right.
Isn't that awesome?
Yeah.
I learned so much by doing this.
Yes, I know.
We just got to throw something we vaguely know about and like people will correct us.
Yeah.
Awesome.
So, no, seriously, we talked about profilers and I talked about scaling, how it was really nice and fast and it did memory profiling and all that.
Well, friend of the show, Anthony Shaw said, hey, since you're on this kick for profilers, have you heard about Austin?
To me, Austin is either a guy's name or a town in Texas.
I hadn't heard about Austin.
Have you?
I got a neighbor named Austin.
Yeah.
I don't think this is the same thing.
So, this is like scaling is a frame stack sampler for CPython, meaning it doesn't have like this huge effect of once you run it on your code, it doesn't become 10 times slower as instrumenting.
You know, it just asks like, hey, what are you up to really quickly?
So, that's cool.
It's nice and fast.
It also is just pure C code.
There's no real dependencies like other than like the C runtime, which is in all the operating systems.
So, it looks at running Python code at intervals and then it dumps out whatever it finds, which is cool.
It has a really simple output, but as you will learn, it has all these interesting ways to visualize that output.
So, it's sort of base, it's atomic unit of output is a flame graph.
So, flame graphs are like stacked up sort of things that are colorful and they also have information.
So, like the color communicates information and the height.
So, it's kind of like a graph with like color bars type of thing and it has the parts of code they're running.
If you want to see what that is, just click on the link and it has it right there at the top.
And that's cool.
So, it puts that out, but you can build other tools to analyze that or you could even make like a little player application that replays the execution of your application in like slow motion.
Like replays that flame graph over time.
Oh, that's neat.
Isn't that cool?
Yeah.
So, now is where it gets really fun because there's a couple of user interfaces on top of this like simple output that can be interpreted.
So, the first one is called the TUI, the Terminal User Interface.
Do you see this animated in our little show notes?
And we'll be in there.
It's nice.
Yeah, it's really cool.
Yeah.
So, let me try to describe it.
Like imagine you've opened, I don't know, Emacs or something like that.
But the top part of it shows the process information, the CPU it's using, the memory it's using, how long it's been running.
And then a graph, an active like interactive flowing graph across the top of like the performance analysis.
And then it has something that's a little bit like top maybe, showing you like what it's currently running, how much time it's using.
Is this time being spent on a sub function call?
Like did I call a thing that called request that is talking to the network and that's why it's slow because we're waiting on the internet?
Or is it actually computationally my stuff running in Python or whatever, right?
So, what do you think?
That's cool, huh?
Yeah, that bottom part reminds me of the thing that you put the process explorer on Windows where you look at all your processes.
Yeah, a little bit.
Like task manager.
But it's actually for like your functions instead of other processes.
Yeah, yeah.
It's nice.
That's cool.
So, that's the TUI, which is going to be a popular one.
But you may also want to be on the web.
So, there's WebAustin, which is another example of making this for the web.
So, you basically can log into wherever you're running it, connect to it, and it has a D3 flame graph that's like animated of what your web app or whatever process you're watching on that remote system is up to.
So, it's kind of the same thing, but like more visual, more graphical.
Like the flame graph is there and whatnot.
So, that's pretty cool.
People can check that one out.
You can even pause it and whatnot.
Then finally, there's this other format called SpeedScope, which can be visualized in other tools.
And you can convert Austin output into the SpeedScope JSON format.
And there's a sample for that in the repo.
If you go look at that, you can load it into the SpeedScope visualizer type of things and have another way to view the data.
So, this is really nice because so many of these profilers are like, we collected all this information.
How would you like it as a CSV?
Or how would you like it as just like random columns in a terminal?
And this is so much like, I would not like it that way.
I really like the visualization because it's one thing to gather the information.
It's another to go, oh, I see.
Right there is actually where it's slow.
And if it's just a dump of a bunch of numbers, I mean, yeah, you can like sort it and whatnot.
And you can use cProfile with different sorting options and get it to mean stuff.
It is not the same.
It's like, aha, there's the picture.
I see.
It's red right there.
And it's really tall.
Let's go figure that out.
Yeah.
And the web one, the logo is awesome.
It's good.
It is really good.
Yeah.
It's like a 70s thing.
It reminds me of Austin Powers.
Yeah.
A little bit, right?
Yeah.
In a non-copyright infringing way.
Anyway, that's it.
If people are looking for a profiler, Austin looks pretty cool.
Check it out.
Definitely.
It seems like it's definitely one of the contenders.
Anthony for sending that in.
I want to talk about numbers.
Does this fit in the screen?
Oh, yeah.
You got your mathematician hat on now or your wizard hat.
I can't decide.
I got this from a man.
He writes two great stuff.
First name Mosh.
Is the last name Zadka?
Zadka?
Mosh, you got to contact me and find out.
Tell me how to pronounce your name.
But numbers in Python.
Really great article.
In Python, you don't really have to think about numbers too much.
They just sort of work.
Yeah.
But you do kind of need to think about them.
And this article is a really good, quick tutorial about the different things that you need to know.
Like integers, they turn into floats really easily.
Like any time there's a division, it'll turn into a float.
Right, which is unlike other languages, which are like truncating sort of things, right?
That basically take the floor of whatever the result would be.
Yeah.
In earlier Python versions, 2.7 like that.
Yeah.
Like truncated off.
Right.
If you want that old type, now you got to double divide, like the two slashes.
Yeah.
And I forget about the two slashes thing.
Yeah.
I never use the two slashes because that seems wrong.
Anyway, so the implications are weird though.
And the other thing, okay, so you got integers, they turn into floats if you divide them.
You got floats, which are things with decimal points in them.
They're not the only things with decimal points in them though.
One of the things you learn early on in programming, but some people are new to programming or numbers,
so it's a good thing to remember, is floats don't behave like floating point numbers in math.
Like the subtraction and addition are not inverses.
And addition is not associative always.
And you can't multiply and then divide and get the same number.
Those are weird things you should be aware of.
The normal thing that I mostly need to remember is don't try to compare floating point numbers with the double equals.
You have to use something like approximate or something.
Yeah.
That's the one that can really catch people out.
I mean, okay, so I thought I was going to get 14 and I got 13.9999999978.
Okay.
Well, it's computers.
We know that stuff's truncated, but it's really easy to go.
If X equal equals some number I'm looking for and that never ever happens.
Right.
It looks right and it is so wrong.
And I think just our training for so many years in theoretical mathematics means that it's hard to look at that and go, that's wrong.
Yeah.
Well, it's interesting that when you see it in numbers, you can, like, for instance, one of the examples is one plus two minus two minus one is zero.
Obviously.
Of course it is.
If it's floating point numbers, though.
So floats don't end up with zero.
You end up with a very small number, but it's not zero.
Okay.
So floats are weird.
Be careful.
Fractions.
So if you don't use floats, there's fractions.
Python has built in fractions.
I actually have never really used these.
It's neat.
They're there.
I've never used them either.
But yeah, there's like a class called fraction with a numerator and a denominator or takes another fraction or a floating point.
Yes.
Even takes a string.
How about that?
The warning in this article is they, fractions take a lot longer than you expect they would for algorithms.
So you can represent things as fractions.
It's cool that you can do that.
Be very careful with any sort of algorithm because it can explode in memory and size and time and stuff like that.
So probably use floating point.
That doesn't surprise me because when I have to do like fraction algorithms, in my mind, it takes a lot longer too.
Yeah.
The last one that he talks about, and it's something that some people don't realize right away, is that decimals are built in.
So there's a decimals library that it's probably not surprising.
One of the reasons it's in there is for financial transactions.
They're set up to be correct with precision and do the right thing.
And so I'm really glad it's there.
Otherwise, we'd have like competing decimal third-party libraries or something like that.
And we probably do.
But this one's built in.
I'm glad the article was written, though, because something weird about decimals that I didn't know about was there's a global state variable called context that holds the precision that's being used for decimal division and stuff.
It could be anywhere in your program that the precision gets changed.
So the recommendation in this article is to use a local context.
So you can do one of those blocks, context, what are those things called?
Context manager.
Context manager, yep.
You can use the context manager, local context, to set a local context precision for your arithmetic.
So that's good.
That seems like that should be the required way.
Because just setting it globally seems really, I don't know, it seems wrong.
Because, you know, think of the race condition there.
I was doing math, and then the precision got cut in half, and then it wasn't what I expected anymore.
Yeah.
Or, I don't know, maybe there should be a minimum precision.
This is interesting, though.
Like, I didn't realize that you could even change the precision of decimals.
So, like, in the docs it says, unlike hardware-based binary floating point numbers, the decimal module has a user-alterable precision defaulting to 28 places, which can be as large as needed for a given problem.
So, yeah, you can change it.
The example in the Python document on the docs show, just globally changing it halfway through a calculation, which seems like a bad, let's kick them down the stairs instead of teaching them to hold on to the handrailing.
But this is really cool, like, this local context, change it, you can set it really high.
That's cool.
I had no idea that you could actually change that to grow as you need it, which is cool.
Yeah, I guess you could still use the global context as long as you, maybe this isn't safe, but as long as you always remember to set it before you do decimal arithmetic.
It's safe as long as you're not doing threading.
Oh, yeah.
Okay.
Yeah, because what if somebody, some other thread has the same idea and changes it?
I think the idea is maybe, it seems to me like possibly it would be better if once set, it couldn't be set again.
Like, you could set it at the beginning of your program, but it couldn't be altered and altered and altered.
Yeah.
Like, right, something along those lines, like, okay, we set it, we're done, it's an exception if you try to set it again to something else and so on.
I mean, it probably is a convenience.
Yeah, this is the whole world I didn't even know about.
This is cool.
Yeah, I would probably set up some sort of, like, hook or something to make sure that you're only setting it one place if you're doing that.
Yeah.
I don't know.
Yeah, sounds good to me.
Cool.
Anyway, yeah, this is actually more interesting than I thought because, like, as usual, I've learned something, which is cool.
Last thing on this, we're going to link to the standard library documentation for fractions and decimals because you may not have heard of them.
And then a very old article that if you really care about floating point numbers, you should at least know this article exists.
Although I don't think I've actually gotten through the whole thing ever.
But it's what every computer scientist should know about floating point arithmetic.
That's a good article.
Yeah, cool.
All right.
Any extras for us today, Michael?
You know, not too much.
I don't have too much to share right now.
Nothing personal.
But I do want to say thank you to everyone who subscribed to the YouTube feed of this podcast because we're breaking every segment.
We've just covered six things.
We're breaking that into six different videos.
And you can see us on video, which is kind of cool.
A bunch of people are subscribing at pythonbytes.fm/YouTube.
You all can check that out.
And you will see that Brian has awesome hats for every segment.
Well, at least this episode.
This episode.
Which, yeah, you got to wait.
Yeah, for sure.
This episode.
So eventually, you'll get to see the hats.
Okay.
I'm glad we mentioned that.
I wanted to mention also that Python 3.9.0 alpha 6 is the last alpha release before we go into betas, I believe.
And it is available.
And it has the peg parser that we talked with, I think, last week about a little bit.
Yeah.
We was here and talked about that was really cool.
The work he's been doing there.
That's a big long-term upgrade, right?
That's something that got written in the original version of Python.
It was unchanged and obviously can be better, right?
Basically, the syntax was limited by the parser and how much it looked ahead and stuff.
And so this should open up the language for more complex concepts or make it easier to add concepts to it.
Yeah.
All right.
So I see we have some competing jokes here.
You want to go first?
Yeah.
I just put a call out on Twitter and said I need some more jokes.
And boy, I got a whole bunch of great ones back.
I'm going to pick one.
This one's from James Zabel.
If you put 1,000 monkeys at 1,000 computers, eventually one will write a Python program and the rest will write Perl.
That's right.
I think maybe like 950 of them will write Perl.
A couple of them are just going to be writing regular expressions like all on their own.
Yeah.
That's true.
All right.
I have one that's maybe in a similar vein here.
So, you know, like we talked about Austin.
It has all these different user interfaces and it's very user friendly.
Well, you could say that Unix is very user friendly as well.
It's just very particular about who its friends are.
Yeah.
I got friends like that.
Yeah.
I got that one from the Pyjoke package.
So pip install Pyjoke and you can have it too.
Yeah.
That's good.
Yeah.
Anyway.
Cool.
Thanks.
All right.
Fun as always.
Great to be here with you.
Bye.
Thank you for listening to Python Bytes.
Follow the show on Twitter at Python Bytes.
That's Python Bytes as in B-Y-T-E-S.
And get the full show notes at Python Bytes.fm.
If you have a news item you want featured, just visit Python Bytes.fm and send it our way.
We're always on the lookout for sharing something cool.
This is Brian Okken and on behalf of myself and Michael Kennedy,
thank you for listening and sharing this podcast with your friends and colleagues.