Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 350, recorded August 29th, 2023.
And I'm Michael Kennedy.
And I'm Brian Okken.
And this episode is brought to you by Sentry.
Make sure those errors don't go unnoticed and you get to them quickly with the right information.
Check them out at pythonbytes.fm/sentry.
We'll tell you more about them later.
And of course, connect with us over on Mastodon at mkennedy, at Brian Okken, at pythonbytes, all at fosstodon.org.
And if you want to be part of the live stream, part of the live audience, that's usually on Tuesdays, 11 a.m. Pacific time, as we are recording today.
So if you can drop by and be part of the show, we would love that.
If not, well, thanks for listening anyway.
Brian, let's kick this off.
Just a quick little article from Bob Beldermos to remind us to keep things simple.
And there's a lot of ways in Python where you can make elegant-looking code, but it also is easier to read.
And that's, I think, some of the emphasis.
So Bob from PyBytes, and they see a lot of, they've got all those challenges.
So I'm sure they see a lot of examples of not quite elegant code, but it does the trick.
So I think this is good advice from a good person.
So like, and there's just a whole bunch, there's just a handful of these here, but they're all really good things.
Like, for instance, using the keyword all.
I don't use it that much, but here's an example.
He's got a function where he wants to know if all things in a list are divisible by some number.
And there's like a function he wrote with just like a for loop that goes through the whole thing.
However, he rewrote it as a, what is that called?
It uses all, but it's comprehension, I believe.
So all numbers divided by divisor equals zero for divisor and divisors.
So it's kind of neat.
It actually might be a generator.
Is it a generator?
I think it might be.
But yeah, when it's passed as an argument, parentheses don't really tell you which it is, does it?
It doesn't.
Yeah, it's pretty cool to find that out for us.
Pretty cool to use that generator or whatever as an argument to a function.
That's pretty slick.
And it's pretty easy to read still, I think.
I still think maybe, well, with the function name, you kind of get what it's going at.
But if it was out of scope of a function, both of these methods would have used a, could use a comment here or there.
Dictionary lookups.
I love this part.
I use it all the time.
The dictionary has a get function.
So normally you reference a key in a dictionary with just brackets.
But if you want to make, have some default value, if it's not there, use get instead.
So you grab a key and then the second value is the value.
Anyway, this saves a lot of code because I do this all the time for dictionary lookups.
And then it goes through quite a few others.
Just it's a good, good list.
We've got list comprehensions.
Don't forget those.
The list comprehensions are wonderful.
We both love those.
Looking for unique values.
This one I had to look at for a while.
It was interesting.
If you're looking, I actually didn't understand the first one that well.
But making sure that all items in a set or items in a something are unique by taking the length and then doing a set of items.
And then like anyway, just lots of lots of fun tricks to shorten your code and make it a little more readable.
I love it.
There's all these non-obvious ways, you know, counter.
I know Bob is a big fan of the counter class, but yeah, that's a really slick way to.
What is he trying to do with this last one?
Counting things.
Yeah, counters.
Counters pretty cool.
Just to count things.
You've got a paragraph or like some text and you want to say which words appear and then how frequently do they appear.
You could split on space and, you know, throw away the punctuation.
Yeah.
And like just basically a couple of lines, right?
Sentence.split.
And that's it.
And you count that.
It's awesome.
It says, you know, this word appeared this many times and it even sorts it.
Yeah.
That's pretty cool.
Yeah.
And it's just like it did sentence.lower.split and then throw it into a counter.
Interesting.
Pretty cool.
Interesting indeed.
Also interesting is it turns out that is in fact a generator that comes out of that.
I did a little quick REPL action on it.
Okay.
For some real time follow up there.
Cool.
Yeah.
All right.
The first one I want to cover today comes from a foundational element of Scrapey.
So Scrapey is the project around extracting data from websites in a fast, cool way.
You've got Scrapey.org.
You've got Scrapey itself.
But the thing I want to highlight is Parcel.
You've probably heard of Beautiful Soup and Beautiful Soup has been around for a really long time.
and it's quite excellent.
Yeah.
But I was looking for something, you know, is there something kind of newer that's got some new paradigms just to try out basically.
And I ran across Parcel and it being the foundation of Scrapey kind of gives it some street cred.
So Parcel lets you extract data from XML and HTML documents.
So the fact that it's XML as well, because I was working with some RSS data for some things.
And you can do either CSS selectors, which are my favorite.
But sometimes you've got to get things that CSS doesn't really easily make it easy for you to get.
So you can use XPath as well.
It also works on JSON, I believe, even though the description doesn't say so.
Yeah.
JSON as well.
So the CSS and XPath is for HTML and XML and it use JMS path, JMS path expressions for JSON documents, which kind of lets you say, I've got some big structure.
So I want to navigate in kind of like you would with a CSS selector.
Like show me all the paragraphs and then get the images and get the title of the image out of every paragraph on the page, no matter how it's structured.
You can kind of do that with this thing for JSON as well, which is pretty awesome.
Yeah.
Instead of, you know, traversing it all over.
And if you want two problems, you can try to solve it with one with regular expressions.
Yeah.
I'll give you a quick example.
If you pull up the page, it says, okay, we're going to take some texts.
The text has a body, an H1, an unordered list, a list items in there.
Those list items are hyperlinks.
So the hyperlinks have URLs and they have text.
There's also some JSON in this thing.
So if you just create a new selector object, you can say H1::text.
And that is a CSS way to speak about the context, the content of that.
And that pulls just the value out of there.
So high parcel or hello parcel is the text inside H1.
So that simple little selector is a real simple example.
So maybe it doesn't totally win you over.
But you know, in a real true complicated HTML document, it would be quite awesome.
They also show how to do that with XPath.
I don't know XPath very well.
And then run a regular expression against it.
I could break that into pieces.
That's pretty intense.
I'm not necessarily doing it.
But you can do things like, for example, I want all the LIs that are only appearing in unordered lists, not the ordered lists ones.
So you can say UL greater than LI and the greater than means immediate child of not somewhere in the hierarchy.
So you just do that CSS selector.
And it gives you an iterable.
It gives you all the list elements that you can pull out the hyperlinks out of both of those by doing slash slash at href.
Right.
To grab that out of the thing that comes back.
And you can also do similar stuff for the XML that's in here.
So you can say, just go find me the thing that has the name A, no matter where it appears in the document, or get me all the items to the list and so on.
Pretty cool.
Again, really simple example, but quite a neat little tool.
I definitely need this.
I've got some HTML that I'm parsing that are, it's not well structured stuff.
It's like, you know, generated from some CMS thing.
And there's no identifiers anywhere.
There's hardly any classes.
It just is like purely generated div nightmares.
And yeah.
Yeah.
And it'll still be lucky if I can find what I'm looking for with something like this.
Yeah.
But it'll help, right?
Yeah.
That's pretty cool.
Yeah, give me.
I'll see if I can pull up one more example real quick.
Hold on.
Let it appear.
Must appear.
I just screenshot it.
Also in our notes here, I put the way to get an RSS feed out of a standard web page.
So how would you normally do that?
You would go get the HTML, then you go to the head section.
And in the head section, there's a bunch of links.
They mean different things.
One of them would have the rel type as what is that?
I can't remember.
It's like additional or something like that.
And the, no, that's the rel.
And then the rel type is something like RSS application plus RSS or, you know, whatever the
mime type is.
So you can just grab those things, just saying head greater than link.
Use a little X path to grab the attributes out of the selector or out of the result and find which
one of those.
And then you've got the URL, which is, you know, where the RSS feed is.
Like if you're looking, if you're writing like a blog engine and somebody puts in the domain, but not the
actual RSS entry, you could get that page, find the RSS entry automatically for them and go on with just a couple lines of code.
That's pretty cool.
Yeah.
Very neat.
Yeah.
All right.
What you got next for us?
Oh, wait, before, before we move on, Brian, before we move on, let me tell everyone about our sponsor.
So as I said at the beginning, century is sponsoring this episode and the next, so support the show.
It really, really helps if you go and if you're considering getting air monitoring or tracing for
your application, check out python by set of m slash century.
Yes.
You can Google them.
We know you can just Google them and sign up, but you use the code Python bytes, or just use the link
and click, what is it down here?
Try century for free.
Then it'll apply that code automatically, which will then let them know, Hey, it's a good idea to
sponsor the show.
So let me tell you about them.
So if you want to remove a little bit of stress from your life, if you're worried about errors on
your website or errors, your users are running into that you might not even know about, you know,
you might want to install something like century.
So if you're waiting for your users to send you an email saying, Hey, I'm running to this problem.
How many of them got frustrated?
What was their opinion of your app or your website or your API?
Probably not great.
How much better it would be if you had error or performance details immediately sent to you,
including things like the call stack, the values of the local variables in that call stack, the
active user who was logged in, let's say their email address all in some report.
And you're like, Oh, here's the problem.
Here's the data.
I got to pass to it to write a unit test to reproduce it.
So make sure it doesn't happen again.
And here's the email, the user who I email and tell them, sorry, we fixed it.
I know you didn't tell us, but we found out anyway, because we have century.
So with century, it's not only possible.
It's simple.
We use it on Python bytes.
I use it on talk Python.
We use it in the talk by the mobile apps.
There's a way to just plug it right into Flutter as well.
Nice.
So pretty, pretty awesome.
And once I did exactly that, we had some user on talk by the training.
They ran into a problem.
I got a notification.
I saw who it was.
I fixed it.
Sent him a message said, Hey, here's the problem.
It's fixed.
They said, I was about to write you.
That's weird, but thank you.
That's awesome.
That's really great.
You know, right?
Yeah, it's really cool.
So if you want to have that kind of superpower for your web apps, your APIs, mobile apps,
whatever, check out century.
So surprise and delight your users create your century account at pythonbytes.fm/century
and be sure to sign up with the code Python bytes, all one word.
It's good for two months of upgraded options for their century business plan,
which will give you 20 times as many monthly events as well as some other features.
So thank you to century for sponsoring our show.
Cool.
Yeah.
And Ryan now over to you.
Well, I want to talk about struck log.
I'm pretty sure we've covered it before.
So struck log is a pretty cool way to to do some logging in your Python, especially if you're
logging from multiple services or, you know, multiple threads.
And it's really great because you can add extra detail and it's got coloring and stuff.
Struck log has some pretty good documentation already, which I love.
And it's a beautiful tool.
However, I wanted to highlight a new article I saw and it really is pretty fun.
Wait, hold on.
Go back real quick.
Okay.
Is the icon logo of struck log, is that like Geordi from Star Trek, but a beaver?
I think so.
I'm not sure.
All right.
Okay.
And he's holding two brackets.
It's so good.
Or curly braces.
So, so the article I wanted to look at was a comprehensive guide to Python logging with struck log.
And one of the things I loved about it was just sort of the beginning example.
There's a, there's a beautiful picture of a whole bunch of, whole bunch of logged items.
But the, the, what I liked was just the starting one that just said, Hey, all you have to do is
do pip install struck log.
And then, and then if you want to just start trying it, it's just a better logger than you're used to.
So import struck log, do logger struck log, get logger.
And then you use it just like you normally would logger info.
And then you can, you can just, here's, here's example.
You can do debug info warning error, critical, all that sort of stuff.
This is a big article talking about the different ways you can set it up with,
you can set the default log logging level.
You can configure it.
You can set it up for different, have different loggers on different applications or different
services, different formatting.
You can have different renderers.
That's all awesome.
And I'm really glad that it walks through that.
But what I really, what I really like was just this basic tutorial of, Hey, just do this,
do the, the get logger and then just log stuff and you get this beautiful output.
Now, the color and the, the weight and alignment of all the output is, is really awesome there.
Yeah.
So often you like, okay, you want to do logging?
Well, okay.
So what you do is you set up the logger, then you register an output.
So let's create a standard out stream writer thing.
And then we can push that into the thing, into it.
And if you don't do that, then no output shows up.
You're like, what is going on here?
Why is this not working?
You know, it's, yeah, this is really nice.
This does, so it does show the beauty of struct log that you can get started really fast.
It has a lot of complexity and it, and it's really not that complicated.
And like I said, the, the documentation is awesome and configuring, configuring it and everything
is not that hard, but it does, it's a new tool.
So it's a, it's, it's great that it's an easy way to get on, on board with it, start using it,
start having these great logs.
And both it can be for going to output, but also you can log to files, of course.
And a great tool.
And I love this tutorial that starts super easy and then gets into the more complex.
So check it out.
Excellent.
What you got for us.
The last one of the main ones, this one comes to us from a TAS Bach and it's created by Hennick.
And I mentioned it before and it's stamina, but I didn't know too much about it.
There were some questions in the audience, like how does it relate to tenacity and other things?
Right?
So I thought, all right, this is a cool thing.
I'll, I'll focus a little bit more.
Yeah.
And it has direct struck log integration.
How's that for a segue, right?
Yeah.
Well, I think struck logs that Hennick thing too, maybe.
Yeah.
Perhaps it is.
It seems like it would be.
So with tenacity, the idea is you can put decorators and other things onto functions or
operations and say, if something goes wrong, try it again.
That's the tenaciousness of that package, right?
That like, yeah, errors will not stop me.
But as Hennick describes it, the tenacity is great, but unopinionated.
And you can work yourself into ways where you might be using it wrong or causing other
sorts of, you know, infinite loop type of issues.
Okay.
So the idea is that stamina is an opinionated wrapper around tenacity.
So it's not a replacement for, but a simplified API for tenacity with the goal of being as
ergonomic as possible and doing the right thing by default with minimizing the potential for doing
it wrong.
So that's pretty cool.
Basically, Hennick says, he used to copy and paste the way he was working with tenacity over and over.
And, you know, wouldn't it be cool to just make a package that kind of embedded those ways of working
with it?
For example, instead of retrying on an exception, retry only on a certain exception, you know, a certain type of exception.
Right.
I want to retry only this only on database connection errors, not if there's a foreign key constraint error,
because that's never going to go away.
Right.
That's always going to be a problem with the data, but maybe the database will come back online.
So let's retry that one.
There's exponential back off, which comes from tenacity as well.
But what about with jitter between the retries instead of just going, I'm going to go one second,
three seconds, five seconds.
Let's go one second, then three seconds ish, then five seconds ish and so on.
Limit the total number of retries, limit the total amount of time, but all at once.
Right.
So not just the number of retries, but the time and retries.
And this one is very relevant to me right now.
I've been thinking a lot about Python typing.
I'll talk more about that later.
But with type hints, you get things like my pie and PyCharm and other tools that say you're
using this function correctly or using it wrong.
And with the way the decorators work with stamina is it preserves type hint
information when you decorate a function that is type hinted.
Honestly, I don't know how to do that, but I'm really glad that it like decorating the
function with one of these retries doesn't wipe away its type information.
That's super cool.
It logs with struct log retries with basic metadata if they happen to be installed.
And you can this one you might like, Brian, you can easily deactivate it with a fixture or
something like that, or just globally for the whole test run so that you don't retry and
a thousand times while you're doing a unit test testing for an exception on purpose.
Yeah, that's great.
Yeah.
So super, super easy to work with.
Just basically put a decorator, right?
Stamina at stamina dot retry.
And in this case, you can say only on the HTTP x HTTP errors and only try it three times.
That's pretty cool.
That's pretty great.
Yeah.
So a lot more you can do.
It's async by default.
So you don't just decorate an async def function.
And it does that as well.
So very, very cool.
People should certainly check it out.
And you can also see in the example, he's doing reveal type, which I believe comes from
my pie and you can reveal type on the example here, which is a decorated thing.
And it shows you that what you get back is a coroutine of any, any and that ACP x response,
which is basically how it was set up to go, right?
Set up to work, right?
Input on an int and then output on that type of thing.
So I think it's a pretty cool library.
It's something I will probably start using.
I previously used tenacity, but you know, why not?
Yeah, looks pretty good.
Cool.
Indeed.
All right.
That's it for our main items, isn't it?
Yeah.
Extras.
Yeah.
What else have you gathered up?
I've got a few.
Do you want to run through?
We'll run through mine first.
Let's do it.
So I have a, so the pytest check, it's a little pytest plugin I've got.
I had this weird request and, and I guess I, I'm not sure how to deal with it.
I was curious.
I'd like to talk through it to see what, what the, the audience has to say.
So somebody said, Hey, is it possible to start making GitHub releases?
And I mean, I do, I do versions.
And so I was, wasn't sure what was going on here.
And then I, and then I, I thought maybe this is one of those people that have done a lot of
these requests and a lot of repos.
So I searched for this, this issue.
And sure enough, there is 157 identical issues on different repos.
So speaking of tenacity.
Yeah.
Um, so my first reaction was, I don't want to do that.
That's lame.
Um, because they're just pushing work on other people.
Um, but, but also maybe it's okay.
So the argument here is that like somebody can say watch releases and then get notified
if a new release happens and they don't, and you can't do that with tags or something.
I'm not sure.
Um, so, my, yeah, first reaction was, I don't want to deal with it.
However, I think there's, oh, I didn't don't have the tab up here, but I think there's
some, GitHub actions that can do this for me every day.
If I'm just doing it by pushing a tag up and if it could do it by, by itself, a few minutes
worth of work, I'd like to know what other people are dealing with, with that.
If they, if they've added GitHub releases to, to their project or not.
Uh, yeah, just curious.
So what's a good venue for them to let you know about that?
Oh yeah.
Um, probably, probably I'm, Fosset on, yeah, right.
Not gonna foster on, or, the show has a contact form.
You can email us.
So yeah, that would be good.
Um, okay.
Uh, so there's that, I threw it right across.
Oh, maybe this is for, funny things.
We'll save that for later.
Um, not yet.
Um, I just pushed up the fixtures chapter for the pytest course.
Um, and, and about the, the intro, the interest got a nice slide deck in it.
So check out the, the preview, that's, that's, for chapter three, when you're
thinking about the course, and I'm trying to describe, how pytest fixtures with work
with like graphics, not really graphics, but you know, slides and drawings and things like
that.
So those are my extras.
How about you?
I've got a couple things for us.
So first of all, there's a shiny new Python 312 to be had.
And that was as of yesterday, 312 RC one.
Neato.
Release can, yeah.
Release candidate.
It's important because it's like, we're really not changing it now.
This is bug fixes.
So if you've been thinking like, okay, there's, there's more features for f-strings,
or there's this crazy thing that Eric Snow pulled off called the per interpreter GIL.
That's pretty awesome.
Um, buffer protocol, things are accessible in Python and many other things, right?
If you were waiting around and think, these are all relevant to me, I want to try them out,
but I don't want to mess with stuff that might go away.
It might change my, I'm just going to wait.
Cause I'm not really going to use it until it comes out in October.
Well, it should be about time to start looking into it with a release candidate.
So that's why this is double noteworthy.
Yeah.
It's also a really good time if you haven't started to start, testing your package.
If you're, if you have packages, you support, to, to add 312 testing.
Exactly.
Cool.
Okay.
Then I got three conference ish things.
PyCon UK 2023 is going to be Friday, 22nd and September to the, the Monday.
Okay.
So that's pretty cool.
I'd love to go to PyCon UK, but it is quite far away.
Now I do love the UK.
So if you were closer and you get there, then that'd be a pretty excellent conference to go
check out.
I think.
Yeah.
Also in the general neighborhood, Eindhoven as a, PyData Eindhoven is going to be November
30th.
So check that out as well.
And the call for proposals is open.
Finally, this one's a little closer to home for us.
Um, this one is PyData Seattle.
Now, normally we wouldn't give a shout out to just a meetup because we can't just go to the huge,
long list.
Um, but Don reached out to me and they've got some pretty cool stuff.
So this is the language creators charity fundraiser for PyData.
Uh, and, the fundraiser goes to num focus and last mile education fund.
So good stuff there.
And the whole thing is let's scroll down a little for pictures here.
We've got Adele Goldberg who created small talk.
Guido van Rossum who created, you know, this thing called Python.
Anders Heilsberg who did turbo Pascal C# and typescripts as well as James Gosling from
Java.
So this is a live in-person event that people can check out.
So when is it, it is September 19th.
So 20 days away or whatever.
If you're around there, want to be part of that.
There's no online version this because they want it to be fundraiser for charity.
It's, it's all about trying to get people to show up in person and be part of it.
So cool.
Those are all my extras.
Nice.
Yeah.
How about some jokes?
Yeah.
Do you have one?
I don't know if I can check it.
I don't know if I can tell you about this.
This one, I don't believe it was sent into us.
I just ran across it somewhere.
How does a librarian access remote computers securely?
SSH.
It's terrible.
It's terrible, isn't it?
It's very bad.
Yeah.
It's very bad.
Okay.
I love it.
Anyway, that's, that's the one I got for us.
Oh, it's a library and access remote computers securely.
Well, I have a GitHub repo called the ChatGPT failures.
Um, and it's got, it's just got a big list of things that have gone bad.
Um, and so this is pretty cool.
Um, it looks like a new, new being failures.
Um, let's see.
Uh, that one about the journalists.
Who was the journalist on that one?
Uh, Bing gets madly in love with a journalist, tries to break up his marriage and really stalkerish
effect and then lies about that journalist in a chat with another user, keeps being inappropriate
and dark.
So I'm not sure.
Uh, but Kevin Roos.
Okay.
That's who it was.
Uh, anyway, so there's, there's, so those are bad user to ask me to do that.
I'm not a bad user.
I'm a good user.
I'm a good chat.
I'm a good chat bot.
Oh my gosh.
So yeah.
So yeah, some failures on ChatGPT.
So I'd love to see this kept updated.
It hasn't been updated for a while.
So, yeah, we need some new ones.
It's pretty funny.
It's crazy how this stuff goes a little bit sideways, isn't it?
It, it is.
And I'm, I'm still on, I still don't know if I need to care about it a lot or if it's
one of those, I don't know if it's one of those things like crypto that maybe will
go away.
Um, or it hasn't really, I know crypto hasn't gone away and there's so many wonderful uses
for, blockchain.
It's a blockchain.
Come on now.
Yeah.
Okay.
Uh, I do think it's interesting with the large language models when you ask it subjective stuff,
right.
It, it could just be weird about it.
Um, or you, it can make up things about like previous, case law.
Uh, you know, you got those lawyers who got in trouble for submitting a bunch of documents
and briefs created by ChatGPT that were false.
But at the, on the other hand, like you can ask it programming questions and it'll give you
pretty good answers.
Yeah.
Right.
Like I asked for it to solve a really complicated regex problem that we were talking about before.
And it's just like, boom, here you go.
And here's a couple of examples in Python.
Thank you.
And those, I don't mind too bad.
Cause you can test it.
Like if I run this, do the, the things I want out of the regex expression come out or no?
If no, then it's a bad chat bot.
If yes, it's a good chat bot.
Yeah.
So anyway, I, I do one of the things I just listened to recently was, Freakonomics
has started a series on, can, on AI.
And the first one is can AI take a joke?
Um, and it is, it is interesting, an interesting discussion.
One of the things that they talked about was, was the current like strike for,
the writers and, and actors, in Hollywood right now.
Right.
So, and I thought that one of the, I, I, I didn't know some of the details.
So hearing a few of the details around it are interesting of, of, like the initial
creation of thing.
Um, so often you can have an idea and then hire some people to write more stuff about
around it.
But, if you didn't come up with the original idea, you don't get as much money.
So if they just have AI come up with the original idea, they don't have to pay anybody the large
amount of money.
Um, oh, I see.
So kind of filling out the details of the joke.
Yeah.
Um, and then some experience around writing of using, some AI to do writing.
Uh, one of the commentaries was, you still have to do human work to come up with
the prompts to like get it, to do something.
Um, and then you have to validate it afterwards to make sure that what they said, what it came
up with was real.
And those are still kind of the humans have to do.
Um, that's one of the fears I have around people using AI to, to generate test cases,
because if they're generating, if AI is coming up their code and coming up with your tests,
there's no humans verifying that it actually is doing what you want it to do.
Um, at some point you need to have people there.
So,
Someone's got to be in the loop.
Yeah.
So anyway, we'll see.
Uh, it's, I'm definitely not a Luddite trying to, actually there's a discussion about Luddite
also in the, in there that, Luddite apparently, I didn't know this, that it isn't
people that there weren't people that were, against technology.
It was people that were against, craftsmen that were against the shoddy craftsmanship
of manufactured items.
Uh, that, the, there wasn't, there wasn't enough people actually making quality goods.
They were just, like factories building low quality goods.
Um, that's what they were opposed to.
And that's interesting.
Uh, analogy that is, anyway, way on a, on a tangent there.
So, but, excellent.
Anyway.
Um, thanks for being here as always.
Thank you to everyone who listened.
See you later.