WEBVTT
00:00:00.001 -->
00:00:04.960Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
00:00:04.960 -->
00:00:09.800This is episode 351, recorded September 5th, and I am Brian Okken.
00:00:09.800 -->
00:00:11.020And I'm Michael Kennedy.
00:00:11.020 -->
00:00:14.920And this episode is also sponsored by Sentry. Thank you, Sentry.
00:00:14.920 -->
00:00:19.420And if you want to reach any of us or the show, either of us or the show,
00:00:19.420 -->
00:00:25.560we're at mkennedy, at brianauken, and at pythonbytes, all at fostadon.org.
00:00:25.680 -->
00:00:31.220And if you're listening later and you'd like to join the show live sometime,
00:00:31.220 -->
00:00:36.080you can join us on YouTube at pythonbytes.fm/live.
00:00:36.080 -->
00:00:37.700And we'd love to have you here.
00:00:37.700 -->
00:00:38.340Indeed.
00:00:38.340 -->
00:00:39.820What do you got for us first, Michael?
00:00:39.820 -->
00:00:42.600Let's talk about multiprocessing.
00:00:42.600 -->
00:00:46.240Empire, not pyre, but mpire, right?
00:00:46.240 -->
00:00:48.460Pyre is the type checker from meta.
00:00:48.460 -->
00:00:53.220Empire is something entirely different about multiprocessing.
00:00:53.220 -->
00:00:58.820And so it's a Python package for easy multiprocessing that's faster than the built-in
00:00:58.820 -->
00:01:04.840multiprocessing, but has a similar API, has really good error reporting and a bunch of
00:01:04.840 -->
00:01:07.840other types of reporting, like how well did that session go?
00:01:07.840 -->
00:01:13.080You know, like how well did you utilize the multiprocessing capabilities of your machine
00:01:13.080 -->
00:01:13.620and so on?
00:01:13.620 -->
00:01:15.400So yeah, let's dig into it.
00:01:15.400 -->
00:01:20.440So the whole acronym for the name is multiprocessing is really easy,
00:01:20.440 -->
00:01:22.260which is not what most people say, right?
00:01:22.600 -->
00:01:23.040No.
00:01:23.040 -->
00:01:29.780But it's a package that's faster than multiprocessing in most cases, has more features,
00:01:29.780 -->
00:01:34.020and is generally more user-friendly than the default multiprocessing package.
00:01:34.020 -->
00:01:41.560It has APIs like multiprocessing.pool, but it also has the benefits of things like copy,
00:01:41.560 -->
00:01:42.620unwrite, shared objects.
00:01:42.620 -->
00:01:44.720We're going to come back to that later as well.
00:01:45.200 -->
00:01:52.380But also the ability to have like init and exit, set up teardown for your workers, some more
00:01:52.380 -->
00:01:53.960state that you can use and so on.
00:01:53.960 -->
00:01:55.300So pretty cool.
00:01:55.300 -->
00:01:56.920It has a progress bar.
00:01:57.080 -->
00:02:02.660It has TQDM progress built right into it across the multiple processes.
00:02:02.660 -->
00:02:05.720So you can say things like, here is some work I want you to do.
00:02:05.720 -->
00:02:06.700There's a hundred items.
00:02:06.700 -->
00:02:09.500Split that across five cores.
00:02:10.020 -->
00:02:15.960And as those different processes complete the work for individual elements, give me a unified
00:02:15.960 -->
00:02:18.260progress bar, which is pretty awesome, right?
00:02:18.260 -->
00:02:18.820Yeah.
00:02:18.820 -->
00:02:19.300Yeah.
00:02:19.300 -->
00:02:19.760Very cool.
00:02:19.880 -->
00:02:20.000Yeah.
00:02:20.000 -->
00:02:20.540Yeah.
00:02:20.540 -->
00:02:22.280It's got a progress dashboard.
00:02:22.280 -->
00:02:23.580Actually, I have no idea what that is.
00:02:23.580 -->
00:02:27.260It has a worker insights that you can ask when it's done.
00:02:27.260 -->
00:02:31.020Like how well did, you know, how efficient was that multiprocessing story?
00:02:31.020 -->
00:02:33.660Graceful and user-friendly exception handling.
00:02:33.660 -->
00:02:34.680It has timeouts.
00:02:34.680 -->
00:02:41.200So you can say, I would like the execution of the work to not take more than three seconds.
00:02:41.200 -->
00:02:47.240And actually you can even say things such as if the worker process itself takes 10 seconds
00:02:47.240 -->
00:02:50.860or more to exit, maybe there's like some, something happening over there.
00:02:50.860 -->
00:02:55.140That's like a hung connection on a database thing or who knows, right?
00:02:55.140 -->
00:02:55.780Some network thing.
00:02:55.780 -->
00:02:59.320You can actually set a different timeout for the process, which is pretty cool.
00:02:59.320 -->
00:03:01.680It has automatic chunking.
00:03:01.680 -->
00:03:06.580So instead of saying, I have a hundred things, let's go individually one at a time, hand them
00:03:06.580 -->
00:03:07.200off to workers.
00:03:07.200 -->
00:03:13.460It can break them up into bigger blocks, including numpy arrays, which is pretty cool.
00:03:13.740 -->
00:03:18.360You can set the maximum number of tasks that are allowed to run at any given moment.
00:03:18.360 -->
00:03:21.780I guess, you know, you can set the workers, but also like, if it does this chunking and
00:03:21.780 -->
00:03:24.620you can say how many things can run to avoid memory problems.
00:03:24.620 -->
00:03:29.400You could even say, four, I want to use five processes, but after.
00:03:29.400 -->
00:03:33.480You know, 10, 10 bits of work on any given process.
00:03:33.660 -->
00:03:38.280Give me a new worker and shut down the others in case there's like leaky memory or other
00:03:38.280 -->
00:03:39.480things along those lines.
00:03:39.480 -->
00:03:42.880you can create a pool of them through a daemon option.
00:03:42.880 -->
00:03:44.080A whole bunch of stuff.
00:03:44.080 -->
00:03:51.000It uses dill to serialize across, the multi-process processes, which is cool because it gives you
00:03:51.000 -->
00:04:00.000more exotic, serialization options for say objects that are not pickleable lambdas functions and other
00:04:00.000 -->
00:04:01.980things in IPython and Jupyter notebooks.
00:04:01.980 -->
00:04:03.420So all that's pretty awesome.
00:04:03.420 -->
00:04:03.700Right?
00:04:03.700 -->
00:04:04.260Yeah.
00:04:04.260 -->
00:04:04.840Yeah.
00:04:05.060 -->
00:04:11.180So the API is super, super simple from empire import worker pool with worker pool jobs equal
00:04:11.180 -->
00:04:14.520five, pull that map, some function, some data go.
00:04:14.520 -->
00:04:19.840So this jobs here tells you how many processes to run basically for the progress bar.
00:04:19.840 -->
00:04:22.560you just set progress bar equals true.
00:04:22.560 -->
00:04:23.620That's not too bad.
00:04:23.620 -->
00:04:26.220Another thing that's cool is you can have shared objects.
00:04:26.220 -->
00:04:33.500So you can have, some shared data that's passed across without, basically using shared
00:04:33.500 -->
00:04:33.840memory.
00:04:33.840 -->
00:04:37.860I think is how that it works so that it's more efficient instead of trying to pickle it
00:04:37.860 -->
00:04:38.280across.
00:04:38.280 -->
00:04:39.740I think they have to be read only or something.
00:04:39.740 -->
00:04:40.720And there's a whole bunch about it.
00:04:40.720 -->
00:04:41.240Oh, interesting.
00:04:41.240 -->
00:04:43.640But you pass it into the worker pool.
00:04:43.640 -->
00:04:44.140Okay.
00:04:44.140 -->
00:04:44.740Yeah.
00:04:44.740 -->
00:04:49.060You say worker pool, these things, I want you to set them up in a way to be shared.
00:04:49.060 -->
00:04:54.740And I think, like I said, in a read only way across, across all the processes instead
00:04:54.740 -->
00:04:55.900of trying to copy them over.
00:04:55.900 -->
00:05:03.780you have a setup and a teardown thing that you can do, to like prepare the worker,
00:05:03.780 -->
00:05:08.840when it gets started, you can ask it for the insights, like I said, and then
00:05:08.840 -->
00:05:09.260benchmarks.
00:05:09.260 -->
00:05:11.760It shows it's significantly faster.
00:05:11.760 -->
00:05:16.080Not just the compared, not just against multi-processing, but they say, here's how you do it.
00:05:16.080 -->
00:05:17.980Here's what happens if you do it in a serial way.
00:05:17.980 -->
00:05:21.440Here's what multi-processing and process pool executors look like.
00:05:21.520 -->
00:05:24.520But it also compares against job lib, dask, and array.
00:05:24.520 -->
00:05:24.960Mm.
00:05:24.960 -->
00:05:28.580And it's, it's pretty much hanging there with the best of them, isn't it?
00:05:28.580 -->
00:05:29.000Yeah.
00:05:29.000 -->
00:05:31.980It does a titch faster than ray everywhere.
00:05:31.980 -->
00:05:32.460Yeah.
00:05:32.460 -->
00:05:33.560Just, yeah.
00:05:33.560 -->
00:05:34.560Just, just a bit.
00:05:34.560 -->
00:05:35.840One other thing.
00:05:35.960 -->
00:05:40.180I don't remember where it was, in this huge, long list of things.
00:05:40.180 -->
00:05:47.500but you can also pin the CPUs to CPU cores, which can be really valuable when you're thinking
00:05:47.500 -->
00:05:52.160about, taking advantage of, you know, L1, L2 CPU caches.
00:05:52.300 -->
00:05:56.920So if your processes are bouncing around back and forth, one's working with some data, then
00:05:56.920 -->
00:05:58.840it switches to another core.
00:05:58.840 -->
00:06:05.340And then it has to pull a new data into the, into the L2 cache, which is like hundreds
00:06:05.340 -->
00:06:06.800of times slower than real memory.
00:06:06.800 -->
00:06:08.080And that's how that slows it down.
00:06:08.080 -->
00:06:09.480Then they switch back and they keep running.
00:06:09.480 -->
00:06:14.740So you can say, you know, pin these workers to these CPUs and you know, you've got a better
00:06:14.740 -->
00:06:17.600chance of them not redoing their cache all the time.
00:06:17.600 -->
00:06:18.260So that's kind of cool.
00:06:18.260 -->
00:06:19.900So there's just a bunch of neat little features in here.
00:06:19.900 -->
00:06:20.480Yeah.
00:06:20.620 -->
00:06:23.400If you're already using multiprocessing, you might check this out.
00:06:23.400 -->
00:06:26.800Oh, if you care about performance for real, you know,
00:06:26.800 -->
00:06:30.740why are you using multiprocessing if you don't care about performance?
00:06:30.740 -->
00:06:36.240Well, I mean, you're, you're looking to pull out the final little bits of performance, I
00:06:36.240 -->
00:06:36.640suppose.
00:06:36.640 -->
00:06:37.020Yeah.
00:06:37.020 -->
00:06:37.220Yeah.
00:06:37.220 -->
00:06:37.440Yeah.
00:06:37.440 -->
00:06:38.100Right.
00:06:38.100 -->
00:06:42.160Like these benchmarks are cool, but they're doing, you know, computation on the workers.
00:06:42.160 -->
00:06:42.600Right.
00:06:42.600 -->
00:06:47.380Whereas a lot of what you're doing is like talking to queues and talking to networks and talking
00:06:47.380 -->
00:06:47.980to databases.
00:06:47.980 -->
00:06:51.260Like it doesn't matter what framework you used to do that long as you're doing something
00:06:51.260 -->
00:06:51.680parallel.
00:06:51.680 -->
00:06:52.300Right.
00:06:52.300 -->
00:06:52.820Yeah.
00:06:52.820 -->
00:06:53.680Well, yeah.
00:06:53.680 -->
00:06:54.320Well, I don't know.
00:06:54.320 -->
00:06:55.760That's why you have to do your own benchmarks.
00:06:55.760 -->
00:06:56.760Yeah, for sure.
00:06:56.760 -->
00:07:00.740And then there's that article over on medium by the creator as well.
00:07:01.160 -->
00:07:03.640That gives you a whole lot of background on all this stuff.
00:07:03.640 -->
00:07:04.220Oh, neat.
00:07:04.220 -->
00:07:04.800Nice.
00:07:04.800 -->
00:07:05.140Yeah.
00:07:05.140 -->
00:07:06.740This is quite a long article.
00:07:06.740 -->
00:07:08.660And I think it's actually more relevant.
00:07:08.660 -->
00:07:13.240Like, for example, it's got screenshots where it shows, you know, if you use something like,
00:07:13.240 -->
00:07:14.760let me read really quickly.
00:07:14.760 -->
00:07:19.000Ray or job lib and you get some kind of exception.
00:07:19.000 -->
00:07:20.560It just says exception occurred.
00:07:20.560 -->
00:07:21.160Yikes.
00:07:21.540 -->
00:07:26.340Whereas with this one, with empire, you get things like here's the call stack that goes
00:07:26.340 -->
00:07:28.520back a little more correctly to the right function.
00:07:28.520 -->
00:07:30.900And here's the arguments that were passed.
00:07:30.900 -->
00:07:31.960Oh, interesting.
00:07:31.960 -->
00:07:32.620Over.
00:07:32.620 -->
00:07:37.700So when it crashes, you know, because you have like five processes, potentially all doing
00:07:37.700 -->
00:07:37.940stuff.
00:07:37.940 -->
00:07:38.580One of them crashed.
00:07:38.580 -->
00:07:39.780Like what data did they have?
00:07:39.780 -->
00:07:40.480I don't know.
00:07:40.480 -->
00:07:41.460It's a parallel.
00:07:41.460 -->
00:07:41.960It's hard.
00:07:41.960 -->
00:07:42.500Right.
00:07:42.560 -->
00:07:46.600So having the arguments like these are the ones that cause the error is pretty excellent.
00:07:46.600 -->
00:07:47.120Yeah.
00:07:47.120 -->
00:07:47.580Cool.
00:07:47.580 -->
00:07:49.400Anyway, empire.
00:07:49.400 -->
00:07:50.560That's what I got for number one.
00:07:50.560 -->
00:07:52.240All right.
00:07:52.240 -->
00:07:52.500Cool.
00:07:52.500 -->
00:07:56.740I want to have, I have something else that starts with M.
00:07:56.740 -->
00:07:58.840Mop up.
00:07:58.840 -->
00:08:05.240So mop up is something that I learned about from an article by glyph.
00:08:05.240 -->
00:08:07.340So I'll let me jump to the article first.
00:08:07.340 -->
00:08:12.040So glyph wrote an article saying, get your Mac Python from python.org.
00:08:12.040 -->
00:08:13.440That's what I already do.
00:08:13.440 -->
00:08:19.080I've tried all the other stuff and I just like just the downloader from python.org.
00:08:19.080 -->
00:08:23.760So this article talks about reasons why that's probably what you want.
00:08:23.760 -->
00:08:28.900And that's probably what if you're writing a tutorial, it's probably what your users need
00:08:28.900 -->
00:08:29.440to do, too.
00:08:29.440 -->
00:08:35.840If they're if they're using a Mac and I won't go through all the details, but he he goes through
00:08:35.840 -->
00:08:42.020reasons why you probably want this one and not things like what are the others?
00:08:42.020 -->
00:08:42.960homebrew.
00:08:42.960 -->
00:08:46.580You can brew install your Python, but he doesn't recommend it.
00:08:46.580 -->
00:08:48.200And you can read all the pyenv.
00:08:48.200 -->
00:08:49.200I've tried it.
00:08:49.200 -->
00:08:52.040It like messes up other stuff for me.
00:08:52.040 -->
00:08:54.500So I like the downloader from Python.
00:08:54.500 -->
00:09:01.720But one of the things that I don't like is that if like if I had Python 311 4 installed and
00:09:01.720 -->
00:09:03.640now Python 311 5 is out.
00:09:03.780 -->
00:09:05.480How do I get that on my computer?
00:09:05.480 -->
00:09:06.660Do I just reinstall it?
00:09:06.660 -->
00:09:07.620Yes, you can.
00:09:07.620 -->
00:09:11.900But Glyph made a new thing called mop up.
00:09:11.900 -->
00:09:16.720So what mop up does is you you just pip install mop up.
00:09:16.840 -->
00:09:23.920And it's like the only thing I install on my global my global Python versions like 311 pip install.
00:09:23.920 -->
00:09:26.980I update pip and install this and that's it.
00:09:26.980 -->
00:09:28.820Everything else goes into a virtual environment.
00:09:29.580 -->
00:09:32.000Or pip x install this.
00:09:32.000 -->
00:09:32.560Exactly.
00:09:32.560 -->
00:09:34.640But mop up.
00:09:34.640 -->
00:09:35.360What's the usage?
00:09:35.360 -->
00:09:36.680So I just tried it this morning.
00:09:36.680 -->
00:09:38.780I didn't pass it any flags.
00:09:38.780 -->
00:09:40.860I just installed it and ran it.
00:09:40.860 -->
00:09:48.360And it updated me from Python 311 4 to Python 311 5 without me having to re-download anything
00:09:48.360 -->
00:09:49.320other than this.
00:09:49.580 -->
00:09:52.680So I'm going to set up something that goes through.
00:09:52.680 -->
00:09:54.760I've got a lot of versions on my computer.
00:09:54.760 -->
00:09:58.140I've got I think well I've got 3.7 through 3.12 install.
00:09:58.140 -->
00:10:02.960And and I want all of them to be on the latest bug fix release.
00:10:02.960 -->
00:10:12.760So I'm just going to use probably use Brett Cannon's pi installer or Python installer pi on
00:10:12.760 -->
00:10:17.640my Mac to go to each of the versions and run mop up on all of them to update it.
00:10:17.780 -->
00:10:19.920So that's what I'd like to do.
00:10:19.920 -->
00:10:20.900Anyway it's cool.
00:10:20.900 -->
00:10:25.940I'm I'm really excited about this because this was like the one hole in using the install
00:10:25.940 -->
00:10:29.840the the python.org installer is how they update it.
00:10:29.840 -->
00:10:31.260So nice.
00:10:31.260 -->
00:10:31.520Yep.
00:10:31.520 -->
00:10:32.260Interesting.
00:10:32.260 -->
00:10:32.780Interesting.
00:10:32.780 -->
00:10:37.460I got to admit I'm still a brew install Python 3 sort of person.
00:10:37.460 -->
00:10:38.080Okay.
00:10:38.080 -->
00:10:43.660And the drawback the main drawback that glyph makes an argument for which is valid is you
00:10:43.660 -->
00:10:46.700don't control necessarily the version of Python that you get.
00:10:46.820 -->
00:10:53.740Because if you brew install I don't know some other you know YouTube downloader app or whatever
00:10:53.740 -->
00:10:59.880rando thing it might say well I need a Python 3.12 and you only have 3.8 right.
00:10:59.880 -->
00:11:02.120And it'll auto upgrade on you without you knowing.
00:11:02.120 -->
00:11:05.560But I'm always running the absolute latest Python anyway.
00:11:05.560 -->
00:11:10.140And so you know when it those other packages say greater than 3.10 like I don't care I already
00:11:10.140 -->
00:11:11.040have greater than 3.10.
00:11:11.400 -->
00:11:15.600So I don't know that's the world I'm living in now but that's okay for me.
00:11:15.600 -->
00:11:16.680Oh okay.
00:11:16.680 -->
00:11:23.220So yeah I'm I'm a package maintainer so I I have multiple versions on my box but it's
00:11:23.220 -->
00:11:28.100but in a lot of people like pyenv for that reason but I yeah I don't.
00:11:28.320 -->
00:11:32.640But anyway I've always I've had trouble with pyenv too especially around the Apple Silicon
00:11:32.640 -->
00:11:41.260Rosetta compiler mismatch like there's just like it wouldn't install for me and so yeah I think the
00:11:41.260 -->
00:11:43.760whole I think the python.org it's a good recommendation though.
00:11:43.760 -->
00:11:44.580Okay cool.
00:11:44.580 -->
00:11:45.520Yep yep.
00:11:45.520 -->
00:11:46.080All right.
00:11:46.920 -->
00:11:49.740before we move on to our next topic Brian.
00:11:49.740 -->
00:11:55.000Well I'd like to thank Sentry for sponsoring this episode of Python Bytes.
00:11:55.000 -->
00:11:59.560You know Sentry for their error tracking service but did you know that you can take take it all
00:11:59.560 -->
00:12:04.520the way through your multi-tier and distributed app with their distributed tracing feature?
00:12:04.520 -->
00:12:05.400How cool is that?
00:12:05.400 -->
00:12:10.720Distributed tracing is a debugging technique that involves tracking your the request of your
00:12:10.720 -->
00:12:15.120system starting from the very beginning like the user action all the way to the back end
00:12:15.120 -->
00:12:16.840database and third-party services.
00:12:16.840 -->
00:12:24.180This can help you identify if the cause of the an error is one project in one project is due to an
00:12:24.180 -->
00:12:25.920error in the other another project.
00:12:25.920 -->
00:12:27.280That's very useful.
00:12:27.280 -->
00:12:33.240Every system can benefit from distributed tracing but they are useful for especially for microservices
00:12:33.240 -->
00:12:40.060in microservice architecture logs won't give you the full picture so you can't debug every request
00:12:40.060 -->
00:12:45.000in full by reading the logs but distributed tracing with a platform like Sentry
00:12:45.000 -->
00:12:50.060can give you visual overview of which services were called during the execution of certain requests.
00:12:50.060 -->
00:12:56.060Aside from debugging and visualizing architecture distributed tracing also helps you identify
00:12:56.060 -->
00:12:59.060performance bottlenecks through a visual like Gantt chart.
00:12:59.060 -->
00:13:08.120You can see if a particular span in your stack took longer than expected and how it could be causing slowdowns in other parts of your app.
00:13:08.120 -->
00:13:17.180You can see if you can see the results of your app.
00:13:17.180 -->
00:13:17.180You can see the results of your app.
00:13:17.180 -->
00:13:18.180You can see the results of your app.
00:13:18.180 -->
00:13:19.180You can see the results of your app.
00:13:19.180 -->
00:13:30.240You can see the results of your app.
00:13:30.240 -->
00:13:41.300You can see the results of your app.
00:13:41.300 -->
00:13:52.360You can see the results of your app.
00:13:52.360 -->
00:14:03.420You can see the results of your app.
00:14:03.420 -->
00:14:04.420You can see the results of your app.
00:14:04.420 -->
00:14:16.480You can see the results of your app.
00:14:16.480 -->
00:14:28.540You can see the results of your app.
00:14:28.540 -->
00:14:29.540You can see the results of your app.
00:14:29.540 -->
00:14:30.540You can see the results of your app.
00:14:30.540 -->
00:14:31.540You can see the results of your app.
00:14:31.540 -->
00:14:32.540You can see the results of your app.
00:14:32.540 -->
00:14:33.540You can see the results of your app.
00:14:33.540 -->
00:14:34.540You can see the results of your app.
00:14:34.540 -->
00:14:35.540You can see the results of your app.
00:14:35.540 -->
00:14:36.540You can see the results of your app.
00:14:36.540 -->
00:14:37.540You can see the results of your app.
00:14:37.540 -->
00:14:38.540You can see the results of your app.
00:14:38.540 -->
00:14:39.540You can see the results of your app.
00:14:39.540 -->
00:14:40.540You can see the results of your app.
00:14:40.540 -->
00:14:41.540You can see the results of your app.
00:14:41.540 -->
00:14:42.540You can see the results of your app.
00:14:42.540 -->
00:14:43.540You can see the results of your app.
00:14:43.540 -->
00:14:44.540You can see the results of your app.
00:14:44.540 -->
00:14:45.540You can see the results of your app.
00:14:45.540 -->
00:14:46.540You can see the results of your app.
00:14:46.540 -->
00:14:47.540You can see the results of your app.
00:14:47.540 -->
00:14:48.540You can see the results of your app.
00:14:48.540 -->
00:14:49.540You can see the results of your app.
00:14:49.540 -->
00:14:50.540You can see the results of your app.
00:14:50.540 -->
00:14:51.540You can see the results of your app.
00:14:51.540 -->
00:14:52.540You can see the results of your app.
00:14:52.540 -->
00:14:53.540You can see the results of your app.
00:14:53.540 -->
00:14:54.540You can see the results of your app.
00:14:54.540 -->
00:14:55.540You can see the results of your app.
00:14:55.540 -->
00:14:56.540You can see the results of your app.
00:14:56.540 -->
00:14:57.540You can see the results of your app.
00:14:57.540 -->
00:14:58.540You can see the results of your app.
00:14:58.540 -->
00:14:59.540You can see the results of your app.
00:14:59.540 -->
00:15:00.540You can see the results of your app.
00:15:00.540 -->
00:15:01.540You can see the results of your app.
00:15:01.540 -->
00:15:02.540You can see the results of your app.
00:15:02.540 -->
00:15:03.540You can see the results of your app.
00:15:03.540 -->
00:15:04.540You can see the results of your app.
00:15:04.540 -->
00:15:05.540You can see the results of your app.
00:15:05.540 -->
00:15:06.540You can see the results of your app.
00:15:06.540 -->
00:15:07.540You can see the results of your app.
00:15:07.540 -->
00:15:08.540You can see the results of your app.
00:15:08.540 -->
00:15:09.540You can see the results of your app.
00:15:09.540 -->
00:15:10.540You can see the results of your app.
00:15:10.540 -->
00:15:11.540You can see the results of your app.
00:15:11.540 -->
00:15:12.540You can see the results of your app.
00:15:12.540 -->
00:15:13.540You can see the results of your app.
00:15:13.540 -->
00:15:19.540So if you have x equals a string, and then I say y equals x, it goes up to that thing
00:15:19.540 -->
00:15:22.540and says plus plus, you know, plus equals one on the reference count.
00:15:22.540 -->
00:15:26.540And when y goes away, then it minus minuses it, right?
00:15:26.540 -->
00:15:27.540When that number hits zero, it gets cleaned up.
00:15:27.540 -->
00:15:31.540There's also stuff on the object for cycles and garbage collection.
00:15:31.540 -->
00:15:33.540So there's a lot of stuff that's happening there, right?
00:15:33.540 -->
00:15:34.540Yeah.
00:15:34.540 -->
00:15:41.540And so what they're doing is they're running a lot of Django for Instagram, which is pretty awesome.
00:15:41.540 -->
00:15:49.540However, what they're trying to take advantage of is the fact that there's a lot of similar data, similar memory usage.
00:15:49.540 -->
00:15:58.540When I load up Python, so if I write type Python on the terminal, and then I open up a new terminal type Python, it's gone through exactly the same startup process, right?
00:15:58.540 -->
00:16:01.540So it's loaded the same shared libraries or DLLs.
00:16:01.540 -->
00:16:02.540It's created.
00:16:02.540 -->
00:16:09.540It's, it's, you know, negative 255 to 255 flywheel numbers.
00:16:09.540 -->
00:16:13.540There's going to reuse instead of when you say the number seven, it doesn't always create a new seven.
00:16:13.540 -->
00:16:17.540You always have the seven that was created at startup exceptions, those kinds of things, right?
00:16:17.540 -->
00:16:32.540Well, if you have a web server that's got 10 or 20 or a hundred worker processes that all went through the same startup for a Python app, you would want to have things like that number seven or some exception type or whatever modules, right?
00:16:32.540 -->
00:16:33.540Core modules that are loaded.
00:16:33.540 -->
00:16:40.540You would like to have one copy of those in memory on Linux, and then have a copy on right thing for the stuff that actually changes.
00:16:40.540 -->
00:16:42.540But those other pieces, you want them to stay the same.
00:16:42.540 -->
00:16:43.540Yeah.
00:16:43.540 -->
00:16:44.540Yeah.
00:16:44.540 -->
00:16:49.540Like there's no point in having like a different representation of the number four for every process.
00:16:49.540 -->
00:16:52.540If there's some way to share that memory that was created at startup.
00:16:52.540 -->
00:16:55.540And we don't need reference counts updated and all that stuff.
00:16:55.540 -->
00:16:56.540Because exactly exactly.
00:16:56.540 -->
00:17:07.540So the, I, what they found was, while many of their Python objects are practically or effectively immutable, they didn't actually over time behave that way.
00:17:07.540 -->
00:17:10.540So they have graphs of private memory and shared memory.
00:17:10.540 -->
00:17:16.540And what you would hope is that the shared memory stays pretty stable over time, or maybe even grows.
00:17:16.540 -->
00:17:17.540Maybe you're doing new stuff.
00:17:17.540 -->
00:17:20.540That's like pulled in similar things, but that's not what happens in practice.
00:17:20.540 -->
00:17:22.540I'm current Python.
00:17:22.540 -->
00:17:32.540The shared memory goes down and down and down, because even though that object, or let's say that flywheel number that got created to be shared, it's still got his reference count number change.
00:17:32.540 -->
00:17:36.540So throughout the behavior of one app, it might go, well, four was used for a long time.
00:17:36.540 -->
00:17:39.540Four was used 300 times here and 280 over there.
00:17:39.540 -->
00:17:41.540So those are not the same four.
00:17:41.540 -->
00:17:45.540Cause on the reference count, they have 281 and 301 or whatever it is.
00:17:45.540 -->
00:17:46.540Right.
00:17:46.540 -->
00:18:02.540And so that, that shared memory is falling down because the garbage collector and, just the interacting with the ref count is very in very meaningless and small ways, changing pieces of the shared memory to make them fall out of the shared state.
00:18:02.540 -->
00:18:06.540So this whole path, this whole idea is we're going to make those types of things.
00:18:06.540 -->
00:18:08.540so that their reference count can't change.
00:18:08.540 -->
00:18:10.540And their GC structures can't change.
00:18:10.540 -->
00:18:11.540They cannot be changed.
00:18:11.540 -->
00:18:17.540They're just always set to some magic number for like this thing's reference count is unchanged.
00:18:17.540 -->
00:18:18.540Right.
00:18:18.540 -->
00:18:26.540So if you look at like the object header, it's got a GC header reference count object type, and then the actual data for the ones that don't change.
00:18:26.540 -->
00:18:28.540Now these new ones can be set.
00:18:28.540 -->
00:18:31.540So even their GC header and the reference counts don't change.
00:18:31.540 -->
00:18:32.540Cool.
00:18:32.540 -->
00:18:32.540Right.
00:18:32.540 -->
00:18:33.540Yeah.
00:18:33.540 -->
00:18:33.540Yeah.
00:18:33.540 -->
00:18:38.540And what that means is if you come down here, it says there's some challenges.
00:18:38.540 -->
00:18:41.540First, they had to make sure that applications wouldn't crash.
00:18:41.540 -->
00:18:44.540If some objects suddenly had different ref counts.
00:18:44.540 -->
00:18:55.540Second, it changes the core memory representation of a Python object, which if you work in the C level, just directly with the memory, that's, you know, pointers to the object.
00:18:55.540 -->
00:18:56.540That can be tricky.
00:18:56.540 -->
00:19:08.540And finally, the core implementation relies on adding checks explicitly to the increment and decrement, the, you know, add ref, remove ref, decrement ref, which are two of the hottest bits of code in all of Python.
00:19:08.540 -->
00:19:09.540Yeah.
00:19:09.540 -->
00:19:10.540As in the most performance critical.
00:19:10.540 -->
00:19:15.540So if you make a change to it, or you make all the Python slower for this, that's bad.
00:19:15.540 -->
00:19:18.540And they did make Python slower, but only 2%.
00:19:18.540 -->
00:19:22.540And they believe that the benefits they get is actually worth it.
00:19:22.540 -->
00:19:26.540Cause you bring in, you know, for like heavy workloads, you get actually better performance.
00:19:26.540 -->
00:19:28.540So it's a trade off, but there it is.
00:19:28.540 -->
00:19:30.540One of the things that was reading this article.
00:19:30.540 -->
00:19:40.540And one of the things that confused me was, is there, is this just something internal to Python that, that it's going to happen under the hood or do I need to change my syntax in any way?
00:19:40.540 -->
00:19:41.540Yes.
00:19:41.540 -->
00:19:42.540I was looking for that as well.
00:19:42.540 -->
00:19:53.540And every single thing about, I went and read the PEP and everything I remember from reading the PEP and maybe I missed something, but everything I got from the PEP was it, the C layer.
00:19:53.540 -->
00:19:59.540It was, you know, here's the pie immortal, you know, call that you make in the C API.
00:19:59.540 -->
00:20:04.540So what I would like to see is something where you set a decorate, like kind of like a data class.
00:20:04.540 -->
00:20:06.540Like this thing is outside of garbage collection.
00:20:06.540 -->
00:20:14.540This class is out or this, I don't know, in some way to say in Python, this thing is a moral for now, at least.
00:20:14.540 -->
00:20:15.540Yeah.
00:20:15.540 -->
00:20:16.540But I didn't see it either.
00:20:16.540 -->
00:20:22.540It also would be good even if we could just do like, like, that would be kind of like a constant then also.
00:20:22.540 -->
00:20:28.540We could set up some, some constants in your system that, that are immortal or something.
00:20:28.540 -->
00:20:29.540Yeah.
00:20:29.540 -->
00:20:30.540Okay.
00:20:30.540 -->
00:20:31.540Yeah.
00:20:31.540 -->
00:20:41.540Like the dictionary of a module that loads up, if you're not dynamically changing it, which you almost never do, unless you're like mocking something out, like, let it, let it be, you know, it's just tell it it's the same.
00:20:41.540 -->
00:20:42.540Don't, don't reference combat.
00:20:42.540 -->
00:20:43.540Yeah.
00:20:43.540 -->
00:20:53.540I'd be curious to see in this implement, as they're implementing it, it does seem like parts of the system are going to go a little bit slower, but also parts of it are going to go faster because you don't have to do all that work, but.
00:20:53.540 -->
00:20:54.540Exactly.
00:20:54.540 -->
00:20:55.540Right.
00:20:55.540 -->
00:20:56.540Yeah.
00:20:56.540 -->
00:20:57.540You don't have to, you don't have to do a lot of stuff.
00:20:57.540 -->
00:20:58.540Okay.
00:20:58.540 -->
00:21:00.540Like the garbage collection cycles that happen over time, right?
00:21:00.540 -->
00:21:01.540Yeah.
00:21:01.540 -->
00:21:04.540These things will just be excluded from garbage collection entirely.
00:21:04.540 -->
00:21:05.540So that's cool.
00:21:05.540 -->
00:21:10.540So they have some graphs of what happened afterwards and the before and after and on the after in the shared memory.
00:21:10.540 -->
00:21:13.540Well, sorry, the before it went almost to zero.
00:21:13.540 -->
00:21:20.540Like it went from, you know, Y axis with no numbers really high to Y axis low with no numbers.
00:21:20.540 -->
00:21:22.540But I don't know exactly what this is.
00:21:22.540 -->
00:21:33.540Maybe a percent, but like I said, it doesn't really, really say, but after processing as few as 300 requests, it was like a 10th of the original shared memory was left.
00:21:33.540 -->
00:21:39.540And that was it now after it's down to it's 75, 80% still shared, which is pretty excellent.
00:21:39.540 -->
00:21:40.540Okay, cool.
00:21:40.540 -->
00:21:46.540But as you said, this is like one of the internal core things from what I can tell.
00:21:46.540 -->
00:21:47.540Yeah.
00:21:47.540 -->
00:21:58.540They do say that this is foundational work for the per interpreter Gil that six, eight, four, as well as making the global interpreter lock optional and see Python seven or three.
00:21:58.540 -->
00:21:59.540So that's why I'm not going to be able to do that.
00:21:59.540 -->
00:22:00.540And that's why I'm not going to be able to do that.
00:22:00.540 -->
00:22:01.540And that's why I'm not going to be able to do that.
00:22:01.540 -->
00:22:02.540And that's why I'm not going to be able to do that.
00:22:02.540 -->
00:22:03.540And that's why I'm not going to be able to do that.
00:22:03.540 -->
00:22:04.540And that's why I'm not going to be able to do that.
00:22:04.540 -->
00:22:05.540Well, I'm not going to be able to do that.
00:22:05.540 -->
00:22:06.540I'm not going to be able to do that.
00:22:06.540 -->
00:22:07.540I'm not going to be able to do that.
00:22:07.540 -->
00:22:08.540I'm not going to be able to do that.
00:22:08.540 -->
00:22:09.540I'm not going to be able to do that.
00:22:09.540 -->
00:22:10.540I'm not going to be able to do that.
00:22:10.540 -->
00:22:11.540I'm not going to be able to do that.
00:22:11.540 -->
00:22:12.540I'm not going to be able to do that.
00:22:12.540 -->
00:22:13.540I'm not going to be able to do that.
00:22:13.540 -->
00:22:14.540I'm not going to be able to do that.
00:22:14.540 -->
00:22:15.540I'm not going to be able to do that.
00:22:15.540 -->
00:22:16.540I'm not going to be able to do that.
00:22:16.540 -->
00:22:17.540I'm not going to be able to do that.
00:22:17.540 -->
00:22:18.540I'm not going to be able to do that.
00:22:18.540 -->
00:22:19.540I'm not going to be able to do that.
00:22:19.540 -->
00:22:20.540I'm not going to be able to do that.
00:22:20.540 -->
00:22:22.540So that's why it's there to support.
00:22:22.540 -->
00:22:26.540And that's why it's relevant for some of these parallelism peps.
00:22:26.540 -->
00:22:28.540So anyway, pretty cool.
00:22:28.540 -->
00:22:31.540This is coming in 3.12, I guess.
00:22:31.540 -->
00:22:32.540Nice. Cool.
00:22:32.540 -->
00:22:37.540Well, I'd like to talk about something that I don't really think about that much in that
00:22:37.540 -->
00:22:40.540that is doc strings for doc string formats.
00:22:40.540 -->
00:22:47.540And I just ran across this article and I'm covering it partly just as a question to the audience.
00:22:47.540 -->
00:22:54.540So the article is from Scott Robinson and it's called Common Doc String Formats in Python.
00:22:54.540 -->
00:22:58.540And doc strings, people forget what they are.
00:22:58.540 -->
00:23:01.540Like, let's say you have a function called add numbers or something.
00:23:01.540 -->
00:23:06.540You can do, you can really do any kind of quote, but the first string in a function,
00:23:06.540 -->
00:23:09.540if it's not assigned to a variable, is the doc string.
00:23:09.540 -->
00:23:11.540And it's the first element.
00:23:11.540 -->
00:23:16.540Anyway, the first line is a little, it's usually one line.
00:23:16.540 -->
00:23:19.540one line and then maybe a space and then some other stuff.
00:23:19.540 -->
00:23:24.540And there apparently there's several format, common formats of this.
00:23:24.540 -->
00:23:29.540You can also, you can get access to it by the underscore doc attribute of something.
00:23:29.540 -->
00:23:37.540So if you have a, a, a reference to a function, you can say dot dunder doc, and you can see the doc string.
00:23:37.540 -->
00:23:42.540And a lot of like ID is use this to pop up hints and stuff.
00:23:42.540 -->
00:23:51.540That's one of the reasons why you want to have like the first, at least the first line be an explanation that is good for somebody to see if it pops up on them and stuff.
00:23:51.540 -->
00:23:54.540So anyway, which formats should this be?
00:23:54.540 -->
00:23:57.540So it covers a handful of different formats.
00:23:57.540 -->
00:24:02.540There's a restructured, restructured text doc stream format.
00:24:02.540 -->
00:24:08.540So you've got all this like descriptions of parameters and the types and stuff.
00:24:08.540 -->
00:24:10.540this is scary looking to me.
00:24:10.540 -->
00:24:15.540there's the, the, let's go through next, Google doc stream format.
00:24:15.540 -->
00:24:18.540This one makes a little more sense, but again, I don't know.
00:24:18.540 -->
00:24:21.540it says, and it talks about the different parameters.
00:24:21.540 -->
00:24:26.540And if, if you really have to describe them, this is probably one of my favorites is what looks pretty good.
00:24:26.540 -->
00:24:27.540return.
00:24:27.540 -->
00:24:30.540What, what, what, what, what is the information that it returns?
00:24:30.540 -->
00:24:36.540what are the arguments and why some like one liner explanations, not too bad.
00:24:36.540 -->
00:24:39.540There's a numpy scipy doc format.
00:24:39.540 -->
00:24:40.540This is also pretty clear.
00:24:40.540 -->
00:24:44.540maybe a little, let's compare the two.
00:24:44.540 -->
00:24:50.540I guess this is it got an extra line because you're doing the underscore line, which is, I guess.
00:24:50.540 -->
00:24:51.540Okay.
00:24:51.540 -->
00:24:53.540It looks sort of, I don't know.
00:24:53.540 -->
00:24:58.540This is a lot of space, but I would, I'm just curious if people are really using this.
00:24:58.540 -->
00:25:08.540Looking at this, I can see the benefit of describing if it's not clear, from the name of your function, describing stuff.
00:25:08.540 -->
00:25:09.540And I also like type hints.
00:25:09.540 -->
00:25:13.540So this seems like a great argument for type hints because the types we,
00:25:13.540 -->
00:25:14.540the types would be great.
00:25:14.540 -->
00:25:15.540Just right in the right.
00:25:15.540 -->
00:25:16.540Right.
00:25:16.540 -->
00:25:16.540Right.
00:25:16.540 -->
00:25:17.540Exactly.
00:25:17.540 -->
00:25:18.540The parameters.
00:25:18.540 -->
00:25:25.540and then if you don't have to describe the type, maybe just have variable names that are more clear.
00:25:25.540 -->
00:25:34.540So, I, my personal preference really is, use type hints and then also, have a description.
00:25:34.540 -->
00:25:40.540If you're going to do a doc string and it's not obvious from the name of the function, then have a description of what the function does.
00:25:40.540 -->
00:25:41.540And that's it.
00:25:41.540 -->
00:25:48.540and then if it's unclear to about what really what the stuff is, the behavior of different parameters, then add that.
00:25:48.540 -->
00:25:57.540But, I, again, I'd love to hear back from people, go ahead and, send me a message on, @brianokken at faucet.org.
00:25:57.540 -->
00:25:59.540This worked great last week.
00:25:59.540 -->
00:26:00.540I got some great feedback.
00:26:00.540 -->
00:26:04.540and so I'd love to hear what people are doing for their doc string formats.
00:26:04.540 -->
00:26:06.540Do you, do you use doc string formats, Michael?
00:26:06.540 -->
00:26:09.540I'm familiar with doc string formats and I've played with them.
00:26:09.540 -->
00:26:12.540I like the Google one best, I think, but I'm with you.
00:26:12.540 -->
00:26:16.540Like if you have good variable names, do you need the parameter information?
00:26:16.540 -->
00:26:19.540If you use type hints, do you need the parameter information to say the type?
00:26:19.540 -->
00:26:23.540If you have a return declaration with a type, do you need to have the returns?
00:26:23.540 -->
00:26:31.540The function has a good name, like get user, you know, area angle bracket, optional user, like, oh, well, it returns a user or it returns none.
00:26:31.540 -->
00:26:33.540How much more do you need to say about what it returns?
00:26:33.540 -->
00:26:34.540You know?
00:26:34.540 -->
00:26:34.540Right.
00:26:34.540 -->
00:26:49.540Like there's a lot of it's, it's a little bit of a, a case study and yes, you want to be very thorough, but also good naming goes a really long way to like limit the amount of comments and docs you got to put onto a thing.
00:26:49.540 -->
00:26:50.540There are times when it makes sense though.
00:26:50.540 -->
00:26:55.540Like if, you're talking about, range or.
00:26:55.540 -->
00:26:56.540something like that.
00:26:56.540 -->
00:27:00.540is it inclusive of both, both numbers?
00:27:00.540 -->
00:27:05.540and if I say one to 10, do I get one, two, three, four up to 10 or I get one, two, three, four up to nine.
00:27:05.540 -->
00:27:05.540Right.
00:27:05.540 -->
00:27:12.540Like those, those situations where you might need to say the non-inclusive upper bound of the rain.
00:27:12.540 -->
00:27:13.540I don't know, whatever.
00:27:13.540 -->
00:27:14.540Something like that.
00:27:14.540 -->
00:27:14.540Right.
00:27:14.540 -->
00:27:15.540Yeah.
00:27:15.540 -->
00:27:15.540Yeah.
00:27:15.540 -->
00:27:19.540I do like, an explanation of what's returned though.
00:27:19.540 -->
00:27:20.540often it's not obvious.
00:27:20.540 -->
00:27:31.540and it's, even if you are doing a type hint and you can get the type of what's returned, what's the meaning of what's returned is if that's not obvious, please put that in a doc string.
00:27:31.540 -->
00:27:32.540But yeah, anyway, cool.
00:27:32.540 -->
00:27:35.540I wonder, I don't, I, this is an honest question.
00:27:35.540 -->
00:27:41.540I have no idea if you express it in any of this documentation or if the editors consume it.
00:27:41.540 -->
00:27:48.540But what would be really awesome is if there was a way to express all possible exception types and the entire call stack, right?
00:27:48.540 -->
00:27:57.540Like you could get a value error, you could get a database connection error, or you could get a uniqueness constraint exception with any of those three.
00:27:57.540 -->
00:28:00.540Then you could have editors where you just hit like alt enter, right?
00:28:00.540 -->
00:28:02.540The error handling goes, bam, bam, bam.
00:28:02.540 -->
00:28:05.540Here's the three types of things you might catch.
00:28:05.540 -->
00:28:05.540Right.
00:28:05.540 -->
00:28:06.540That would be awesome.
00:28:06.540 -->
00:28:11.540But I don't know if you can express the possible range of exceptions in there or not.
00:28:11.540 -->
00:28:13.540Or unless you've, yeah.
00:28:13.540 -->
00:28:17.540And especially if you're calling any extra functions within, within a function.
00:28:17.540 -->
00:28:18.540Yeah.
00:28:18.540 -->
00:28:21.540You don't know if it's going to raise an exception possibly, but.
00:28:21.540 -->
00:28:22.540Possibly.
00:28:22.540 -->
00:28:23.540Yeah.
00:28:23.540 -->
00:28:28.540Anyway, that's something I would see actually really useful there that you don't express in like the type information or the name or any of those things.
00:28:28.540 -->
00:28:29.540Yeah.
00:28:29.540 -->
00:28:30.540Cool.
00:28:30.540 -->
00:28:31.540Yeah.
00:28:31.540 -->
00:28:32.540Cool.
00:28:32.540 -->
00:28:33.540Well, those are our items.
00:28:33.540 -->
00:28:34.540Michael, do you have any extras for us?
00:28:34.540 -->
00:28:37.540I have an extra for you in particular.
00:28:37.540 -->
00:28:38.540How about that?
00:28:38.540 -->
00:28:39.540Okay.
00:28:39.540 -->
00:28:40.540Let's start with that one then.
00:28:40.540 -->
00:28:44.540So last week you asked about GitHub releases.
00:28:44.540 -->
00:28:45.540Who uses these?
00:28:45.540 -->
00:28:46.540Should I be bothered?
00:28:46.540 -->
00:28:47.540Yeah.
00:28:47.540 -->
00:28:49.540There's this person that seems to be telling everyone on GitHub.
00:28:49.540 -->
00:28:51.540They should use releases if they're not.
00:28:51.540 -->
00:28:52.540Do I care?
00:28:52.540 -->
00:28:58.540And Rhett Turnbull, who's been on talk Python to talk about building Mac apps or with Python.
00:28:58.540 -->
00:29:01.540GitHub said there said GitHub releases questions.
00:29:01.540 -->
00:29:06.540I use them and I like them so people can subscribe to be notified of new releases.
00:29:06.540 -->
00:29:10.540I use GH, the GitHub command line.
00:29:10.540 -->
00:29:14.540GitHub release create to create one of the command line every time I pushed up IPI.
00:29:14.540 -->
00:29:18.540I'm sure this can be done as an action, but I don't push that often.
00:29:18.540 -->
00:29:19.540So it's fine with me.
00:29:19.540 -->
00:29:21.540Anyway, there's some feedback for you.
00:29:21.540 -->
00:29:22.540Thanks.
00:29:22.540 -->
00:29:27.540Yeah, I actually got quite a few people reaching out and I really appreciate it.
00:29:27.540 -->
00:29:38.540And it did convince me that I'm going to start trying to figure it out using GitHub releases, but I also want to make sure that it's automated as much as possible.
00:29:38.540 -->
00:29:40.540I don't want to add redundant work just for the heck of it.
00:29:40.540 -->
00:29:45.540So you're going to set up some automation to go around and tell everyone on GitHub who doesn't have releases going yet?
00:29:45.540 -->
00:29:46.540No.
00:29:46.540 -->
00:29:47.540They should do releases.
00:29:47.540 -->
00:29:50.540Think of all the contributor badges you're going to get.
00:29:50.540 -->
00:29:52.540Yeah.
00:29:52.540 -->
00:29:53.540I'm just kidding.
00:29:53.540 -->
00:29:57.540All right.
00:29:57.540 -->
00:29:58.540Let's talk about one more thing.
00:29:58.540 -->
00:30:09.540We've heard about IPI issues where people are uploading malicious packages and a lot of times it's crypto kitties and other idiots who are doing that or researchers to like just prove a concept that it's not going to be.
00:30:09.540 -->
00:30:10.540Prove of concept that it can be done.
00:30:10.540 -->
00:30:14.540But Lazarus hackers who are I'm pretty sure.
00:30:14.540 -->
00:30:14.540Yeah.
00:30:14.540 -->
00:30:25.540North Korean state sponsored hacking group is uploaded a fake VMware VM connect library targeting it professionals.
00:30:25.540 -->
00:30:29.540So it only had 237 downloads.
00:30:29.540 -->
00:30:38.540But when you start to think about state actor hacking level of stuff getting installed onto your machine, that's like a at minimum format.
00:30:38.540 -->
00:30:41.540The OS maybe just throw it in the trash.
00:30:41.540 -->
00:30:42.540I don't know.
00:30:42.540 -->
00:30:44.540It's like pretty bad level of being infected.
00:30:44.540 -->
00:30:45.540So I don't know.
00:30:45.540 -->
00:30:47.540That's I have no action or further thoughts.
00:30:47.540 -->
00:30:49.540Just like a, Hey, that's worth checking out.
00:30:49.540 -->
00:30:50.540Yeah.
00:30:50.540 -->
00:30:54.540And maybe we do need to care about our, our, you know, pipeline and whatever.
00:30:54.540 -->
00:31:01.540But yeah, the supply supply chain, but we do have the new security person, Mike, that was hired.
00:31:01.540 -->
00:31:02.540Right.
00:31:02.540 -->
00:31:03.540So that's excellent.
00:31:03.540 -->
00:31:04.540Yes.
00:31:04.540 -->
00:31:05.540Yeah.
00:31:05.540 -->
00:31:06.540He was in the audience.
00:31:06.540 -->
00:31:07.540So that was great.
00:31:07.540 -->
00:31:08.540I believe it was Mike.
00:31:08.540 -->
00:31:09.540Right.
00:31:09.540 -->
00:31:10.540Hopefully I got the name, right?
00:31:10.540 -->
00:31:11.540Yeah.
00:31:11.540 -->
00:31:12.540Over to you.
00:31:12.540 -->
00:31:13.540That's what I got.
00:31:13.540 -->
00:31:20.540It's actually this, the, I don't know how to pronounce that J and Y J and Y, on PI, the PI bytes slack.
00:31:20.540 -->
00:31:26.540we were, talking about using, talking about using TRS 80 computers.
00:31:26.540 -->
00:31:35.540And I said, Hey, I remember typing in lunar lander on my TRS 80 way back when, copied it out of the back of a magazine.
00:31:35.540 -->
00:31:41.540And he's, he said, Oh, I've got a copy, copy of, of, lunar lander that works on Python.
00:31:41.540 -->
00:31:42.540I'm like, Oh, I want to try it.
00:31:42.540 -->
00:31:48.540And, and I still can't, I'm going to get back to him, but, I can't get his to work.
00:31:48.540 -->
00:31:51.540And then I looked around and there was this other cool one.
00:31:51.540 -->
00:31:54.540lunar lander Python.
00:31:54.540 -->
00:32:01.540I found that's a four years old and apparently it was done as part of a fundamentals of computing course.
00:32:01.540 -->
00:32:03.540which is, which is pretty impressive.
00:32:03.540 -->
00:32:06.540I couldn't get it to work, but their website looks great.
00:32:06.540 -->
00:32:08.540So they have a website with it.
00:32:08.540 -->
00:32:13.540You got attached to it with, with like a screenshots and it shows good fonts too.
00:32:13.540 -->
00:32:14.540Yeah.
00:32:14.540 -->
00:32:15.540Yeah.
00:32:15.540 -->
00:32:18.540And it looks exactly like the lunar lander that I typed into my TRS 80.
00:32:18.540 -->
00:32:20.540So I'm pretty excited about that.
00:32:20.540 -->
00:32:22.540anyway, but I can't get that to work either.
00:32:22.540 -->
00:32:32.540So if anybody's got like a lunar lander, copy or something that works on, works with modern Python, I would love to, to play with it.
00:32:32.540 -->
00:32:35.540I also want to like hack with it with my daughter and stuff.
00:32:35.540 -->
00:32:40.540So anyway, that's the only extra thing I got is, bring on the lunar lander.
00:32:40.540 -->
00:32:41.540That's really cool.
00:32:41.540 -->
00:32:42.540I like it.
00:32:42.540 -->
00:32:43.540Yeah.
00:32:43.540 -->
00:32:44.540Mike, Mike Felder is here.
00:32:44.540 -->
00:32:45.540Fidel is here.
00:32:45.540 -->
00:32:50.540the security guy and people are thinking him and stuff for all the security work.
00:32:50.540 -->
00:32:53.540So just getting started, but yeah, it's, it's not an easy job.
00:32:53.540 -->
00:32:54.540I'm sure.
00:32:54.540 -->
00:32:55.540Yeah.
00:32:55.540 -->
00:32:56.540And we're pretty excited.
00:32:56.540 -->
00:32:58.540I can't think of a better person to do this job.
00:32:58.540 -->
00:32:59.540So indeed.
00:32:59.540 -->
00:33:01.540So shall we play some bingo?
00:33:01.540 -->
00:33:02.540Sure.
00:33:02.540 -->
00:33:03.540All right.
00:33:03.540 -->
00:33:04.540This is our joke.
00:33:04.540 -->
00:33:05.540Program or bingo.
00:33:05.540 -->
00:33:06.540I love it.
00:33:06.540 -->
00:33:07.540So, you know, bingo works.
00:33:07.540 -->
00:33:10.540Everybody gets a different card with different options.
00:33:10.540 -->
00:33:16.540Typically it's numbers, but in this case it's program or actions or statements you call out or have happened.
00:33:16.540 -->
00:33:23.540And as they get called out, you mark them off and whoever completes a row or column or I dunno, something diagonal.
00:33:23.540 -->
00:33:25.540I don't play that much bingo, but you win.
00:33:25.540 -->
00:33:26.540Right.
00:33:26.540 -->
00:33:29.540And so this is, this is a possible program or bingo card.
00:33:29.540 -->
00:33:32.540We should come up with one, a whole bunch of them.
00:33:32.540 -->
00:33:34.540So I'll just read you some of the options out of this card.
00:33:34.540 -->
00:33:35.540Okay.
00:33:35.540 -->
00:33:36.540Ryan.
00:33:36.540 -->
00:33:39.540So we've got number one written code without comments.
00:33:39.540 -->
00:33:43.540Everybody could check that one off for all of the C inspired language.
00:33:43.540 -->
00:33:46.540People forgot a semi-colon at the end of a line.
00:33:46.540 -->
00:33:47.540That's good.
00:33:47.540 -->
00:33:51.540I can certainly relate with number three, close 12 tabs after fixing an issue.
00:33:51.540 -->
00:33:52.540Oh yeah.
00:33:52.540 -->
00:33:53.540Oh yeah.
00:33:53.540 -->
00:33:54.540Also related.
00:33:54.540 -->
00:33:57.540Number four, 20 warnings, zero errors.
00:33:57.540 -->
00:33:59.540Works on my machine, man.
00:33:59.540 -->
00:34:00.540Yeah, exactly.
00:34:00.540 -->
00:34:02.540The number five is program.
00:34:02.540 -->
00:34:04.540Didn't run on someone else's computer.
00:34:04.540 -->
00:34:05.540Yeah.
00:34:05.540 -->
00:34:08.540And instantiation of the works on my machine problem.
00:34:08.540 -->
00:34:11.540And then this number six to do list greater than completed tasks.
00:34:11.540 -->
00:34:13.540Number seven copied code from stack overflow.
00:34:13.540 -->
00:34:15.540I'm pretty sure we can all check that one off.
00:34:15.540 -->
00:34:17.540Close program without saving it.
00:34:17.540 -->
00:34:18.540Okay.
00:34:18.540 -->
00:34:21.540Number nine, ask to fix a laptop because you're a programmer.
00:34:21.540 -->
00:34:22.540I have a problem with my computer.
00:34:22.540 -->
00:34:24.540Like, please don't, please don't.
00:34:24.540 -->
00:34:26.540Number 10 turned your bug into a feature.
00:34:26.540 -->
00:34:29.54011 deleted block of code and regretted it later.
00:34:29.540 -->
00:34:32.540Finally learned a new programming language, but never used it.
00:34:32.540 -->
00:34:33.540Hello TypeScript.
00:34:33.540 -->
00:34:35.540We could come up with so many of these.
00:34:35.540 -->
00:34:36.540We should, we should totally do.
00:34:36.540 -->
00:34:37.540We should do more.
00:34:37.540 -->
00:34:38.540So good.
00:34:38.540 -->
00:34:39.540Aren't they?
00:34:39.540 -->
00:34:40.540You can just go on and on.
00:34:40.540 -->
00:34:41.540Yeah.
00:34:41.540 -->
00:34:42.540Yeah.
00:34:42.540 -->
00:34:47.540You can do a backup copy of your code repository, even though it's like a hub.
00:34:47.540 -->
00:34:48.540Yeah.
00:34:48.540 -->
00:34:50.540Zip is my source control.
00:34:50.540 -->
00:34:51.540Yeah.
00:34:51.540 -->
00:34:57.540And then the, the, the, there's usually a free one in the middle that could just be a need
00:34:57.540 -->
00:34:59.540to need to update pip.
00:34:59.540 -->
00:35:01.540That's exactly.
00:35:01.540 -->
00:35:02.540Pip is out of date.
00:35:02.540 -->
00:35:03.540Yeah.
00:35:03.540 -->
00:35:04.540Awesome.
00:35:04.540 -->
00:35:11.540Well, as usual, pleasure to talk with you, Michael, and thank you so much Sentry for sponsoring
00:35:11.540 -->
00:35:12.540this episode.
00:35:12.540 -->
00:35:16.540Again, everybody check out Sentry and go to, what was that link again?
00:35:16.540 -->
00:35:17.540Pythonbytes.fm/sentry.
00:35:17.540 -->
00:35:18.540Thanks Brian.
00:35:18.540 -->
00:35:19.540Thank you.
00:35:19.540 -->
00:35:20.540Bye.
00:35:20.540 -->
00:35:21.540See y'all.
00:35:21.540 -->
00:35:22.240Thank you. Bye.