Brought to you by Talk Python Courses and Six Feet Up consulting

#498: A Tiny Episode

Published Tue, Sep 29, 2026, recorded Tue, Sep 29, 2026
0:00
00:33:17
Watch this episode on YouTube
Play on YouTube
Watch the live stream replay

About the show

Sponsored by us! Support our work through:

Connect with the hosts

Join us on YouTube at pythonbytes.fm/live to be part of the audience. Usually Tuesday at 7am PT. Older video versions available there too.

Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to our friends of the show list, we'll never share it.

Calvin #1: MemTensor / MemoryOS PyPI package hijacked via a malicious build backend

  • On Sept 23 an attacker published backdoored MemoryOS 2.0.34 on PyPI and three bad versions (0.1.21, 0.1.23, 0.1.25) of MemTensor's OpenClaw plugin on npm. PyPI had no clean release that day, so 2.0.34 was the newest.
  • They pushed commits to MemTensor's own GitHub Actions release pipelines. On PyPI that was a custom Poetry build backend, and on npm a tweaked validation script. Both used BASH_ENV to hand the publish token to the attacker before the real publish ran. SafeDep couldn't confirm how the attacker got push access.
  • Runs on import, not install: A Go implant called sckit starts when the library loads, so --ignore-scripts won't save you.
  • It harvests credentials from your home directory (npm and PyPI tokens, GitHub tokens, SSH keys, cloud CLI tokens, .env files) and sends them to skyleen[.]fr servers.
  • It's a worm: It uses stolen tokens to copy itself into other repos and packages, so the victim list could grow.
  • If you installed it: Downgrade to MemoryOS 2.0.33 (plugin 0.1.20) and rotate every credential reachable from $HOME. Also kill any running sckit stage0 process and check repos you can push to for a stray runtime-update.yml workflow or .sckit/ directory.

Michael #2: TinyMongo

  • Want to use a MongoDB data interface, but swap out the storage engine?
    • Memory for testing/caching
    • JSON/TinyDB simple JSON files
    • SQLite for durable, high-perf reads with WAL
    • SQLIte shared for high write apps
    • DuckDB + Parquet for analytics apps
    • Postgres + MariaDB for multi-machine client/server
  • Great for teaching, examples, and simple deployments
  • Amazing story of paired AI development
    • Will completely run talkpython.fm after weeks of shared work together (in SQLite mode).

Calvin #3: Jev: what to know

  • What it is: Jev is a model from TypeSafe AI that answers with typed results (yes/no probabilities, scores, picks from your options) instead of prose. Real Python published a hands-on tutorial on 2026-09-24 and the buzz on hacker news is almost deafening.
  • It's proprietary: Jev is a hosted, closed-weight model. There are no weights to download and no self-hosting. Everything called "open Jev" is an independent reimplementation, not TypeSafe's model.
  • Your data leaves your machine: Every call sends your input text to a third-party API. In the tutorial that path goes through OpenRouter to TypeSafe. Think twice before sending customer messages, tickets or anything sensitive.
  • Cost and stability are open questions: The tutorial calls Jev "cheap, but not free" and says it's fast and cheap "at the moment." It also says whether that stays true is "something to keep an eye on."
  • Credit to Real Python: It's a good, practical intro. It shows the Noul, Score and Choice primitives, and its point that instruction wording matters more than thresholds is useful advice for any model. The tutorial itself says similar results are possible with a well-prompted LLM.
  • Open options to look at instead:
    • JevK5 (https://github.com/allebee/jevk5): Apache-2.0 weights and code, 4B or 9B parameters, and it accepts TypeSafe-style requests.
    • SemIf, formerly OpenJev (https://github.com/TheoLeeCJ/openjev): MIT-licensed, small models, and it can run CPU-only.
    • openjev-sglang (https://github.com/ekzhang/openjev-sglang): a Jev-compatible endpoint running Qwen3.6-35B-A3B, but no license is stated, so check before commercial use.
  • The catch: These copy Jev's interface, not its model or training. Results will differ, and I haven't run any of them. Benchmarks are self-reported, and JevK5 is English-only.

Michael #4: One innocent dict read makes attribute access permanently slower

Timofei Ivankov benchmarks a CPython internals surprise: since 3.11, attribute access skips the instance dict entirely. A specialized opcode reads the attri.bute at a fixed byte offset in the object's inline values array. Read obj.__dict__ once, though, and the dict gets materialized, the object loses that specialized path for the rest of its life, and a million-iteration loop goes from 33 ms to 51 ms on CPython 3.14. vars() and copy.copy() trigger the same thing, so a debugging print or a shallow copy in code touching your hot objects quietly makes every later attribute access roughly 1.5x slower.

  • The slowdown is permanent and nothing about it looks like a performance decision: ordinary code far from the hot loop can trigger it, and the function that gets slower never changes.
  • Materializing dict produces a split table, and the LOAD_ATTR_WITH_HINT fallback declines split tables, so the object ends up with no specialization at all
  • vars(), 'x' in o.dict, and copy.copy() all materialize it; copy.copy is the realistic trap since nobody treats a shallow copy as a performance decision
  • slots instances read attributes at exactly the same speed and cannot fall into the trap since there is no dict to materialize
  • On the free-threaded build both effects grow: atomic incref on reads plus an object lock on writes push the penalty from 17.6 to 25.4 ns
  • Credit: this item was surfaced by the PyCoder's Weekly newsletter

Extras

Calvin:

  • whatsnewt - a TUI text adventure through what's new in Python 3.15; playful but niche.

Joke: Shipping a button in 2026…

Episode Transcript

Collapse transcript

00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your buds.

00:05 This is unbelievably episode 498 coming up on episode 500,

00:10 recorded September 29th, 2026.

00:13 I'm Michael Kennedy.

00:14 And I'm Calvin Hendrix Parker.

00:15 Check us out on all the socials.

00:18 We put all the links if you want to interact with us there at the top of the show.

00:21 This episode is brought to you by us.

00:23 So be sure to check out Six Feet Up if you have an amazing,

00:26 you would like, People who've done a lot of problem solving in the Python space for many, many years.

00:31 Reach out to Calvin and learn about Python.

00:34 Got some courses over at Talk Python.

00:36 They had new things coming.

00:37 Nothing to announce yet, but a lot of work has been going lately on a new thing over there.

00:43 So I'm very excited.

00:44 Check out the newsletter.

00:45 Just visit the homepage.

00:46 Click newsletter.

00:47 We got lots of cool things to send to you there.

00:49 And with that, you have scary news.

00:52 Are you going to scare us?

00:53 Hopefully not too much.

00:54 It's not quite October, although I do see lots and lots of decorations out in the stores these days for Halloween.

01:01 But there is unfortunately...

01:02 It's like a jump scare, right?

01:03 A little bit, yeah.

01:04 There's been a supply chain attack and there's no shortage of these over the last couple of years,

01:10 probably due to the proliferation of AI and the tools that attackers can use to build these different exploits.

01:15 This one is around MemTensor and MemoryOS.

01:18 So some people may not be affected by this, but I think the real true story here is to follow

01:25 how it's done and to protect your CI pipelines ultimately.

01:29 So on September 23rd, an attacker published a backdoor into MemoryOS.

01:34 So if you're using OpenClaw or if you have installed a MemoryOS

01:38 skill into your agentic harness, you could be susceptible to this.

01:43 So look for these various versions 0.1.21 on the plugin there's or that's the bad versions and 0.1.23 and 25 and then the

01:53 memory os version 0.2 no sorry 2.0.34 the newest one that was released last week those are

02:02 problematic they are going to launch a go process in the background even working around like the

02:10 import path stuff won't get around this because it'll launch this what looks like a legitimate

02:16 named thing, S-C-K-I-T.

02:18 You may misview it as scikit, but it's actually S-C-K-I-T. It's a Go

02:23 library that loads in the background. And what it does, scours your system for credentials,

02:27 posts them to a command and control server, kind of the standard play there.

02:30 And then it attempts to inject itself into other CI pipelines as a worm.

02:35 So this one's not just an exploit that's and exfiltrate your credentials,

02:40 they're actually looking to exfiltrate them, exploit them,

02:43 and then turn them into a worm to gather more and more of them, whatever projects you're

02:47 basically working on. So it traverses your home directory looking for PyPI tokens,

02:51 GitHub tokens, you name it,

02:54 and then sends them to a nefarious server someplace.

02:58 Those then locate itself and try and go again.

03:00 So if you are on these various versions of these various packages,

03:04 make sure downgrade to the safe versions,

03:08 the 2.0.33 of memory OS and 0.1.20 of the plugin and rotate

03:14 every possible credential you have that's reachable from your home directory.

03:18 Make sure you kill any SCKIT processes that are running because that is where it is talking to the command and control

03:26 server. So unfortunate news, no fun.

03:30 The write-up from SafeDep, which is linked to from the show

03:33 notes here has a really good take on basically how they got in there's a couple spots where they

03:39 don't know how they got some of the tokens they assume maybe social engineering or a leak of a

03:45 github token someplace but the various projects have put in some fixes into their ci pipelines to

03:52 hopefully prevent future attacks like this from happening and you probably could learn something

03:56 a thing or two for your own ci pipelines to harden your processes as well that is a jump scare

04:02 Yeah, less than fun.

04:04 Less than fun.

04:04 No one loves to hear that news on a Tuesday morning.

04:08 But I think everyone needs to be aware and protect their CI pipelines.

04:11 Because again, this is how they got in.

04:13 They basically used the GitHub Actions pipelines.

04:16 Not that GitHub Actions is in itself vulnerable to these things.

04:20 It just enables these kinds of things.

04:23 It's the other practices that are what made this possible.

04:26 I remember how scary it was that there were worms on the internet,

04:30 especially back when firewalls, what's a firewall?

04:33 That's what a company, that's what like giant companies do.

04:36 Yeah.

04:37 So there's, on the webpage,

04:38 they also link into the issue from the MemoryOS folks

04:43 and the OpenClub plugin repositories.

04:46 Again, I think it's a good responsible write-up

04:48 of what happened.

04:50 The repositories themselves don't have a lot of information on them,

04:53 but this article does.

04:55 Yeah.

04:55 It's just, it's scary, you know, having very cool what we can do as developers,

04:59 but at the same time, the responsibility of, oh my gosh,

05:03 something got through and it didn't just affect me.

05:06 It didn't just affect my users, but everybody who might have used something I created

05:10 now, it's like taking over all of their music.

05:12 Oh my gosh, that's a serious fire.

05:15 So. I mean, it's a common complaint. Like, why can't we just dump files into a web route like we used to and

05:19 deploy CGI applications?

05:22 Because that was very dangerous. We just didn't know it yet because of

05:25 the various vectors for exploit and attack.

05:29 Deploying software safely requires a thoughtful

05:32 and intentional process.

05:33 Yeah.

05:34 And to some degree, safety and isolation of your computer that makes

05:38 that software.

05:39 Very true.

05:39 So yeah, pay attention to a lot of the sandboxing and containers and

05:43 things like that that help you with those processes.

05:45 Would you say you got to pay attention to like tiny little issues?

05:48 Tiny things could, you know,

05:50 be an interesting way to go.

05:52 I want to talk about Tiny Mongo.

05:54 Are you familiar with this?

05:55 I am not, actually.

05:56 I'm quite curious.

05:57 My son actually was in a MongoDB hackathon over the weekend,

05:59 so maybe he might be interested in this.

06:00 This would have been absolutely awesome for that.

06:03 I mean, maybe if it was about MongoDB, no.

06:06 But I've covered this before, actually.

06:08 Gives me a chance to highlight a cool little search feature of our, if you search them,

06:12 you can actually say, only show me the episodes that exactly covered this.

06:16 So way back in 2017, nine years ago,

06:19 we covered Tiny Mongo.

06:21 So the guy behind this, Steven, I had posted way back when I had posted some issue saying,

06:28 this thing is cool.

06:29 So let me tell you what TinyMongo is, and then I'll tell you why it's back on the show after

06:33 nine years.

06:34 So TinyMongo is what SQLite is to Postgres.

06:39 TinyMongo is to MongoDB.

06:40 Okay.

06:41 In process, local file, but it goes,

06:44 I don't know, it goes a little farther than SQLite, as you'll see,

06:47 in some really interesting ways.

06:49 but it uses well-known durable backends for the most part.

06:53 So you can choose a really well-known, well-tested, well-trusted backend for this.

07:00 But basically think in process, I want something without a server.

07:04 Now, as part of this news item is very, very fast.

07:07 So Stephen looked at this GitHub issue and decided, all right, I'm going to fix it.

07:12 So the issue I filed a while ago was, this is really cool.

07:15 It supports a subset of MongoDB, but not enough.

07:19 Okay.

07:20 So I was using, when I posted the issue, I think I was using MongoEngine.

07:24 When he replied to the issue, I was using, what one was it?

07:27 I was using a Pydantic-based one, Beanie.

07:29 And then by the time he actually got the thing working, I was using just raw MongoDB queries.

07:36 But I said, look, this is cool, but I can't use it with anything based on these ORMs

07:41 because the ORMs have a certain set of startup things they do.

07:45 like ensure these collections exist, ensure this index exists.

07:49 You know, it's like testing different things as just part of the standard setup,

07:53 you know, like it scaffolds the index automatically and stuff.

07:56 And those things weren't working.

07:57 So I said, would you be willing to put in enough structure,

08:01 maybe even if there are no ops, that I could actually run a quote real application on top of tiny Mongo?

08:07 Because there's all sorts of cool reasons you might want this.

08:09 Like if you're doing a tutorial or a workshop, you don't want to have to start out and go now kids,

08:15 The first thing we're going to start is by setting up a network server and securing it.

08:18 Like, no, no, no.

08:19 Yeah, there goes the day.

08:21 You're like, okay, well, we're not doing the workshop anymore,

08:23 right?

08:24 But if you have something like SQLite, you can just say,

08:26 this is the connection string.

08:28 This is the uv pip install command.

08:30 Now let's keep going.

08:32 But it's the same program.

08:33 You just change the connection string basically to get like a real server,

08:38 right?

08:38 Like to switch over to real Mongo or whatever.

08:40 So Stephen took that idea and just totally ran with it.

08:43 and came back to me and said, hey, look, what do I need?

08:48 How about this?

08:49 You know, this last question was asked in the time of AI,

08:53 the time of really smart coding agents, right?

08:55 Just the before times and there's now.

08:57 Exactly.

08:58 So I think this actually represents a really super interesting collaboration

09:03 between me and Stephen.

09:05 So, Stephen, sorry.

09:07 So he said, well, what do I need?

09:08 I said, well, how about this?

09:09 why don't I just see if I can get Talk Python to run on top of this,

09:13 just as it is?

09:14 And I just said, all right, well, I'm going to take Mongo out.

09:18 I'm going to stop talking to the real Mongo.

09:20 And I'm going to put Tiny Mongo in and get it to run.

09:22 And there were all these issues like, yeah, it technically works,

09:25 but this thing is a thousand times slower in this way.

09:27 It's like, oh.

09:28 Interesting.

09:28 I wasn't expecting that.

09:30 Yeah.

09:30 Well, it almost worked.

09:32 Once we got it working, it was like, okay, now it works.

09:33 But it's like, these five things are insanely slow.

09:36 this type of query is not actually supported or limit doesn't actually limit it in the DB.

09:41 It pulls it all back and then it like limits it in memory.

09:43 You know, those kind of weird little, like it's fine.

09:46 But if you've got hundreds of thousands or millions of records,

09:49 you're like, no, this

09:50 is not going to fly.

09:51 This is out of control.

09:53 So we went through all those and now it's like really quite close to MongoDB performance.

09:59 Michael, would you recommend this for production usage or is it still more for exploring,

10:03 playing, teaching?

10:06 I would recommend it.

10:07 I think it's safe.

10:08 I'll tell you why.

10:09 I'll tell you why.

10:09 I think it's, I would recommend it.

10:11 If you would consider SQLite as your backend for production,

10:15 which I think actually is viable.

10:17 Yeah, it's very safe.

10:17 I think that's very safe.

10:18 It has restrictions on like parallel writers and stuff,

10:21 but I do think it's quite safe.

10:23 I agree.

10:24 If you would consider SQLite as a backend, then I think this, I would recommend this as a backend.

10:28 Yes, as we'll see.

10:30 Okay, so let's go down.

10:33 I mean, what's cool about it is the way you write is you just like write regular code

10:36 and you just import tinymongo as PyMongo, which is the standard way of creating a thing.

10:41 And you give it a connection string sort of deal that is like this file instead of this database.

10:47 And then you just write regular queries against it, right?

10:49 So what's really neat down here somewhere is all the different backends it has.

10:55 So like SQLite, it might maybe even uses the SQLite version for this,

11:00 I'm not sure, is you have an in-memory version.

11:02 So it never even writes the disk.

11:03 Like I'm doing unit tests or I'm just firing up this code,

11:08 this data, I'm going to think about it and then throw it away.

11:10 Right.

11:10 That's pretty cool.

11:11 It has this JSON backend, which is it's sort of default way.

11:15 I haven't done it.

11:16 This was not really able to totally solve the Talk Python runtime, I think, or it was like too slow or something.

11:22 But switching to SQLite.

11:23 So basically it uses SQLite with all of the SQLite transactions,

11:28 write ahead log stuff and all that kind of stuff.

11:31 And that's a really good production story.

11:33 And then look at this, Calvin, sharded SQLite.

11:35 I'm more curious about the next one, which is DuckDB.

11:38 Yeah, so you're going to ask.

11:40 Yeah, because there you've got real JSON support possibly.

11:43 Yeah, Stefan is a huge fan of DuckDB and those kinds of things.

11:47 So this is DuckDB and Parquet files as the backend, which is pretty interesting.

11:52 So if you're doing data science-y things and you were doing Mongo type of queries,

11:56 this is the way.

11:57 This is a pretty good one.

11:58 And then also it has a way to say like, you know, point that over at Postgres and MariaDB

12:04 if you'd rather have something that's kind of like Mongo,

12:06 but you don't actually run Mongo.

12:08 I mean, you literally talk to it as if it was Mongo.

12:10 Yeah, I'm unsure about that use case.

12:12 I think it might just run Mongo.

12:13 I would too.

12:14 I would totally too.

12:15 But I think the SQLite one, it's really good.

12:18 We got it really, really dialed.

12:20 So I actually linked to one of the issues.

12:22 There's a bunch of issues over there.

12:24 So I had some issues.

12:26 Steven added him and sort of referenced me.

12:27 And we just went back and forth.

12:29 And I would say, hey, Claude.

12:31 I'd open up, I had a branch for Talk Python.

12:34 I'd open it up and said, hey, Claude, check out this GitHub issue.

12:37 Can you try to implement it on top of this thing?

12:40 And he would do it and say, well, I found all these issues.

12:42 I said, okay, file some issues.

12:43 Then Steven would have Codex look at it, fix it up, reply.

12:48 And we would just pass it back and forth.

12:51 And the reason that's interesting is I'm not giving him the Talk Python code base.

12:55 And I ended up running on Talk Python training, which is like 300,000 lines of Python code

12:59 and got it working there as well.

13:01 But I'm not giving him that code.

13:02 But he was able to literally prototype both from a performance and correctness perspective

13:07 running on both those code bases by just bouncing back and forth.

13:11 Well, my AI did your spike and it found that it ran like this and this worked and this didn't.

13:17 And so, okay, I fixed this, try it again.

13:19 And we just went back and forth for like over and over for days and got it really, really

13:23 dialed.

13:24 And I thought that was, that itself is worth covering here.

13:26 Yeah, I like that workflow.

13:28 Yeah, yeah, it's very interesting.

13:30 Obviously, my prompts were like, you will not put any proprietary information,

13:35 any secrets, any source code example.

13:37 You will put all generic, you know what I mean?

13:40 But at the same time, it totally worked.

13:41 And it was really cool.

13:44 But I think this is a super interesting thing because until this recent work,

13:49 this version 1.3.1 that got released, There was no SQLite equivalent for MongoDB.

13:54 And now I think there legitimately is.

13:56 It's not 100% coverage, but it's quite high.

13:59 It runs multiple real-time apps.

14:01 Yeah, I like that.

14:02 Well, especially for the education market, being able to teach someone really quickly

14:04 without having to install and serve.

14:07 And that's a huge barrier for a lot of people.

14:09 Yeah.

14:09 It looks really good.

14:10 I'm really excited about it.

14:12 Thank you, Stefan, for doing this work.

14:13 And there might be a follow-up at some point as well.

14:16 And what a great story for open source.

14:18 Yeah, exactly.

14:19 Like a really cool way to get some actual hands-on experience on real projects by sort of ping-ponging GitHub issues back and forth.

14:28 It was crazy.

14:29 Speaking of crazy, I've heard this topic is setting the world on fire.

14:35 Well, and I wanted to bring it to light to get some people some exposure to it.

14:38 If you've not heard of Jev yet, you're probably living under a rock someplace,

14:42 and that's okay.

14:43 But the folks over at RealPython did a tutorial

14:47 of how to get started with Jev in Python.

14:50 For those of you who don't know, Jev is a model from a company called TypeSafe AI

14:55 that answers typed results like yes, no's, probabilities,

14:59 scores, and pick from options instead of you talking with it.

15:03 So you don't chat with Jev.

15:05 You don't come into Jev and say, hey, build me an app or tell me a bear story

15:09 or whatever the thing you may want.

15:11 propose to JEV sets of information, evaluation,

15:16 the kind of result you want. And then JEV can, in parallel,

15:19 evaluate those things, either scoring them, giving them yes-nos.

15:23 I mean, the docs from the tutorial are basically a customer service example where the customer says,

15:29 I've tried contacting support like three times. Can I please get escalated?

15:33 And so then the JEV for that basically is, here's how you know if the person is telling the truth or not. So they have a

15:39 YesNo or TrueFall.

15:40 And there's some custom various data types that go along with it.

15:43 So what's nice is that the real Python article will get you started with Jev.

15:48 So you'll understand the data types.

15:49 You'll understand like what Jev's about, that you can't just chat with it.

15:52 But I think, and the buzz is real.

15:54 Like I've heard tons and tons of people talking about it.

15:57 It looks like the invites are back open again.

15:58 I was actually able to sign up for Jev this morning

16:00 and try it out, but it is proprietary.

16:04 Jev is a hosted closed wait model.

16:07 There are no waits to download.

16:09 There's no self-hosting of this thing.

16:11 Everything called OpenJev is an independent implementation and not TypeSafe's model,

16:18 which means your data leaves your machine.

16:21 So I don't know how much you trust TypeSafe AI.

16:24 I don't know who they are, where they're hosted, what their business models are.

16:28 Obviously, it's not free.

16:29 You have to put a credit card down to use this model and try it out.

16:33 But every call sends your input to the input text you put in there to a third party.

16:38 So be careful, like much like you just mentioned

16:40 how you are sanitizing your inputs for working back and forth on the tiny Mongo project

16:46 with Stefan, be careful what you send into this one

16:48 because you don't control it just as much as you control

16:51 what you send to Anthropic or OpenAI.

16:54 Those are pretty well established companies with a good business model and they seem to be running on,

16:59 you know, credibility and reputation.

17:01 You have to do your research and know what you're gonna be sending over there.

17:05 So think twice before sending customer messages,

17:07 tickets or anything sensitive.

17:08 The other thing is like costs and stability are a question,

17:12 right?

17:12 So basically Jev bills themselves as very cheap and it is very cheap. Like you can,

17:17 and very fast, you can have it sort through.

17:20 I heard someone tell me an example, like look through my inbox of a

17:23 million messages, categorizing them for like needs immediate attention,

17:28 is about a customer, et cetera,

17:30 et cetera.

17:30 And it can build you a table and sort that table in just milliseconds.

17:34 It's that fast.

17:35 I want to give people an option here.

17:37 It's a good practical intro.

17:39 It shows how to use the null, the score, the choice primitives,

17:43 but there are open options out there.

17:44 I know I keep caveating this like episode,

17:47 this, this section of the episode.

17:49 There are some open options to look at instead.

17:52 For example, Jevk5, it's an Apache 2.0 licensed weights and code.

17:58 So that's kind of my front runner right now. I've not tried it,

18:00 but it does accept type safe style requests.

18:04 These are API compatible, but they are not the JEV model. So you're going to get different potential results.

18:09 There's also one called SimF, which was formerly called OpenJEV. I'm sure lots of takedown notices

18:15 came flying back and forth as all these alternatives came out that were also called

18:18 something something JEV.

18:20 Another one's OpenJEVSGLang.

18:22 Again, the catch here is these are not the JEV model. They are close.

18:26 There was actually a really interesting JEV in 25 lines of Python,

18:31 on a little bit tongue in cheek post that also came out about this.

18:35 But what they did here was use the Quinn three model

18:38 and told it to act like Jev.

18:40 And for most things, I think it gave reasonable results,

18:43 but also at the very end, this was a real tongue in cheek post

18:48 kind of poking fun at the hype that is Jev right now.

18:53 So I wanted to put that out there for folks to be just mostly aware of the fact

18:56 that you're sending your data to a proprietary company

18:59 and be careful what you're sending to it totally trust it and have a business agreement with that organization beyond putting your credit

19:06 card into a credit card field.

19:07 So I hope folks are vigilant as they go forth and try these things.

19:11 The hype is real.

19:13 Oh my gosh, you couldn't again move last week without hearing about Jev in some

19:17 meeting and some article and some topic.

19:22 It's a very interesting way and a very interesting usage.

19:24 It's a very, I think it's a great pattern for reducing token spend and usage on other models

19:31 collaboration or combination with other models,

19:33 but you need to understand what it really means

19:35 in action.

19:36 It's a super cool thing.

19:38 You're right. It's absolutely blowing.

19:39 Jev is blowing up.

19:41 I had to watch some YouTube videos this week.

19:44 I'm missing something because there's a lot of this thing I've never heard of going on around and around.

19:49 When you sign up for a Jev account, it makes you take a pop quiz to ask you whether or not you can chat with Jev. I won't give you the

19:56 answer because if you don't know, you shouldn't probably be using Jev.

19:59 If you got to ask, It's not for you.

20:01 Yeah.

20:01 I was going to say that there's never been a time, I think, where we're sending as much detailed information to other companies and other places as the last couple years.

20:14 Be careful out there, folks.

20:16 It's real.

20:18 Yeah.

20:18 But the reason we're doing it is because it's so productive and so useful, right?

20:21 It is.

20:22 I mean, the patterns, I think,

20:24 in looking at some of those open wide options, if you can put in place, again,

20:28 I'll stress, probably why I stressed things last week.

20:30 was around evals.

20:31 Building good evals for your CI pipeline to run against these models,

20:35 whether they're classifiers like JEV or whether they're LLMs like the QIN or other open weights models,

20:41 means you can swap back and forth with confidence.

20:43 And if you can do that, you can use one of these

20:45 open weights models, open source,

20:47 even versions of these models with more confidence on your own

20:50 GPUs. These things will run on even very small CPU,

20:53 GPU.

20:54 I think there was a QIN 306B model that they're using in the parody article that runs on like a raspberry pi you can get those anywhere

21:02 nice but i'm not using Anthropic for something i've been using glm53 flash and that's been

21:08 super super neat but i want to talk about an age of innocence that may be over here this is an

21:12 article i don't typically cover articles i typically more but but it kind of pulls out it highlights a

21:17 really important thing that the reason i pull it up is because it kind of broke my understanding of

21:22 Python performance tips for one particular axis.

21:26 So this is by Timothy Ivankov.

21:30 So cool to write this up.

21:32 I think it might have had a little writing help, but that's okay.

21:35 So here's the headline.

21:36 It's reading Dunderdict once, one time.

21:40 Reading Dunderdict of an object permanently de-optimizes attribute access.

21:46 What?

21:47 Why is that?

21:48 Why is that not good?

21:49 And I was a wonder's point of this comes from PyCoder.

21:51 The permanence of it is the striking bit.

21:54 Permanently, for the rest of that object's life cycle,

21:57 its performance is broken.

21:59 Okay, so here's an old performance tip.

22:02 And I'll tell you the one that I used that I thought was amazing.

22:05 And it was amazing.

22:06 If I have a loop and in this hot, let's call it a hot loop here.

22:09 This is an example.

22:10 A million times around, we're just going to do the same thing.

22:12 Like we're going to say, create an attribute,

22:14 self.value, access self.value in the loop,

22:17 increment plus equals on the self.value.

22:20 Well, traditionally, that would go into the DunderDict, find the value,

22:24 pull that value out, change it, store it back into the DunderDict, right?

22:28 That was the backing store for its fields, which is weird,

22:32 but that's how it worked.

22:33 So here's what you do.

22:34 Instead of doing that interchange over and over and over,

22:37 do it on a local variable.

22:38 Create a value, do all your work on a local variable in the function,

22:43 and then at the end, set the value to the class,

22:46 right?

22:47 Create a value, and then eventually say self.value equals value,

22:49 right?

22:49 Super simple.

22:50 That used to make a big, big difference.

22:53 And now it does still a little bit, does a little bit. So it technically works.

23:00 However, if you do this enough times,

23:03 it turns out that the new specializing adaptive interpreter notices that and it drops the load adder,

23:10 which is the bytecode instruction that reads the field from the dictionary.

23:15 Eventually it drops it and it starts processing it different,

23:19 right?

23:19 And so what it does is it actually starts to look at just,

23:23 well, where in the offset, like a fixed byte offset

23:26 into the object's storage for this, which is like,

23:29 wow, okay, pretty cool.

23:31 So that's, I think, since 13, really interesting.

23:34 And you can see the different aspects.

23:36 It turns out that it's even more significant, this change of the problem they're suggesting or pointing out.

23:43 Is that really a problem?

23:44 It's just breaks in optimization.

23:46 that the breakage is stronger in a free threaded world.

23:49 And the article goes into why.

23:50 So check this out.

23:51 If you just say, like maybe this is like a debugging thing or whatever,

23:54 you just say print dunder dict of the object and then you go have that function run.

23:59 All of a sudden it's 50 milliseconds instead of 30 milliseconds.

24:03 1.5 times slower.

24:04 What do you think?

24:06 It's intense to get down to that level.

24:09 It is, but there's a bunch of little simple things that you're like,

24:13 I could read the fields or I could just say star star dunderdict and do this and that.

24:19 And it turns out that that actually, it didn't used to make any difference,

24:23 but because of the specializing adaptive interpreter,

24:26 now it does, right?

24:28 So like if you just ask vars of an object or if you ask if a field is in the dictionary,

24:34 well, here's the really tricky one, a shallow copy,

24:37 right?

24:37 Like, well, that's a totally reasonable thing.

24:38 I'm going to clone this before I hand it back or something.

24:42 Well, that clone that you did, it can attribute access.

24:45 to access it yeah it makes it 50 slower i've definitely done that mostly when i'm debugging

24:49 or triaging code or kind of walking through the interpreter because it's easy to access i can't

24:55 think of too many times where i would have tried to do it in code you could see how it's a it's an

24:59 easy workaround it's like oh it's just right there i'm going to reach for it yeah exactly so these

25:04 the the first three like are kind of um debugging ones but this last shallow copy this is a

25:08 legitimate thing, right? That you might do.

25:11 And so here's the, this is the part that I didn't get because the world has changed and I haven't been like prototyping everything at that level.

25:20 I'm a big fan of dunder slots.

25:22 It means you can't dynamically add stuff to your class,

25:24 but more importantly, used to mean that this whole dictionary mechanism was no longer used.

25:30 And it basically used an offset into a list that was just in each instance.

25:35 So it honestly made things a lot better in terms of memory and in terms of attribute access was significantly faster.

25:42 Well, apparently slots makes no difference anymore because the specializing adaptive

25:48 interpreter, at least in this use case, right? This is like a,

25:50 I'm accessing the same thing a lot of times, right? It could be, you know, profiling is tricky.

25:55 Performance is tricky, but basically the specializing adaptive interpreter for hot pass slots versus not didn't really matter.

26:04 And I didn't know about slots until I read Luciano's book,

26:07 Fluent Python.

26:08 That's where I discovered that.

26:10 And now you're saying it really doesn't matter anymore because of the new bits in there.

26:14 Yeah, exactly.

26:15 So I believe I might have learned about it as well from Luciano's book.

26:20 So yeah, 3.11 and beyond, there's a lot of the faster CPython thing.

26:25 Changed some of these things.

26:26 And it changed how this, especially with the specialized and adaptive interpreter,

26:30 changed a lot about how this dictionary and access, and that's the whole story,

26:34 slots, dictionary access, optimizing or not optimizing it, and so on. So I thought this was an interesting

26:41 dive into something that's, you know, everyone uses classes,

26:45 objects, even if they're not big OOP folks,

26:48 you still create objects.

26:50 I mean, do you have a number?

26:52 You know what I mean?

26:53 Well, it's just, and it's convenient,

26:55 but I think if you were, again,

26:57 performance debugging and reaging and you ran into this,

27:00 you've been surprised. Yes, I would. I would certainly say

27:03 so. I would say so.

27:04 Michael, would you want an interesting way to find out what's new or what's

27:08 newt in Python?

27:10 So I got this extra here I wanted to share.

27:13 This is cool.

27:14 I've seen this now. I thought I had not seen. I've seen this is cool. This is a dungeon crawler called what's newt.

27:21 And it, but what it does is it runs you through the what's new in Python.

27:24 And this version is specific for 3.15.

27:27 You can't run it with prior versions because it actually uses the features in

27:31 3.15 to check that you've completed the challenge in the dungeon.

27:36 So I've got the dungeon up right here. So I'll just read off real quick. So this one starts off with the first room of the

27:41 interpreter and the one nobody sees.

27:44 Slips of paper are wedged into every crack of the masonry.pth

27:48 files.

27:48 Hundreds of them, each one adding a directory to the path.

27:52 A few begin with the words import.

27:54 And those have scorch marks, rightfully so.

27:57 A brass plaque is bolted to the wall. A new file

28:00 sits on the lectern beneath it, unwritten.

28:03 And so at this point, you have a puzzle,

28:04 which is what runs before your program does.

28:07 And it has a link actually in the terminal.

28:09 That is a hyperlink.

28:11 It's a nice little TUI app.

28:13 And when you click on that, it'll open up the related PEP to basically

28:17 give you a hint for it. So if you want to solve it, you just type solve.

28:20 I'll type solve.

28:23 It'll my butt because it does not have VI key bindings in there. So I had to like use my arrow keys.

28:28 You probably had almost just like a caveman.

28:33 And so based on the PEP 829, it added in the new

28:38 namespace, a callable syntax for bringing in a callable into your PTH file or the new

28:47 sys.path, for example. So they're deprecating the word import.

28:51 And now 315 adds this file format that can only name a callable.

28:55 Here's how you write it. And when you click check,

28:57 it's like solved. A reader can now see what starts up without executing it. The site modules batches every static

29:03 sys.path extension first, and then only runs the startup callable so that a.start file can rely on

29:09 the path being complete.

29:10 Please press enter when you're finished reading.

29:12 And then it takes you into Do you want to go north,

29:15 south, east, west on your journey and learn more?

29:18 And tracks your progress so you can see what scores I've gotten,

29:21 how many puzzles I've solved.

29:22 If you go east, it's a very lazy path.

29:25 Yeah.

29:26 So that's super fun.

29:28 I've not spent enough time reading the what's new in newer versions of Python,

29:33 kind of like you alluded to in the last article,

29:35 because we just use Python.

29:37 And a lot of times I'm not leveraging some of these new features, but this is a fun way

29:40 to learn what they are.

29:41 I figured I'd throw that in there.

29:42 Oh, it is very fun.

29:43 This is from Barry Warsaw, right?

29:45 I believe so.

29:46 That's a good question.

29:47 I believe so.

29:48 What's new?

29:49 It is.

29:49 You're right.

29:50 It is Barry Warsaw.

29:51 Yep.

29:51 Good job, Barry.

29:52 Nice work, Barry.

29:53 I love it.

29:53 I'm here for it.

29:54 And especially with the hype around Dungeon Crawler Carl right now, this is very appropriate.

30:00 Brings me back to the days of MUDs.

30:02 I used to play multi-user dungeons.

30:04 I mean, me and my friends, we would spend tons of time in these places back in high school.

30:09 People got to remember when I was in high school, there literally was no web.

30:14 Not like it was bad.

30:16 We're dinosaurs roaming.

30:17 The worldwide web, I know.

30:19 The whole thing was created in 1993 when I was in college.

30:23 So before that, you're like, well, we got Telnet.

30:26 What are we going to do, folks?

30:27 Yep.

30:28 Muds.

30:28 That's what we're going to do.

30:29 We're going to use Gopher.

30:30 It was a lot like this.

30:31 Yeah.

30:31 Gopher, Archie, Telnet.

30:33 Oh my gosh.

30:34 News groups.

30:35 Yeah.

30:36 Get your newsreader out.

30:37 What's so ironic is it was so amazing.

30:40 And it seems so futuristic.

30:42 I bought things off of news groups, like going in through Telnet and then getting the news

30:47 groups.

30:47 And I bought an expansion card for my HP 48 GX.

30:51 Incredible.

30:51 All right.

30:52 Well, from the past to the future,

30:54 well, to the present, which feels actually legitimately

30:57 future.

30:57 Tell me about the future.

30:58 Things used to be so simple.

30:59 You mentioned throwing just a set of files to a folder and you may be behind a C panel

31:05 so you can admin your website.

31:07 Oh, that was almost too modern for me, C-panel.

31:09 Yeah.

31:10 Yeah, just FTP it up.

31:11 I'm sorry.

31:12 Not even SFTP, just straight FTP.

31:14 Just open FTP.

31:17 So I want to come back and do one more Kyle Lintit because I couldn't help myself,

31:23 Calvin.

31:24 I saw, oh my God, I saw this one when we talked about the big data video.

31:30 So here's more homework for folks.

31:33 This is the perfect encapsulation of just how stuff gets so complicated for such a simple thing.

31:39 So here's this 10-minute video.

31:42 It tells the story of multiple mini personas throughout

31:46 that we experience as software developers and data scientists and so on,

31:49 trying to build tools, just a simple thing.

31:53 You know, it starts with, okay, I need you to build a dashboard

31:57 with a single button that does, I don't know,

32:00 you know, whatever the button does, right?

32:02 Pretty soon, there's this guy over the shoulder and says,

32:06 what about what are you doing with a regular database you need a graph database he goes i

32:11 don't need to have a graph database for 200 000 users he goes what if we had 200 000 200 000 and

32:18 one users he goes gosh his delivery is genius in this one it's so good so good my highlight was the

32:26 pearl guy pearl pearl you know devil shows up on his shoulder yeah it does yeah there's this this

32:33 other guy's like well we need a ddd you know domain driven design bounded context for the

32:38 button we need docker builds for the button it just goes on and on and just oh it is absolutely

32:46 good and the pearl guy somewhere farther it is like i could have built this with a single pearl

32:51 script and a cron job back in you know whenever but you portray them perfectly i mean if you've

32:57 been around any amount of time in this world you're gonna you're gonna laugh yeah yeah yeah it's it's

33:02 So good.

33:02 So everyone, I leave you with a delightful,

33:08 too realistic look at how software is built these days.

33:10 Yeah.

33:11 Well, this was really, really a good episode, Calvin.

33:14 Like you said.

33:15 Yeah.

33:16 Catch you later.


Want to go deeper? Check our courses




Subscribe to Python Bytes