WEBVTT

00:00:00.001 --> 00:00:04.380
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:00:04.380 --> 00:00:11.120
your earbuds. This is episode 124, recorded April 3rd, 2019. I'm Michael Kennedy. And I'm Brian

00:00:11.120 --> 00:00:15.020
Akin. And this episode is brought to you by DigitalOcean. Check them out at pythonbytes.fm

00:00:15.020 --> 00:00:20.220
slash DigitalOcean. Get $100 credit for new users. Tell you more about why that's awesome later.

00:00:20.220 --> 00:00:23.460
All right now, Brian, I feel like we're going to go to your happy place.

00:00:24.300 --> 00:00:32.820
Yes, I'm definitely one of the testing nerds that's around. And I'm excited about the pytest 4.4.0

00:00:32.820 --> 00:00:41.040
released. There's a lot of stuff in the 4.4 release. And that's pretty cool. There's a lot of actually

00:00:41.040 --> 00:00:45.840
really neat things. One of the things, I'm going to save the big one for last. But the one of the

00:00:45.840 --> 00:00:51.220
cool things is there's a test paths variable that you can put in your configuration, any file,

00:00:51.620 --> 00:00:57.600
it tells the pytest where to look for tests. And it kind of short circuits some of the

00:00:57.600 --> 00:01:00.280
searching everything under the current directory.

00:01:00.280 --> 00:01:02.960
Just what, like two subdirectories or something, but not everything?

00:01:02.960 --> 00:01:07.400
Yeah, like for instance, this is very common if you've got like a structure where you get tests

00:01:07.400 --> 00:01:12.780
in one directory, your source in another directory, and then maybe some documents or something.

00:01:12.780 --> 00:01:18.940
And it's a large project. If you just launch pytest from the top, it'll look at everything.

00:01:18.940 --> 00:01:22.000
And it really should just look in the test directory.

00:01:22.000 --> 00:01:23.480
Right, exactly. It makes sense.

00:01:23.480 --> 00:01:28.060
So that's pretty cool. It's been around for a while, but it's kind of hidden. Like it just

00:01:28.060 --> 00:01:33.760
worked that way. And what they've done now is they've added in the output, it tells you which

00:01:33.760 --> 00:01:37.860
tests paths have been set. So that's nice.

00:01:37.860 --> 00:01:38.580
Yeah, that's cool.

00:01:38.580 --> 00:01:42.340
And then there's a whole bunch of stuff that's relevant to especially to plugin writers.

00:01:42.860 --> 00:01:46.920
And a little bit for test writers. There's actually quite a few things. I encourage people

00:01:46.920 --> 00:01:52.220
if they're nerdy about pytest to check out the changed list. The thing that I'm super excited

00:01:52.220 --> 00:01:58.840
about is there were a couple of internal changes that made it so that there's a new plugin called

00:01:58.840 --> 00:02:01.840
the pytest Subtests that works.

00:02:01.840 --> 00:02:02.680
Oh, nice.

00:02:02.680 --> 00:02:11.060
So pytest has always been able to run unit test code. But one of the things that happened is if

00:02:11.060 --> 00:02:17.940
unit tests had subtests in them, and subtests are a way to have kind of multiple checks within a test,

00:02:17.940 --> 00:02:23.760
if you had those in there and one of them failed, it's supposed to keep going and check all of them.

00:02:24.140 --> 00:02:30.580
But pytest would stop at the first failure. Now it doesn't. Now it continues on with running all of them.

00:02:30.580 --> 00:02:35.320
That's cool. Like, so if I've got, say, a list of five things, and I want to loop over those and

00:02:35.320 --> 00:02:40.340
test each one of them without some kind of parameterized test or something, I just want to loop over them

00:02:40.340 --> 00:02:43.160
all and write one test and do that. Like, I would do that with a subtest.

00:02:43.160 --> 00:02:44.320
Yeah, or at least you can.

00:02:44.320 --> 00:02:44.500
Yeah.

00:02:44.500 --> 00:02:50.460
And it works pretty good. So it really was to the plugin and the changes were really to fix this

00:02:50.460 --> 00:02:55.700
little corner case of the unit test support. And so I'm really glad that they did that.

00:02:55.700 --> 00:03:01.760
But they also threw in a new fixture called subtests. So even if you're not using unit test,

00:03:01.760 --> 00:03:08.740
you can use this new fixture. And it has a subtest.test context manager that works just like

00:03:08.740 --> 00:03:12.200
the unit test version, but you can use it in pytest tests.

00:03:12.200 --> 00:03:12.940
Yeah, that's cool.

00:03:12.940 --> 00:03:13.500
That's neat.

00:03:13.500 --> 00:03:18.920
Another one that I think is nice is the async. So you have the async, you know, mark as async,

00:03:18.920 --> 00:03:26.300
decorator you can use. But previously, if you did that, but for some reason, like the right

00:03:26.300 --> 00:03:32.580
plugin to run the async, say like paytest-async.io or paytest.trio wasn't there, they would just not

00:03:32.580 --> 00:03:36.440
run, but they were still marked as passed. And now at least you get a warning and they're not run or

00:03:36.440 --> 00:03:37.380
something like this. That's cool.

00:03:37.380 --> 00:03:39.560
Yeah, that's a oops.

00:03:39.560 --> 00:03:44.040
That's one way to make your test pass. Like, let's just not install that async runner.

00:03:44.040 --> 00:03:44.520
We'll be cool.

00:03:44.700 --> 00:03:45.400
Yeah. Yeah.

00:03:45.400 --> 00:03:51.920
Well, keeping with the async theme, I want to roll right into requests. So I literally just

00:03:51.920 --> 00:03:58.420
hung up recording or stopped recording with Kenneth Reitz. We're doing an episode on Talk Python and

00:03:58.420 --> 00:04:03.580
we're talking to him about requests a little bit, but mostly other things. Anyway, this next item

00:04:03.580 --> 00:04:11.580
follows right onto that is request-async. So currently without this library or something like it,

00:04:11.580 --> 00:04:17.300
if I want to use async and await and I'm doing web requests like microservices or calling like a

00:04:17.300 --> 00:04:23.360
Stripe API or something, I either do it synchronously with requests or I can do it asynchronously, but I

00:04:23.360 --> 00:04:30.360
have to switch out my calling package. I have to use like aiohttp.client session or something totally

00:04:30.360 --> 00:04:36.180
different. Rewrite my code. There's a package called request-async, which is pretty cool. And it's

00:04:36.180 --> 00:04:42.580
actually a different thing you import, but if you import it as requests, then you can do await

00:04:42.580 --> 00:04:51.980
request.get, await request.post and all of that. So it seamlessly fits into your async and await methods.

00:04:51.980 --> 00:04:56.720
Maybe you're testing with that pytest thing I was talking about. And it's basically the same API,

00:04:56.720 --> 00:04:59.040
but now it's async friendly, which is cool.

00:04:59.040 --> 00:05:00.540
That's very neat. Yeah.

00:05:00.600 --> 00:05:04.580
And like I said, there's other stuff you could use. You could use aiohttp, which is nice,

00:05:04.580 --> 00:05:09.560
but it means you rewrite your stuff, right? And a lot of people depend on like changing DNS resolvers

00:05:09.560 --> 00:05:12.900
and all sorts of crazy stuff deep down inside a request. So this will let you do that.

00:05:12.900 --> 00:05:17.560
Theoretically, at least I haven't tried all the edge cases, but let you do that without rewriting

00:05:17.560 --> 00:05:21.600
your code, which I think is pretty cool. Now I did say, I was just talking to Kenneth and

00:05:21.600 --> 00:05:27.160
one of the things he said is they are working on native async and await support for requests.

00:05:27.160 --> 00:05:31.600
So that's pretty cool, which would make this unnecessary. So why do I bring it up? Well,

00:05:31.600 --> 00:05:35.260
he said it's probably like not done for a while. It's probably like a year away because they're

00:05:35.260 --> 00:05:40.600
doing like major rework inside of requests. And, you know, think how many libraries and people

00:05:40.600 --> 00:05:44.360
depend upon requests. So, and how hard that must make it to change at all. Right.

00:05:44.360 --> 00:05:49.960
Yeah. It needs to not break back backwards compatibility and it's not even just breaking it. It can't

00:05:49.960 --> 00:05:54.480
slow things down either. Yeah, exactly. So they're talking about making a new package called request

00:05:54.480 --> 00:06:01.000
three. So you import request three and it has a slightly different API, just barely. So anyway,

00:06:01.000 --> 00:06:05.540
here's an interim way to get async and await working with request. And another thing, there's a cool bit

00:06:05.540 --> 00:06:11.740
of testing going on here, Brian, I thought you might like, so I can mock out my endpoint. Like let's

00:06:11.740 --> 00:06:17.140
suppose I'm trying to call an API or something and I don't really want it to go to the real server.

00:06:17.140 --> 00:06:21.600
I want to give it a test one. I can create a flask app or court or starlet or whatever

00:06:21.600 --> 00:06:28.220
and create a mock like connection pool or something to that effect and give it my real website

00:06:28.220 --> 00:06:32.560
implemented in Python. And that's the mock behavior of the, this thing.

00:06:32.560 --> 00:06:35.620
Okay. Well, that's neat. Is there more information about that somewhere?

00:06:35.660 --> 00:06:39.300
Sure. It's covered in the GitHub repo that I linked to. And if you go to the bottom down

00:06:39.300 --> 00:06:44.620
there, it talks about it. I don't totally know what's going on exactly. But for example, like,

00:06:44.620 --> 00:06:49.460
you know, you want to call, I don't know, your API and you could have like a little local one running

00:06:49.460 --> 00:06:53.720
on SQL, SQLite or something. And you could like literally give it the app. It won't even go to

00:06:53.720 --> 00:06:57.780
the network. It'll just like directly interact with the app as if it was the web server.

00:06:57.940 --> 00:06:58.900
Oh, that's really cool.

00:06:58.900 --> 00:07:01.640
Yeah. It's pretty wild. So anyway, this is...

00:07:01.640 --> 00:07:02.000
I'll play with that.

00:07:02.000 --> 00:07:05.120
Yeah. Yeah. It's a pretty cool thing to be playing with. And it has some other cool

00:07:05.120 --> 00:07:07.720
async testing support. So it's got a cool testing angle as well.

00:07:07.720 --> 00:07:08.280
Nice. Cool.

00:07:08.280 --> 00:07:10.160
Speaking of services, what do you got next?

00:07:10.260 --> 00:07:16.140
I did notice that there was an article in the register about a bunch of, I don't know how a

00:07:16.140 --> 00:07:18.860
bunch, but some layoffs atnpm.

00:07:18.860 --> 00:07:24.740
Right. npm is the commercial equivalent of pip, sort of. And PyPA, Python Package Authority,

00:07:24.740 --> 00:07:26.180
like mushed into one, right?

00:07:26.180 --> 00:07:31.880
Yeah. I didn't know that it was a for-profit like company, but apparently it is.

00:07:31.880 --> 00:07:34.340
Yeah. That's interesting all by itself right there, isn't it?

00:07:34.340 --> 00:07:40.120
Yeah. So Dustin Ingram wrote an article talking about, and Dustin is one of the people that

00:07:40.120 --> 00:07:46.660
works with PyPI and the Packaging Authority. And he wrote an article called PyPI as a Service.

00:07:46.660 --> 00:07:55.300
And essentially there's a couple of interesting comparisons between npm and PyPI. Firstly,

00:07:55.300 --> 00:08:03.860
NPM has been around for longer, I guess, since 2014. PyPI in 2002. Oh no, we're older.

00:08:03.860 --> 00:08:11.640
So PyPI is older. Math is easy. Anyway, they have like $10 million in funding. And whereas

00:08:11.640 --> 00:08:19.120
in 60, around 60 people working there and the PyPI has like less than half a million in grants.

00:08:19.120 --> 00:08:24.900
And then just like, there's only half of a fraction of a single employee and then some volunteers.

00:08:24.900 --> 00:08:32.160
So there's a lot less people running PyPI and a lot less money. But what if they changed it?

00:08:32.660 --> 00:08:37.820
Apparently they've had a lot of people ask for an as a service version. So they could have a,

00:08:37.820 --> 00:08:43.060
like a private thing. So you could have your, you could use something like PyPI, but with your own

00:08:43.060 --> 00:08:48.380
stuff that's internal or whatever. And generally just talked about some of the problems with that.

00:08:48.380 --> 00:08:54.760
One of the problems is it might jeopardize the nonprofit aspect of the Python Software Foundation.

00:08:54.760 --> 00:09:00.260
That would be bad. Also, there's a whole bunch of people that, companies that donate services and

00:09:00.260 --> 00:09:05.040
infrastructure to make PyPI run at the tune of about a million dollars a year.

00:09:05.420 --> 00:09:11.460
And I don't know if, and he mentions that they might not be thrilled about donating that service

00:09:11.460 --> 00:09:13.060
to a for-profit company.

00:09:13.060 --> 00:09:13.780
I'm sure they wouldn't.

00:09:13.780 --> 00:09:19.900
I agree. There's also some of the ecosystem. There's, there's other options out there. However,

00:09:19.900 --> 00:09:24.360
I've kind of looked into these and I'm not really thrilled with the other options available. So

00:09:24.360 --> 00:09:29.740
I actually think there's room for somebody else to create something like PyPI for private

00:09:29.740 --> 00:09:33.780
use that might as a service that might be an opportunity for somebody.

00:09:33.780 --> 00:09:39.400
Yeah, for sure. You know, one of them that comes to mind is pydist.com. That's in beta right now,

00:09:39.400 --> 00:09:44.180
but it's basically that. It's basically the service that people are asking for. Honestly,

00:09:44.180 --> 00:09:49.880
I totally see the problem here, right? We've got this careful balance of this actually really expensive

00:09:49.880 --> 00:09:55.720
thing to run, PyPI, especially the traffic and the website and whatnot. And then we've got these

00:09:55.720 --> 00:10:01.360
donations taking care of that. There probably is a business model to be had here, but there's going

00:10:01.360 --> 00:10:08.940
to be like a wicked dip to zero, near zero. And it has to, somehow you have to be able to climb back

00:10:08.940 --> 00:10:13.080
high enough to cover just the expenses, right? Like that's pretty risky to do that.

00:10:13.080 --> 00:10:17.280
Right. And also, what do you do with the people that are now volunteering? Do you start paying them?

00:10:17.280 --> 00:10:21.540
What if they only volunteer for a couple hours a week or a couple hours a month? Do you pay them for that?

00:10:21.720 --> 00:10:28.780
Yeah. And then also, they support some of these alternate services right now, PyPI does. And if they

00:10:28.780 --> 00:10:35.760
had an incentive to not support the other services and only support their own profit, that's not good. So anyway,

00:10:35.760 --> 00:10:37.840
it's an interesting topic.

00:10:37.840 --> 00:10:42.400
I honestly think that there's actually a huge potential. I've talked to people in the community

00:10:42.400 --> 00:10:47.440
about this, but I don't know that I've talked about on the podcast before around pypi.org.

00:10:48.180 --> 00:10:55.560
If you look at how much traffic is there, there's a huge opportunity for non-invasive ethical ads and

00:10:55.560 --> 00:11:01.140
other types of promoted stuff to be put on there. And I'm sure they could do more than a million dollars

00:11:01.140 --> 00:11:05.660
with the amount of traffic they have, but there would be that bad dip and they might not make it through

00:11:05.660 --> 00:11:11.000
and so on. But I certainly see this as totally possible that it could go that way. And it may be,

00:11:11.040 --> 00:11:16.100
you know, given that they're basically saying, hey, we need to receive a donation of $40,000,

00:11:16.100 --> 00:11:22.360
$45,000 a month of bandwidth. And if we don't, we're done. Right? That's a really scary situation

00:11:22.360 --> 00:11:27.440
to be in as well. They're dependent just on one company. So I don't know. It's super interesting.

00:11:27.440 --> 00:11:35.380
The layoffs at NPM, that doesn't make me sound, it makes me really want to encourage PyPI to go that way.

00:11:35.380 --> 00:11:41.260
Right. It was interesting at the end, the conclusion wasn't that it's never going to happen. It's just

00:11:41.260 --> 00:11:47.560
right now, it looks like it's not worth it. It would be kind of a pain and it might backfire. And

00:11:47.560 --> 00:11:51.480
so right now they're not looking into it, but it's not a never thing.

00:11:51.480 --> 00:11:55.100
That makes sense. All right. Before we get on to the next one, let me just tell you all about

00:11:55.100 --> 00:12:00.440
some cool features at DigitalOcean. Something they just announced is the DigitalOcean Marketplace.

00:12:00.440 --> 00:12:05.420
So it's like one click apps and server configuration for all sorts of tools and whatnot.

00:12:05.420 --> 00:12:11.060
So maybe you want a discourse server, a GitLab enterprise server, a MongoDB server, or even

00:12:11.060 --> 00:12:15.740
Django. You can go up to there, create an account, go into the marketplace and just click the button

00:12:15.740 --> 00:12:21.360
and boom, you have an infrastructure all set up, pre-configured to run whatever app it is that

00:12:21.360 --> 00:12:25.080
you want there. So there's a bunch there. And I think you can even create more and add them

00:12:25.080 --> 00:12:29.460
if you want your project in there. So check them out at pythonbytes.fm/DigitalOcean.

00:12:29.660 --> 00:12:35.100
Get $100 free credit for new users and definitely get a play with that marketplace. It's quite cool.

00:12:35.100 --> 00:12:41.420
Brian, if I was looking to run, say, some data science Python in the cloud, and I maybe wanted

00:12:41.420 --> 00:12:45.500
to do that without paying any money, maybe I was a college professor and I wouldn't have

00:12:45.500 --> 00:12:49.760
my students do it or even high school, or I just didn't want to pay money or whatever.

00:12:49.760 --> 00:12:54.660
There's a bunch of these services now that'll run basically Jupyter in the cloud, right?

00:12:54.660 --> 00:12:55.300
Okay.

00:12:55.400 --> 00:13:00.400
So there's a couple of big ones. We've like Azure and we have Google, but there's some smaller ones

00:13:00.400 --> 00:13:06.360
as well. And a friend of ours, Kevin Markham, put together a cool article called six easy ways to run

00:13:06.360 --> 00:13:11.160
your Jupyter notebook in the cloud. So basically he went through and compared six different services,

00:13:11.160 --> 00:13:15.260
assuming they all have, you know, they got into this list. If they had all the characteristics

00:13:15.260 --> 00:13:19.720
in that they don't require you to install anything on a machine, they're either completely free or they

00:13:19.720 --> 00:13:26.080
have a completely free plan. They give you access to something like a Jupyter notebook environment.

00:13:26.080 --> 00:13:34.420
You can import and export real Jupyter notebooks through the IPYNB format, and they support Python

00:13:34.420 --> 00:13:39.740
language, maybe others as well. Out of all the ones he looked through, there's six that were decent that

00:13:39.740 --> 00:13:45.560
matched those criteria. So we have binder. Maybe you've gone to GitHub and you've seen like a GitHub repo

00:13:45.560 --> 00:13:52.560
that has some IPython notebooks in it and a little binder, like a run in binder button. So if you click

00:13:52.560 --> 00:13:58.480
that, you can basically use the binder service and run any Jupyter notebook that lives in a public GitHub

00:13:58.480 --> 00:14:03.000
repo on binder. So you just click a button and say, run this repo. That's kind of cool, right?

00:14:03.000 --> 00:14:03.700
Yeah, very cool.

00:14:03.700 --> 00:14:07.540
So that's nice. What I like about Kevin's article is he goes through and says, these are the pros,

00:14:07.540 --> 00:14:12.300
these are the cons. So like pros, obviously this is free and easy. If you already work on GitHub,

00:14:12.300 --> 00:14:18.420
it's just right there. If you don't, or what you have is a private repo, then binder is not such a

00:14:18.420 --> 00:14:23.460
big help. Another thing that's big in data science is Kaggle, right? So they have these Kaggle competitions,

00:14:23.460 --> 00:14:28.120
which are like, here's a bunch of data, try to solve a problem by, you know, getting the data to tell you

00:14:28.120 --> 00:14:32.580
or training a neural network or something like that. So Kaggle is known for that. But they also have this

00:14:32.580 --> 00:14:38.260
thing called kernels, like a free service called kernel. So Kaggle kernels. And these are kind of like

00:14:38.260 --> 00:14:41.440
Jupyter Notebooks, like super simplified ones. So you can run your stuff there. That's cool.

00:14:41.440 --> 00:14:47.500
Maybe one of the bigger ones is Google Colaboratory or Google Colab. And long as you have a Google account,

00:14:47.500 --> 00:14:53.420
it's like Google Docs, but for Jupyter Notebooks, you just log in, go. What I really like about this one is

00:14:53.420 --> 00:14:58.340
it's like Google Docs in that like you and I could be working on a problem. And we could just both be typing

00:14:58.340 --> 00:15:02.840
at the same time and working right alongside each other. So the Collaboratory bit is like super big there.

00:15:02.920 --> 00:15:03.500
Oh, that's nice.

00:15:03.500 --> 00:15:10.100
So that's pretty good. And then also you can run your code regularly on a server through Google

00:15:10.100 --> 00:15:18.800
Colab, but you can also run it on a GPU or a TPU, TensorFlow unit, processing unit, which is pretty

00:15:18.800 --> 00:15:23.300
awesome for something. I don't know if you have to pay for the GPU option, but still pretty cool.

00:15:23.300 --> 00:15:24.000
Yeah.

00:15:24.000 --> 00:15:28.800
Because a lot of people don't have, certainly don't have TensorFlow chips laying around probably.

00:15:28.800 --> 00:15:35.520
Maybe comparable to the Google one is the Azure Notebooks. So, you know, this is a big part of

00:15:35.520 --> 00:15:41.400
what Python and Microsoft are doing. You know, what Python is sort of showing up in, in the Microsoft

00:15:41.400 --> 00:15:47.240
space is over on Azure and Azure Notebooks. So they've got something that's more of like a project,

00:15:47.240 --> 00:15:52.160
right? It's not just a notebook, but it's like multiple notebooks, markdown files, data sets. So

00:15:52.160 --> 00:15:55.980
you kind of create these like project folder type things that you can run on Azure Notebooks. And

00:15:55.980 --> 00:16:00.460
that's cool. Also free. All of them are free. There's something I had not heard of cocalc for

00:16:00.460 --> 00:16:06.920
collaborative calculation. Also super collaboratory, like the Google Colaboratory one. Yeah, it's

00:16:06.920 --> 00:16:11.380
pretty cool. It lets you do all sorts of stuff like Jupyter notebooks, but also Sage worksheets

00:16:11.380 --> 00:16:16.520
and other things, which is good. And finally from JetBrains, we have data lore and it's not exactly

00:16:16.520 --> 00:16:21.420
Jupyter notebooks, but it's like a re-imagining of a Jupyter notebook, which is cool, but you can

00:16:21.420 --> 00:16:25.800
import and export Jupyter notebooks from it. So that's pretty cool. Like all the features and

00:16:25.800 --> 00:16:32.280
auto-complete and cool stuff that you get in PyCharm, but like in a notebook, Jupyter-like notebook is sort of

00:16:32.280 --> 00:16:37.100
data lore. Also real-time collaboration there. So those are all, yeah, those are all pretty cool. So if people

00:16:37.100 --> 00:16:41.760
are out there thinking like, Hey, I want to do some Jupyter in the cloud, maybe for a course or for

00:16:41.760 --> 00:16:46.340
collaboration or something, these are all good options. Yeah. Very cool. Yeah. Nice article, Kevin. And

00:16:46.340 --> 00:16:49.960
hopefully it helps some folks out there. Speaking of Jupyter, what do you got next?

00:16:49.960 --> 00:16:55.420
Yeah. Did you have this down and I just didn't see it beforehand or did we just coincidence?

00:16:55.420 --> 00:16:56.340
Just a coincidence.

00:16:56.340 --> 00:17:03.980
Okay. So my next item is Jupyter notebook tutorials. So let's say you have some people you're trying to

00:17:03.980 --> 00:17:09.640
collaborate or not. And you have some people that aren't quite familiar with Jupyter notebooks and you

00:17:09.640 --> 00:17:15.320
want to get them up to speed really fast. I'm actually in this situation right now, not for me,

00:17:15.320 --> 00:17:21.100
but with some people I'm trying to ramp up. And I found there's a ton of tutorials about Jupyter

00:17:21.100 --> 00:17:26.680
notebooks, of course, out there, but I really liked, there's two tutorials from a data quest.

00:17:26.680 --> 00:17:33.580
The first is Jupyter notebook for beginners, a tutorial. And the second is tutorial advanced

00:17:33.580 --> 00:17:38.700
Jupyter notebooks. And it's by the same author, which I should have written down, but I didn't.

00:17:38.940 --> 00:17:45.740
It starts out incredibly gentle, but it's also useful and concise and quick. You can get through

00:17:45.740 --> 00:17:51.460
quite a bit right away. And so it even starts with like, if you want to install Jupyter on your

00:17:51.460 --> 00:17:56.960
computer, how to install it, how to get started up. You don't even, if you aren't even familiar with how

00:17:56.960 --> 00:18:03.680
these work, how to get going, a little bit of a discussion about the file type, the IPYNB,

00:18:04.060 --> 00:18:08.100
and then a run through of the interface and how, how it works to work with a notebook.

00:18:08.100 --> 00:18:14.040
And then even into data. So like loading data and some important things like plotting data right

00:18:14.040 --> 00:18:20.460
off the bat, and then even how to share and then using save and checkpoint frequently to make sure

00:18:20.460 --> 00:18:27.000
that you save parts of your notebook. It's like this saving often is something we take for granted with

00:18:27.000 --> 00:18:31.380
an editor, but it's kind of nice to have this within a Jupyter notebooks also.

00:18:31.380 --> 00:18:32.040
Yeah, for sure.

00:18:32.040 --> 00:18:37.320
And I kind of like that he says, he stops the beginning one. It's long enough to get people

00:18:37.320 --> 00:18:42.180
started right at there, but then the advanced one, once people play with it a little bit,

00:18:42.180 --> 00:18:48.460
getting into some advanced things, which like the magics, keywords, debugging,

00:18:48.460 --> 00:18:55.120
shell commands, logging, using Seaborn, do using macros and all sorts of stuff in the advanced

00:18:55.120 --> 00:18:59.340
one, which are not, it's nice, but it's not, they're not too long. You could probably take an

00:18:59.340 --> 00:19:02.860
hour or so and go through it and learn what you need and skip what you don't need yet.

00:19:02.860 --> 00:19:03.400
Yeah, that's cool.

00:19:03.400 --> 00:19:09.920
I've also been playing with using a PyCharm to edit iPython notebooks. It works really good.

00:19:09.920 --> 00:19:15.920
I would recommend if people are debugging notebooks, maybe not use a write in Jupyter. I would probably

00:19:15.920 --> 00:19:18.800
use PyCharm for debugging. Yeah. PyCharm is pretty sweet for debugging.

00:19:18.800 --> 00:19:23.040
Anyway, so that's what I got. Yeah, it's nice. I think those definitely go well together. So

00:19:23.040 --> 00:19:27.280
people can check out those articles and then try them online. They don't even have to install anything.

00:19:27.280 --> 00:19:32.200
All right. Final one, Brian comes from friend of the show, Trey Hunter, and, it's called

00:19:32.200 --> 00:19:38.120
unique sentinel values. Identity checks and when to use object instead of none. And I think this is

00:19:38.120 --> 00:19:43.060
just a really nice reminder. Maybe something a lot of folks don't know, or haven't really thought

00:19:43.060 --> 00:19:48.300
about often we have to clear a variable and it may or may not have a value, right? Think of like

00:19:48.300 --> 00:19:53.780
computing the minimum of something. So you're gonna, the algorithm is you have the minimum value and you've

00:19:53.780 --> 00:19:58.020
got to set that to something and then you're gonna loop through all the items and you're gonna set it to the

00:19:58.020 --> 00:20:03.060
lowest. But how do you kind of initialize that, right? Do you set it to none? Do you set it to maybe negative one?

00:20:03.060 --> 00:20:08.180
But well, what if the values could be negative? Like what, what is that value, right? So often none becomes this thing

00:20:08.180 --> 00:20:15.760
that is the, it's not yet set value, but if none is a valid value, or maybe in this minimum example,

00:20:15.760 --> 00:20:20.520
like none could actually be a value that was passed to you in the list that you're trying to find the

00:20:20.520 --> 00:20:25.000
minimum of, but you need to treat it differently than actually the not having, you know, like it gets

00:20:25.000 --> 00:20:30.400
really weird, right? Yeah. So Trey makes a case for this, for something different in this article.

00:20:30.560 --> 00:20:35.880
I really like this. It's like, instead of sending a value to none, you can set it to object,

00:20:35.880 --> 00:20:42.680
parenthesis, parenthesis, and that allocates an object, much like none is an object, ironically,

00:20:42.680 --> 00:20:48.260
singleton, and things like that. But object is going to be allocated on a heap and we'll never,

00:20:48.260 --> 00:20:53.500
no one will ever pass that thing to you, right? There's no other use case for allocating an object,

00:20:53.500 --> 00:20:58.080
object, right? You always have something derived from object, right? I don't know, a string,

00:20:58.080 --> 00:21:03.760
a number, a customer, but not object itself, like the base class. So just allocating one of those is

00:21:03.760 --> 00:21:09.760
like the perfect sentinel value. And there's all kinds of examples where he goes through default

00:21:09.760 --> 00:21:15.300
values for function, like default parameters for functions, how you deal with that, how do you deal

00:21:15.300 --> 00:21:20.280
with like this minimum example, what is the first value before you've looked at the list. And so you

00:21:20.280 --> 00:21:25.300
end up with really nice checks, like that set minimum equals to object. And then if minimum is not initial,

00:21:25.520 --> 00:21:30.940
right, or is not this, you know, you set the initial to like this new object, right, then you go work

00:21:30.940 --> 00:21:36.640
with it. So super simple adaptation that solves a certain class of bugs and makes it really nice.

00:21:36.640 --> 00:21:37.340
That's interesting.

00:21:37.340 --> 00:21:42.020
Yeah, it's super simple, but it's like, it's kind of a good reminder. And there's the example,

00:21:42.020 --> 00:21:47.480
he re-implements the min function that's a built-in, but in Python, and goes through all the cases to

00:21:47.480 --> 00:21:51.200
make it work and shows how this pattern is much better than using none.

00:21:51.200 --> 00:21:55.340
I'll have to hit up Trey and ask him how to deal with that with type hints.

00:21:55.340 --> 00:21:55.640
Yeah.

00:21:55.640 --> 00:21:56.780
Because I'm used to...

00:21:56.780 --> 00:22:00.340
Oh, yeah, I know, I know. You can't just say optional. I guess you got to do like union of

00:22:00.340 --> 00:22:02.100
object, but that's also not a good answer.

00:22:02.100 --> 00:22:03.560
Because that would be everything.

00:22:03.560 --> 00:22:05.060
Yeah.

00:22:05.060 --> 00:22:09.440
Yeah, right. Yeah, it's not so good.

00:22:09.440 --> 00:22:11.920
Anyway, interesting. But it's a cool idea.

00:22:11.920 --> 00:22:15.720
Yeah, it's a great idea. It is a little bizarre with the, I don't know, with the type hints,

00:22:15.720 --> 00:22:16.660
you're right, but that's okay.

00:22:16.660 --> 00:22:21.280
I think you can get around it or just put like a, you know, ignore this one line type

00:22:21.280 --> 00:22:21.580
of thing.

00:22:21.580 --> 00:22:25.880
Yeah, well, I mean, and it only really will come into place if it's part of your interface

00:22:25.880 --> 00:22:26.480
to something.

00:22:26.480 --> 00:22:31.420
I mean, you'd probably do have to be careful with like mypy and mypyc and those tools,

00:22:31.420 --> 00:22:36.260
so they'll probably freak out if you don't take it into account. So, but yeah, I love the

00:22:36.260 --> 00:22:40.320
pattern in general, how it fits with type hints. That's like a different, different aside.

00:22:40.320 --> 00:22:41.400
Yeah, sorry, Trey.

00:22:41.400 --> 00:22:43.880
Yeah, Trey, there's your follow-up article, man.

00:22:45.040 --> 00:22:49.860
Brian, that's it for our official six topics as usual. You got anything extra you want

00:22:49.860 --> 00:22:50.380
to share with anyone?

00:22:50.380 --> 00:22:55.380
I do. I forgot to write it down, but you reminded me because you're talking about Sentinel values

00:22:55.380 --> 00:22:58.940
and Sentinels were part of the Matrix, right?

00:22:58.940 --> 00:23:04.040
Oh yeah, they were scary. Those are the big metal things that went through like the underground

00:23:04.040 --> 00:23:07.800
tubes and they would like grab onto the spaceship with the good guys in it. Yeah.

00:23:07.800 --> 00:23:12.260
Yeah, yeah. But there's something that's not scary is the cool computer screens that would

00:23:12.260 --> 00:23:14.280
like go downwards, right? Right.

00:23:14.280 --> 00:23:19.560
So one of the things I found, which is, I brought it up because I brought up pytest earlier,

00:23:19.560 --> 00:23:28.320
was a plugin called pytest-neo. And it runs all your pytest, like normally if you just run pytest by

00:23:28.320 --> 00:23:33.520
default, it'll print out like the test file name and then a whole bunch of dots and the dots mean

00:23:33.520 --> 00:23:40.560
everything passed or like an F for fail. The pytest Neo plugin, if you have that installed, that happens,

00:23:40.560 --> 00:23:46.980
but it goes downwards and looks like the screen, like a Matrix screen, but actually it looks cool.

00:23:46.980 --> 00:23:51.320
But it's actually informative. It has all the same information, just in the wrong, a different direction.

00:23:51.320 --> 00:23:54.800
Whoa. I need to learn unit testing. Chunk. Yeah, that's awesome. I love it.

00:23:54.800 --> 00:23:57.800
Brings me back to the 90s. That's cool. Very, very cool.

00:23:58.100 --> 00:23:58.480
How about you?

00:23:58.480 --> 00:24:04.180
I've got a couple of things. Let's start with this one. So I recently released a free course. So

00:24:04.180 --> 00:24:08.660
people can check that out over at training.talkpython.fm or just click the link. I think we've talked about

00:24:08.660 --> 00:24:12.780
Kenneth Wright's new web framework called Responder, right?

00:24:12.780 --> 00:24:13.280
I think so.

00:24:13.280 --> 00:24:17.940
I think so. Yeah, I'm pretty sure we have. So I decided to create a super short little mini course on it.

00:24:17.940 --> 00:24:31.560
So I created a almost one hour long course on Responder and the framework and it actually uses, goes and builds that we go and build out like a cool API using Responder and then actually consume it with Vue.js as well.

00:24:31.560 --> 00:24:40.040
So there's a cool little Vue.js front end on top of that. So if people want to get some quick exposure to Responder, maybe see some of the cool features that it can do.

00:24:40.260 --> 00:24:49.480
Kind of Flask-like, but it does a bunch of other awesome stuff as well. It's not just Flask. Check that out. So check out the Responder course. Like I said, it's free. So no problem. You can just go check that out.

00:24:49.480 --> 00:25:00.500
And the other one is really cool, but I have to really remind myself to use it. So imagine this. I'm working in an editor. This is for PyCharm or any of the IntelliJ platforms like WebStorm or whatever.

00:25:01.300 --> 00:25:13.120
And I've got like a big monitor up, a whole bunch of code on the screen, and I have my fingers on the keyboard and I want to go up to that section where I'm doing like open something, something as fin or whatever.

00:25:13.120 --> 00:25:19.540
Right. But I don't want to take my mouse and go over that. I don't want to arrow up like 17 lines and then go to the right control, whatever.

00:25:19.540 --> 00:25:22.940
So there's this thing called Ace Jump. Have you heard of this?

00:25:22.940 --> 00:25:23.360
No.

00:25:23.360 --> 00:25:28.320
Ace Jump lets you hit a hotkey. I think it's on Mac. It's command semicolon.

00:25:28.980 --> 00:25:38.920
And then if you type, let's say F-I, it'll go and put like a single character on every space that F-I is a substring of on the screen.

00:25:38.920 --> 00:25:45.620
Maybe the one I'm looking for has like a J byte. So it's F-I and hit J. And it'll take you straight to it.

00:25:45.620 --> 00:25:55.120
So it basically turns your screen, your code into like, you do a little bit of a search and then like one character keystroke to jump to that section of code.

00:25:55.120 --> 00:25:55.920
Oh, that's cool.

00:25:55.920 --> 00:25:56.620
It's super cool.

00:25:57.020 --> 00:26:05.540
It's super hard to remember to do that. Not just arrow, arrow, arrow, arrow or mouse or whatever. Right. But it's if I can remind myself to do this, it's going to be great.

00:26:05.540 --> 00:26:08.620
Okay. Well, I mean, I don't use arrows, man.

00:26:08.620 --> 00:26:09.400
Sometimes.

00:26:09.400 --> 00:26:10.740
There's a V-I mode.

00:26:10.740 --> 00:26:13.180
True. True, true.

00:26:13.180 --> 00:26:17.000
Anyway. So, no, that's cool. I'm going to have to try that out.

00:26:17.000 --> 00:26:23.460
Yeah. So it's just basically like type as you search and the whole thing becomes like sort of quick jump around your editor.

00:26:24.400 --> 00:26:25.760
All right. Are you ready for a pie joke?

00:26:25.760 --> 00:26:26.560
I am.

00:26:26.560 --> 00:26:27.780
I got to hit it a few times.

00:26:27.780 --> 00:26:31.440
What's the object oriented way to become wealthy?

00:26:31.440 --> 00:26:32.300
I don't know. How?

00:26:32.300 --> 00:26:32.980
Inheritance.

00:26:32.980 --> 00:26:33.300
Okay.

00:26:33.300 --> 00:26:34.000
That's bad, right?

00:26:34.780 --> 00:26:38.820
A good programmer is someone who always looks both ways before crossing a one-way street.

00:26:38.820 --> 00:26:43.240
Child.

00:26:43.240 --> 00:26:43.920
Dad.

00:26:43.920 --> 00:26:47.000
Why does the sun rise in the east and set in the west?

00:26:47.000 --> 00:26:48.140
Dad.

00:26:48.140 --> 00:26:49.220
Sun is working.

00:26:49.220 --> 00:26:49.840
Don't touch it.

00:26:49.840 --> 00:26:53.040
All right.

00:26:53.040 --> 00:26:55.540
I'll do one more for you because it's about Python 2.7.

00:26:56.040 --> 00:26:59.680
Remfinally, Beth removed Python 2.7 from her server in 2020.

00:26:59.680 --> 00:27:04.200
Finally, she said with glee, only to see the announcement for Python 4.4.

00:27:04.200 --> 00:27:06.480
Yeah.

00:27:06.480 --> 00:27:08.400
All right.

00:27:08.400 --> 00:27:09.840
That's pretty cool.

00:27:09.840 --> 00:27:11.760
Well, I guess we'll leave it there, huh?

00:27:11.760 --> 00:27:12.040
Yep.

00:27:12.040 --> 00:27:12.560
That's good.

00:27:12.560 --> 00:27:13.000
All right, Brian.

00:27:13.000 --> 00:27:13.680
Thanks for being here.

00:27:13.680 --> 00:27:15.160
Thanks for finding all these items.

00:27:15.160 --> 00:27:15.560
Thanks.

00:27:15.560 --> 00:27:15.940
Bye.

00:27:15.940 --> 00:27:16.040
Bye.

00:27:16.280 --> 00:27:18.020
Thank you for listening to Python Bytes.

00:27:18.020 --> 00:27:20.560
Follow the show on Twitter via at Python Bytes.

00:27:20.560 --> 00:27:23.400
That's Python Bytes as in B-Y-T-E-S.

00:27:23.400 --> 00:27:26.640
And get the full show notes at pythonbytes.fm.

00:27:26.640 --> 00:27:30.860
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:27:30.860 --> 00:27:33.540
We're always on the lookout for sharing something cool.

00:27:33.540 --> 00:27:36.680
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:27:36.680 --> 00:27:40.100
Thank you for listening and sharing this podcast with your friends and colleagues.

