Python Bytes - #180 Transactional file IO with Python and safer
Episode Date: May 8, 2020Topics covered in this episode: Ubuntu 20.04 is out! Working with warnings in Python Safer file writer codespell Austin profiler Numbers in Python Extras Joke See the full show notes for this ep...isode on the website at pythonbytes.fm/180
Transcript
Discussion (0)
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 May Day.
I am Brian Ocken.
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 ago ubuntu 20.04 is out 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 like 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 18.04,
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 everywhere.
That's right.
It's time to hit all your your code with flint and auto f
string all the things so upgraded all of the servers for python bytes the servers are you
know 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 vader on talk python episode 215
so people really want to look in 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.
Read it 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 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 pies 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 digital ocean the
top you can go to digital ocean 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 yeah and actually we've already had the
kernel upgraded the 5.4 kernel upgraded to like a version. I just had to 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 pay attention to kernel upgrades and stuff?
Yeah, apparently, yeah.
They're not on a platform-as-a-service type of thing.
It's not a big deal.
It's pretty regular, like once a month or whatever.
I'm usually logged in to one of them every couple days doing something,
and it'll say, oh, either it's already already applied. It says you got to reboot it. 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 noticed 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.
So Reuven Lerner is a friend of the show and a great guy, teaches Python.
And he 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 what 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 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. 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. 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 or 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.
This is 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 um because python will deprecate things too and then you can have a head heads up that you
need to start fixing your code because and 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 digital 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 behave as internet gateways.
That's cool.
Yeah, it's like your own little baby 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.
Digital ocean is your trusted partner in the cloud.
Visit pythonbytes.fm slash digital ocean to get $100
credit for new users to build something awesome. Yeah, we love it. Like I just said, I'll 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 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 async io threaded stuff multi-processing 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 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 the beginner level that has no
try except blocks anywhere in the code
it's just like i don't know what you call 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 gonna do a try do a bunch
of stuff except handle the error right that's That's good. And maybe you're catching
different errors. Like maybe that's another level. I don't know what the make 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 with 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
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 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.open file name as file pointer. And then otherwise,
all your code is identical. Okay. 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 with block, the with 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 with block,
am I leaving because of 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.
Isn't that cool?
So if there's an exception in your with block,
it still closes up the file pointer and everything,
but your data is unchanged.
It's kind of like a transaction with an 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.
It's pretty small because it just uses shutil to replace the file.
It writes to the file just as you would write to the file.
And then at the very end, it goes, move this file to this destination and overwrite.
So it 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 and 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 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 because I want to talk actual 28 lines of code. Do you have that open? I did.
Click on that really quick because I want to talk about a couple of really interesting
patterns here. 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 it 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.open,
it actually yields out the underlying file pointer that came from open.
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.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.
Yeah, isn't that crazy?
Yeah, it'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?
I'm on the other tab. Did I distract you?
Yeah, you did. New article, new hat. Code spell.
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 Codespell. And I had never
heard of Codespell, so I was excited to have a new topic for the podcast. Also, just, this is neat.
So Codespell, 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 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.
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 non-Python programs too as well.
Why not?
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 auto-complete. And so I don't care. I'm like, dah, dah, dah. It is just like, okay, auto-complete.
I'm not even like ever typing that again. Right's just like, okay, autocompletion. I'm not even ever typing that again, right?
I guess I just wasn't paying attention to that.
I kind of suck at spelling.
That was an extra bad case.
Some new person came on the team and said,
dude, why is this misspelled all over the place?
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. I'm 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'd 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 this variation or this other thing. And that's cool.
But there's also X, Y, and Z, right? Isn't that awesome?
Yep. Yeah. Yep. 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. It'd be 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 go to the neighbor named Austin.
Yeah, I don't think this is the same thing.
So this is like scaling as a frame stack sampler for c python
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 versions do 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 a 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 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, interactive flowing graph
all across the top of the performance analysis.
And then it has something that's a little bit like top, maybe,
showing you 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 uh the thing that you put the process explorer on Windows, where you can look at all of the other processes. Yeah, a little
bit like task manager, but it's actually for like your functions instead of other processes. Yeah,
yeah. That's nice. That's cool. So that's the two E, which is going to be a popular one. But you
may also want to be on the web. So there's Web Austin, which is another example of making this
for the web. So you basically can log into 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 yeah more graphical like the flame
flame graph is there and whatnot so that's pretty 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 speed scope 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 please 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 there's just a dump of a bunch of numbers
i mean yeah you can like sort it and whatnot and it you can use c profile with different sorting
options and get it to mean stuff but it's 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 yeah
in a non-copyright infringing way anyway that's it if people are looking for a
profiler austin looks pretty cool uh check it out uh it seems like it 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 uh man
he writes two great stuff.
First name Mosh, last name 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.
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, yeah. Like truncated off. Right, in earlier Python versions, 2.7 like that? Yeah.
Truncated it off. Right. If you want that old time, now you've got to double divide
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. The other thing, okay, so
you've got integers, they turn into floats if you divide
them. You've got floats, which are things with decimal points in them. They're not the only things with decimal points in them though. 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 1 is 0, obviously.
Of course it is.
If it's floating point numbers, though.
So floats don't end up with 0.
You end up with a very small number, but it's not 0.
Okay, so floats are weird.
Be careful.
Fractions.
So if you don't want to 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 a class called fraction with a numerator and a denominator,
or it takes another fraction or a floating point.
Even takes a string.
How about that?
The warning in this article is 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 is floating
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
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 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 hand railing.
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 needed them, 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 long as you're maybe this isn't safe, but as long as you always remember to set it before you do decimal arithmetic.
It's safe 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 whole world.
I haven't.
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.
It 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 Python bites out of them slash YouTube.
Y'all can check that out and you will see that Brian has awesome hats for
every segment.
Well,
he's this episode least this episode this
episode which yeah you gotta 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 uh python 3.9.0 alpha 6
is the last alpha release before we go into betas i believe and uh it is available and it has the
peg parser that we talked with um i think last week about a little bit yeah 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 and 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 Abel.
If you put a thousand monkeys at a thousand 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 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.
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 PythonBytes.fm. If you have a news item you want featured,
just visit PythonBytes.fm and send it our way. We're always on the lookout for sharing something
cool. This is Brian Ocken, and on behalf of myself and Michael Kennedy, thank you for
listening and sharing this podcast with your friends and colleagues.