<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">

<channel>
	<title>Planet Python</title>
	<link>http://planetpython.org/</link>
	<language>en</language>
	<description>Planet Python - http://planetpython.org/</description>

<item>
	<title>Rodrigo Girão Serrão: Personal highlights of PyCon Lithuania 2026</title>
	<guid>https://mathspp.com/blog/personal-highlights-of-pycon-lithuania-2026</guid>
	<link>https://mathspp.com/blog/personal-highlights-of-pycon-lithuania-2026</link>
	<description>&lt;img alt=&quot;&quot; src=&quot;https://mathspp.com/images/6/c/2/c/5/6c2c583d4b21857089bef76e25bd5835529e3c53-thumbnail.webp&quot; /&gt;
                                &lt;p&gt;In this article I share my personal highlights of PyCon Lithuania 2026.&lt;/p&gt;

&lt;h2 id=&quot;shout-out-to-the-organisers-and-volunteers&quot;&gt;Shout out to the organisers and volunteers&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#shout-out-to-the-organisers-and-volunteers&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This was my second time at PyCon Lithuania and, for the second time in a row, I leave with the impression that everything was very well organised and smooth.
Maybe the organisers and volunteers were stressed out all the time &amp;mdash; organising a conference is never easy &amp;mdash; but everything looked under control all the time and well thought-through.&lt;/p&gt;
&lt;p&gt;Thank you for an amazing experience!&lt;/p&gt;
&lt;p&gt;And by the way, congratulations for 15 years of PyCon Lithuania.
To celebrate, they even served a gigantic cake during the first networking event.
The cake was &lt;em&gt;at least&lt;/em&gt; 80cm by 30cm:&lt;/p&gt;
&lt;img title=&quot;The PyCon Lithuania cake.&quot; alt=&quot;A picture of a large rectangular cake with the PyCon Lithuania logo in the middle.&quot; src=&quot;https://mathspp.com/user/pages/02.blog/personal-highlights-of-pycon-lithuania-2026/_cake.webp&quot; /&gt;The PyCon Lithuania cake.&lt;p&gt;I'll be honest with you: I didn't expect the cake to be good.
The quality of food tends to degrade when it's cooked at a large scale...
But even the taste was great and the cake had three coloured layers in yellow, green, and red.&lt;/p&gt;
&lt;h2 id=&quot;social-activities&quot;&gt;Social activities&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#social-activities&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The organisers prepared &lt;em&gt;two&lt;/em&gt; networking events, a speakers' dinner, and three city tours (one per evening) for speakers.
There was &lt;em&gt;always&lt;/em&gt; something for you to do.&lt;/p&gt;
&lt;p&gt;The city tour is a brilliant idea and I wonder why more conferences don't do it:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Participants get to know a bit more of the city that's hosting the conference.&lt;/li&gt;
&lt;li&gt;Participants get the chance to talk to each other in a relaxed and informal environment.&lt;/li&gt;
&lt;li&gt;Hiring a tour guide is typically fairly cheap, especially when compared to organising a full-blown social event in a dedicated venue and with dedicated catering.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I had taken the city tour last time I had been at PyCon Lithuania and taking it again was not a mistake.&lt;/p&gt;
&lt;!-- Here's our group at the end of the tour, immediately before the speakers' dinner:
![Some PyCon Lithuania speakers smile at the camera in front of Gediminas's castle.](_tour.webp &quot;Some PyCon Lithuania speakers at the city tour.&quot;) --&gt;
&lt;p&gt;The conference organisers even made sure that the city tour ended close to the location of the speakers' dinner &lt;em&gt;and&lt;/em&gt; that the tour ended at the same time as the dinner started.
Another small detail that was carefully planned.&lt;/p&gt;
&lt;p&gt;The atmosphere of the restaurant was very pleasant and the staff there was helpful and kind, so we had a wonderful night.
At some point, at our table, we noticed that the folks at the other two tables were projecting something on a big screen.
There was a large curtain that partially separated our table from the other two, so we took some time to realise that an impromptu Python quiz was about to take place.&lt;/p&gt;
&lt;p&gt;I'm (way too) competitive and immediately got up to play.
After six questions, which included learning about the existence of the web framework &lt;em&gt;Falcon&lt;/em&gt; and correctly reordering the first four sentences of the Zen of Python, I was crowned the winner:&lt;/p&gt;
&lt;img title=&quot;The final score for the quiz.&quot; alt=&quot;A slanted picture of a blue screen showing the player RGS at the top of the quiz podium.&quot; src=&quot;https://mathspp.com/user/pages/02.blog/personal-highlights-of-pycon-lithuania-2026/_quiz.webp&quot; /&gt;The final score for the quiz.&lt;p&gt;The top three players got a &lt;em&gt;free&lt;/em&gt; spin on the PyCon Lithuania wheel of fortune.&lt;/p&gt;
&lt;h2 id=&quot;egg-hunt-and-swag&quot;&gt;Egg hunt and swag&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#egg-hunt-and-swag&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On each day of the conference there was an egg hunt running throughout the full day.
You'd get stamps by talking to sponsors, which is a fun way of getting more people to talk...&lt;/p&gt;</description>
	<pubDate>Sat, 11 Apr 2026 12:23:00 +0000</pubDate>
</item>
<item>
	<title>Armin Ronacher: The Center Has a Bias</title>
	<guid>https://lucumr.pocoo.org/2026/4/11/the-center-has-a-bias/</guid>
	<link>https://lucumr.pocoo.org/2026/4/11/the-center-has-a-bias/</link>
	<description>&lt;p&gt;Whenever a new technology shows up, the conversation quickly splits into camps.
There are the people who reject it outright, and there are the people who seem
to adopt it with religious enthusiasm.  For more than a year now, no topic has
been more polarising than AI coding agents.&lt;/p&gt;
&lt;p&gt;What I keep noticing is that a lot of the criticism directed at these tools is
perfectly legitimate, but it often comes from people without a meaningful amount
of direct experience with them.  They are not necessarily wrong.  In fact, many
of them cite studies, polls and all kinds of sources that themselves spent time
investigating and surveying.  And quite legitimately they identified real
issues: the output can be bad, the security implications are scary, the
economics are strange and potentially unsustainable, there is an environmental
impact, the social consequences are unclear, and the hype is exhausting.&lt;/p&gt;
&lt;p&gt;But there is something important missing from that criticism when it comes from
a position of non-use: it is too abstract.&lt;/p&gt;
&lt;p&gt;There is a difference between saying &amp;#8220;this looks flawed in principle&amp;#8221; and saying
&amp;#8220;I used this enough to understand where it breaks, where it helps, and how it
changes my work.&amp;#8221;  The second type of criticism is expensive.  It costs time,
frustration, and a genuine willingness to engage.&lt;/p&gt;
&lt;p&gt;The enthusiast camp consists of true believers.  These are the people who
have adopted the technology despite its shortcomings, sometimes even because
they enjoy wrestling with them.  They have already decided that the tool is
worth fitting into their lives, so they naturally end up forgiving a lot.  They
might not even recognize the flaws because for them the benefits or excitement
have already won.&lt;/p&gt;
&lt;p&gt;But what does the center look like?  I consider myself to be part of the center:
cautiously excited, but also not without criticism.  By my observation though
that center is not neutral in the way people imagine it to be.  Its bias is not
towards endorsement so much as towards engagement, because the middle ground
between rejecting a technology outright and embracing it fully is usually
occupied by people willing to explore it seriously enough to judge it.&lt;/p&gt;
&lt;h2&gt;Bias on Both Sides&lt;/h2&gt;
&lt;p&gt;The compositions of the groups of people in the discussions about new technology
are oddly shaped because one side has paid the cost of direct experience and the
other has not, or not to the same degree.  That alone creates an asymmetry.&lt;/p&gt;
&lt;p&gt;Take coding agents as an example.  If you do not use them, or at least not for
productive work, you can still criticize them on many grounds.  You can say they
generate sloppy code, that they lower your skills, etc.  But if you have not
actually spent serious time with them, then your view of their practical reality
is going to be inherited from somewhere else.  You will know them through
screenshots, anecdotes, the most annoying users on Twitter, conference talks,
company slogans, and whatever filtered back from the people who &lt;em&gt;did&lt;/em&gt; use them.
That is not nothing, but it is not the same as contact.&lt;/p&gt;
&lt;p&gt;The problem is not that such criticism is worthless.  The problem is that people
often mistake non-use for neutrality.  It is not.  A serious opinion on a new
language, framework, device, or way of working usually has some minimum buy-in.
You have to cross a threshold of use before your criticism becomes grounded in
the thing itself rather than in its reputation.&lt;/p&gt;
&lt;p&gt;That threshold is inconvenient.  It asks you to spend time on something that may
not pay off, and to risk finding yourself at least partially won over.  It is a
lot to ask of people.  But because that threshold exists, the measured middle is
rarely populated by people who are perfectly indifferent to change.  It is
populated by people who were willing to move toward it enough in order to
evaluate it properly.&lt;/p&gt;
&lt;p&gt;Simultaneously, it&amp;#8217;s important to remember that usage does not automatically
create wisdom.  The enthusiastic adopter might have their own distortions.  They
may enjoy the novelty, feel a need to justify the time they invested, or
overgeneralize from the niche where the technology works wonderfully.  They may
simply like progress and want to be associated with it.&lt;/p&gt;
&lt;p&gt;This is particularly visible with AI.  There are clearly people who have decided
that the future is here, all objections are temporary, and every workflow must
now be rebuilt around agents.  What makes AI weirder is that it&amp;#8217;s such a massive
shift in capabilities that has triggered a tremendous injection of money, and a
meaningful number of adopters have bet their future on that technology.&lt;/p&gt;
&lt;p&gt;So if one pole is uninformed abstraction and the other is overcommitted
enthusiasm, then surely the center must sit right in the middle between them?&lt;/p&gt;
&lt;h2&gt;Engagement Is Not Endorsement&lt;/h2&gt;
&lt;p&gt;The center, I would argue, naturally needs to lean towards engagement.  The
reason is simple: a genuinely measured opinion on a new technology requires real
engagement with it.&lt;/p&gt;
&lt;p&gt;You do not get an informed view by trying something for 15 minutes, getting
annoyed once, and returning to your previous tools.  You also do not get it by
admiring demos, listening to podcasts or discussing on social media.  You have
to use it enough to get past both the first disappointment and the honeymoon
phase.  Seemingly with AI tools, true understanding is not a matter of hours but
weeks of investment.&lt;/p&gt;
&lt;p&gt;That means the people in the center are selected from a particular group: people
who were willing to give the thing a fair chance without yet assuming it
deserved a permanent place in their lives.&lt;/p&gt;
&lt;p&gt;That willingness is already a bias towards curiosity and experimentation which
makes the center look more like adopters in behavior, because exploration
requires use, but it does not make the center identical to enthusiasts in
judgment.&lt;/p&gt;
&lt;p&gt;This matters because from the perspective of the outright rejecter, all of these
people can look the same.  If someone spent serious time with coding agents,
found them useful in some areas, harmful in others, and came away with a nuanced
view, they may still be thrown into the same bucket as the person who thinks
agents can do no wrong.&lt;/p&gt;
&lt;p&gt;But those are not the same position at all.  It&amp;#8217;s important to recognize that
engagement with those tools does not automatically imply endorsement or at the
very least not blanket endorsement.&lt;/p&gt;
&lt;h2&gt;The Center Looks Suspicious&lt;/h2&gt;
&lt;p&gt;This is why discussions about new technology, and AI in particular feel so
polarized.  The actual center is hard to see because it does not appear visually
centered.  From the outside, serious exploration can look a lot like adoption.&lt;/p&gt;
&lt;p&gt;If you map opinions onto a line, you might imagine the middle as the point
equally distant from rejection and enthusiasm.  But in practice that is not how
it works.  The middle is shifted toward the side of the people who have actually
interacted with the technology enough to say something concrete about it.  That
does not mean the middle has accepted the adopter&amp;#8217;s conclusion.  It means the
middle has adopted some of the adopter&amp;#8217;s behavior, because investigation
requires contact.&lt;/p&gt;
&lt;p&gt;That creates a strange effect because the people with the most grounded
criticism are often also adopters.  I would argue some of the best criticism of
coding agents right now comes from people who use them extensively.  Take
&lt;a href=&quot;https://mariozechner.at/&quot;&gt;Mario&lt;/a&gt;: he created a coding agent, yet is also one of
the most vocal voices of criticism in the space.  These folks can tell you in
detail how they fail and they can tell you where they waste time, where they
regress code quality, where they need carefully designed tooling, where they
only work well in some ecosystems, and where the whole thing falls apart.&lt;/p&gt;
&lt;p&gt;But because those people kept using the tools long enough to learn those
lessons, they can appear compromised to outsiders.  And worse: if they continue
to use them, contribute thoughts and criticism back, they are increasingly
thrown in with the same people who are devoid of any criticism.&lt;/p&gt;
&lt;h2&gt;Failure Is Possible&lt;/h2&gt;
&lt;p&gt;This line of thinking could be seen as an inherent &amp;#8220;pro-innovation bias&amp;#8221;.  That
would be wrong, as plenty of technology deserves resistance.  Many people are
right to resist, and sometimes the people who never gave a technology a chance
saw problems earlier than everyone else.  Crypto is a good reminder: plenty of
projects looked every bit as exciting as coding agents do now, and still
collapsed when the economics no longer worked.&lt;/p&gt;
&lt;p&gt;What matters here is a narrower point.  The center is not biased towards novelty
so much as towards contact with the thing that creates potential change.  The
middle ground is not between use and non-use, but between refusal and commitment
and the people in the center will often look more like adopters than skeptics,
not because they have already made up their minds, but because getting an
informed view requires exploration.&lt;/p&gt;
&lt;p&gt;If you want to criticize a new thing well, you first have to get close enough to
dislike it for the right reasons.  And for some technologies, you also have to
hang around long enough to understand what, exactly, deserves criticism.&lt;/p&gt;</description>
	<pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>Talk Python to Me: #544: Wheel Next + Packaging PEPs</title>
	<guid>https://talkpython.fm/episodes/show/544/wheel-next-packaging-peps</guid>
	<link>https://talkpython.fm/episodes/show/544/wheel-next-packaging-peps</link>
	<description>When you pip install a package with compiled code, the wheel you get is built for CPU features from 2009. Want newer optimizations like AVX2? Your installer has no way to ask for them. GPU support? You're on your own configuring special index URLs. The result is fat binaries, nearly gigabyte-sized wheels, and install pages that read like puzzle books. A coalition from NVIDIA, Astral, and QuantSight has been working on Wheel Next: A set of PEPs that let packages declare what hardware they need and let installers like uv pick the right build automatically. Just  uv pip install torch and it works. I sit down with Jonathan Dekhtiar from NVIDIA, Ralf Gommers from QuantSight and the NumPy and SciPy teams, and Charlie Marsh, founder of Astral and creator of uv, to dig into all of it.&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode sponsors&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;a href='https://talkpython.fm/sentry'&amp;gt;Sentry Error Monitoring, Code talkpython26&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href='https://talkpython.fm/temporal'&amp;gt;Temporal&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;a href='https://talkpython.fm/training'&amp;gt;Talk Python Courses&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;h2 class=&quot;links-heading mb-4&quot;&amp;gt;Links from the show&amp;lt;/h2&amp;gt;
&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Guests&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Charlie Marsh&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/charliermarsh?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Ralf Gommers&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/rgommers?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Jonathan Dekhtiar&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/DEKHTIARJonathan?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;CPU dispatcher&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://numpy.org/doc/stable/reference/simd/how-it-works.html?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;numpy.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;build options&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://numpy.org/doc/stable/reference/simd/build-options.html?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;numpy.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Red Hat RHEL&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;www.redhat.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Red Hat RHEL AI&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.redhat.com/en/products/ai?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;www.redhat.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;RedHats presentation&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://wheelnext.dev/summits/2025_03/assets/WheelNext%20Community%20Summit%20-%2006%20-%20Red%20Hat.pdf?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;wheelnext.dev&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;CUDA release&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://developer.nvidia.com/cuda/toolkit?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;developer.nvidia.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;requires a PEP&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://discuss.python.org/t/pep-proposal-platform-aware-gpu-packaging-and-installation-for-python/91910?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;discuss.python.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;WheelNext&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://wheelnext.dev/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;wheelnext.dev&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Github repo&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://github.com/wheelnext?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;github.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;PEP 817&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://peps.python.org/pep-0817/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;peps.python.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;PEP 825&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://discuss.python.org/t/pep-825-wheel-variants-package-format-split-from-pep-817/106196?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;discuss.python.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;uv&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://docs.astral.sh/uv/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;docs.astral.sh&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;A variant-enabled build of uv&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://astral.sh/blog/wheel-variants?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;astral.sh&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;pyx&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://astral.sh/blog/introducing-pyx?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;astral.sh&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;pypackaging-native&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://pypackaging-native.github.io?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;pypackaging-native.github.io&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;PEP 784&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://peps.python.org/pep-0784/?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;peps.python.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Watch this episode on YouTube&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://www.youtube.com/watch?v=761htncGZpU&quot; target=&quot;_blank&quot; &amp;gt;youtube.com&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode #544 deep-dive&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/episodes/show/544/wheel-next-packaging-peps#takeaways-anchor&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm/544&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Episode transcripts&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/episodes/transcript/544/wheel-next-packaging-peps&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Theme Song: Developer Rap&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;🥁 Served in a Flask 🎸&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/flasksong&quot; target=&quot;_blank&quot; &amp;gt;talkpython.fm/flasksong&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;---==  Don't be a stranger  ==---&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;YouTube&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://talkpython.fm/youtube&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-youtube&quot;&amp;gt;&amp;lt;/i&amp;gt; youtube.com/@talkpython&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Bluesky&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://bsky.app/profile/talkpython.fm&quot; target=&quot;_blank&quot; &amp;gt;@talkpython.fm&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Mastodon&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://fosstodon.org/web/@talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-mastodon&quot;&amp;gt;&amp;lt;/i&amp;gt; @talkpython@fosstodon.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;X.com&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://x.com/talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-twitter&quot;&amp;gt;&amp;lt;/i&amp;gt; @talkpython&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on Bluesky&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://bsky.app/profile/mkennedy.codes?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;@mkennedy.codes&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on Mastodon&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://fosstodon.org/web/@mkennedy&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-mastodon&quot;&amp;gt;&amp;lt;/i&amp;gt; @mkennedy@fosstodon.org&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;strong&amp;gt;Michael on X.com&amp;lt;/strong&amp;gt;: &amp;lt;a href=&quot;https://x.com/mkennedy?featured_on=talkpython&quot; target=&quot;_blank&quot; &amp;gt;&amp;lt;i class=&quot;fa-brands fa-twitter&quot;&amp;gt;&amp;lt;/i&amp;gt; @mkennedy&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/div&amp;gt;</description>
	<pubDate>Fri, 10 Apr 2026 16:56:54 +0000</pubDate>
</item>
<item>
	<title>PyCharm: How (Not) to Learn Python</title>
	<guid>https://blog.jetbrains.com/pycharm/2026/04/how-not-to-learn-python/</guid>
	<link>https://blog.jetbrains.com/pycharm/2026/04/how-not-to-learn-python/</link>
	<description>&lt;p&gt;While listening to &lt;a href=&quot;https://www.youtube.com/watch?v=i6SdsSj96ys&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mark Smith’s inspirational talk&lt;/a&gt; for &lt;em&gt;Python Unplugged on PyTV &lt;/em&gt;about &lt;em&gt;How to Learn Python&lt;/em&gt;, what caught my attention was that Mark suggested turning off some of PyCharm’s AI features to help you learn Python more effectively.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image-2.png&quot; alt=&quot;&quot; class=&quot;wp-image-696367&quot; /&gt;



&lt;p&gt;As a PyCharm user myself, I’ve found the AI-powered features beneficial in my day-to-day work; however, I never considered that I could turn certain features on or off to customize my experience. This can be done from the settings menu under &lt;em&gt;Editor&lt;/em&gt; | &lt;em&gt;General&lt;/em&gt; | &lt;em&gt;Code Completion&lt;/em&gt; | &lt;em&gt;Inline&lt;/em&gt;.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image1-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-700369&quot; /&gt;



&lt;p&gt;While we are at it, let’s have a look at these features and investigate in more detail why they are great for professional developers but may not be ideal for learners.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Local full line code completion suggestions&lt;/h2&gt;



&lt;p&gt;JetBrains AI credits are not consumed when you use local line completion. The completion prediction is performed using a built-in local deep learning model. To use this feature, make sure the box for &lt;em&gt;Enable inline completion using language models&lt;/em&gt; is checked, and choose either &lt;em&gt;Local&lt;/em&gt; or &lt;em&gt;Cloud and local&lt;/em&gt; in the options. To show the complete results using the local model alone, we will look at the predictions when only &lt;em&gt;Local&lt;/em&gt; is selected.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image2-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-700380&quot; /&gt;



&lt;p&gt;When it’s selected, you see that the only code completion available out of the box in PyCharm is for Python. To make suggestions available for CSS or HTML, you need to download additional models.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image3-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-700391&quot; /&gt;



&lt;p&gt;When you are writing code, you will see suggestions pop up in grey with a hint for you to use &lt;em&gt;Tab&lt;/em&gt; to complete the line.&amp;nbsp;&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image4.png&quot; alt=&quot;&quot; class=&quot;wp-image-700402&quot; /&gt;



&lt;p&gt;After completing that line, you can press &lt;em&gt;Enter&lt;/em&gt; to go to the next one, where there may be a new suggestion that you can again use &lt;em&gt;Tab&lt;/em&gt; to complete. As you see, this can be very convenient for developers in their daily coding, as it saves time that would otherwise be spent typing obvious lines of code that follow the flow naturally.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;However, for beginners, mindlessly hitting &lt;em&gt;Tab&lt;/em&gt; and letting the model complete lines may discourage them from learning how to use the functions correctly. An alternative is to use the hint provided by PyCharm to help you choose an appropriate method from the available list, determine which parameters are needed, check the documentation if necessary, and write the code yourself. Here is what the hint looks like when code completion is turned off:&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image5.png&quot; alt=&quot;&quot; class=&quot;wp-image-700413&quot; /&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Cloud-based completion suggestions&lt;/h2&gt;



&lt;p&gt;Let’s have a look at cloud-based completion in contrast to local completion. When using cloud-based completion, next-edit suggestions are also available (which we will look at in more detail in the next section).&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image6.png&quot; alt=&quot;&quot; class=&quot;wp-image-700424&quot; /&gt;



&lt;p&gt; Cloud-based completion comes with support for multiple languages by default, and you can switch it on or off for each language individually.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image-1.png&quot; alt=&quot;&quot; class=&quot;wp-image-696348&quot; /&gt;



&lt;p&gt;Cloud-based completion provides more functionality than local model completion, but you need a JetBrains AI subscription to use it.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image8.png&quot; alt=&quot;&quot; class=&quot;wp-image-700446&quot; /&gt;



&lt;p&gt;You may also connect to a third-party AI provider for your cloud-based completion. Since this support is still in Beta in PyCharm 2026.1, it is highly recommended to keep your JetBrains AI subscription active as a backup to ensure all features are available.&lt;/p&gt;



&lt;p&gt;After switching to cloud-based completion, one of the differences I noticed was that it is better at multiple-line completion, which can be more convenient. However, I have also encountered situations where the completion provided too much for me, and I had to jump in to make my own modifications after accepting the suggestions.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image9.png&quot; alt=&quot;&quot; class=&quot;wp-image-700457&quot; /&gt;



&lt;p&gt;For learners of Python, again, you may want to disable this functionality or have to audit all the suggestions in detail yourself. In addition to the danger of relying too heavily on code completion, which removes opportunities to learn, cloud code completion poses another risk for learners. Because larger suggestions require active review from the developer, learners may not be equipped to fully audit the wholesale suggestions they are accepting. Disabling this feature for learners not only encourages learning, but it can also help prevent mistakes.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Next edit suggestions&lt;/h2&gt;



&lt;p&gt;In addition to cloud-based completion, JetBrains AI Pro, Ultimate, and Enterprise users are able to take advantage of next edit suggestions.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image10.png&quot; alt=&quot;&quot; class=&quot;wp-image-700468&quot; /&gt;



&lt;p&gt;When they are enabled, every time you make changes to your code, for example, renaming a variable, you will be given suggestions about other places that need to be changed.&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/nes.gif&quot; alt=&quot;&quot; class=&quot;wp-image-700347&quot; /&gt;



&lt;p&gt;And when you press &lt;em&gt;Tab&lt;/em&gt;, the changes will be made automatically. You can also customize this behavior so you can see previews of the changes and jump continuously to the next edit until no more are suggested.&lt;/p&gt;



&lt;p&gt;This is, no doubt, a very handy feature. It can help you avoid some careless mistakes, like forgetting to refactor your code when you make changes. However, for learners, thinking about what needs to be done is a valuable thought exercise, and using this feature can deprive them of some good learning opportunities.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;PyCharm offers a lot of useful features to smooth out your day-to-day development workflow. However, these features may be too powerful, and even too convenient, for those who have just started working with Python and need to learn by making mistakes. It is good to use AI features to improve our work, but we also need to double-check the results and make sure that we want what the AI suggests.&lt;/p&gt;



&lt;p&gt;To learn more about how to level up your Python skills, I highly recommend watching &lt;a href=&quot;https://www.youtube.com/watch?v=i6SdsSj96ys&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mark’s talk on PyTV&lt;/a&gt; and checking out all the &lt;a href=&quot;https://www.jetbrains.com/help/ai-assistant/getting-started-with-ai-assistant.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AI features&lt;/a&gt; that JetBrains AI has to offer. I hope you will find the perfect way to integrate them into your work while remaining ready to turn them off when you plan to learn something new.&lt;/p&gt;</description>
	<pubDate>Fri, 10 Apr 2026 14:21:21 +0000</pubDate>
</item>
<item>
	<title>Ahmed Bouchefra: Build Your Own AI Meme Matcher: A Beginner's Guide to Computer Vision with Python</title>
	<guid>https://efficientcoder.net/ai-matcher-python</guid>
	<link>https://efficientcoder.net/ai-matcher-python</link>
	<description>&lt;p&gt;Have you ever wondered how Snapchat filters know exactly where your eyes and mouth are? Or how your phone can unlock just by looking at your face? The magic behind this is called &lt;strong&gt;Computer Vision&lt;/strong&gt;, a field of Artificial Intelligence that allows computers to “see” and understand digital images.&lt;/p&gt;

&lt;p&gt;Today, we are going to build something incredibly fun using Computer Vision: a &lt;strong&gt;Real-Time Meme Matcher&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Point your webcam at yourself, make a shocked face, and watch as the app instantly matches you with the “Overly Attached Girlfriend” meme. Smile and raise your hand, and Leonardo DiCaprio raises a glass right back at you.&lt;/p&gt;

&lt;p&gt;But this isn’t just a fun project. We are going to build this using &lt;strong&gt;Object-Oriented Programming (OOP)&lt;/strong&gt;. OOP is a professional coding style that makes your code clean, organized, and easy to upgrade. By the end of this tutorial, you will have a working AI app and a solid understanding of how professional software is structured.&lt;/p&gt;

&lt;p&gt;Let’s dive in!&lt;/p&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;Before we start coding, make sure you have the following ready:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Python 3.11&lt;/strong&gt; or newer installed on your computer.&lt;/li&gt;
  &lt;li&gt;A working webcam.&lt;/li&gt;
  &lt;li&gt;A folder named &lt;code class=&quot;highlighter-rouge&quot;&gt;assets&lt;/code&gt; in your project directory containing a few popular meme images (like &lt;code class=&quot;highlighter-rouge&quot;&gt;success_kid.jpg&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;disaster_girl.jpg&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will also need to install a few Python libraries. Open your terminal or command prompt and run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;mediapipe opencv-python numpy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-theory-how-does-it-work&quot;&gt;The Theory: How Does It Work?&lt;/h2&gt;

&lt;p&gt;Before we look at the code, let’s understand the two main concepts powering our application: Computer Vision (Facial Landmarks) and Object-Oriented Programming.&lt;/p&gt;

&lt;h3 id=&quot;1-facial-landmarks-how-the-ai-sees-you&quot;&gt;1. Facial Landmarks (How the AI “Sees” You)&lt;/h3&gt;

&lt;p&gt;We are using a  Google library called &lt;strong&gt;MediaPipe&lt;/strong&gt;. When you feed an image to MediaPipe, it places a virtual “mesh” of 478 invisible dots (called landmarks) over your face.&lt;/p&gt;

&lt;p&gt;To figure out your expression, we use simple math. For example, how do we know if your mouth is open in surprise?&lt;/p&gt;

&lt;p&gt;We measure the vertical distance between the dot on your top lip and the dot on your bottom lip.&lt;/p&gt;

&lt;p&gt;If the distance is large, your mouth is open! We do the same for your eyes and eyebrows to calculate “scores” for surprise, smiling, or concern.&lt;/p&gt;

&lt;h3 id=&quot;2-object-oriented-programming-oop&quot;&gt;2. Object-Oriented Programming (OOP)&lt;/h3&gt;

&lt;p&gt;Instead of writing one massive, confusing block of code, OOP allows us to break our program into separate components called &lt;strong&gt;Classes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of a Class as a blueprint.&lt;/p&gt;

&lt;p&gt;For our Meme Matcher, we will create three distinct classes, each with a “Single Responsibility” (a golden rule of coding):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ExpressionAnalyzer&lt;/code&gt; (The Brain):&lt;/strong&gt; Handles the AI math and MediaPipe.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;MemeLibrary&lt;/code&gt; (The Database):&lt;/strong&gt; Loads the images and compares the user’s face to the memes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;MemeMatcherApp&lt;/code&gt; (The UI):&lt;/strong&gt; Opens the webcam and draws the pictures on the screen.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;step-1-building-the-brain&quot;&gt;Step 1: Building the Brain&lt;/h2&gt;

&lt;p&gt;Let’s start by creating the class that does all the heavy lifting. Create a file named &lt;code class=&quot;highlighter-rouge&quot;&gt;meme_matcher.py&lt;/code&gt; and import the necessary tools. Then, we will define our first class.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cv2&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;mediapipe&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pathlib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;concurrent.futures&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ThreadPoolExecutor&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pickle&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;subprocess&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExpressionAnalyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    The ExpressionAnalyzer class acts as the 'Brain' of our project.
    It encapsulates (hides away) the complex MediaPipe machine learning logic.
    &quot;&quot;&quot;&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Class Variables: Landmark indices for eyes, eyebrows, and mouth
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;LEFT_EYE_UPPER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;159&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;145&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;158&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LEFT_EYE_LOWER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;133&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RIGHT_EYE_UPPER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;386&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;374&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;385&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RIGHT_EYE_LOWER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;253&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;257&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;362&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LEFT_EYEBROW&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;63&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;105&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;107&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RIGHT_EYEBROW&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;293&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;334&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;296&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;336&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;MOUTH_OUTER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;61&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;291&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;39&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;181&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;269&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;405&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;MOUTH_INNER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;78&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;308&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;88&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;NOSE_TIP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame_skip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;  
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;     
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_skip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame_skip&lt;/span&gt; 

        &lt;span class=&quot;c1&quot;&gt;# Download the required AI models automatically
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_model_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_download_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;face_landmarker.task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;[https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task](https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task)&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_model_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_download_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;hand_landmarker.task&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;[https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task](https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task)&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Initialize MediaPipe objects for both video and images
&lt;/span&gt;        
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_mesh_video&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_init_face_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;video_mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_detector_video&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_init_hand_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;video_mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_mesh_image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_init_face_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;video_mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_detector_image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_init_hand_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;video_mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;understanding-the-brain&quot;&gt;Understanding the Brain&lt;/h3&gt;

&lt;p&gt;In the code above, we define lists of numbers like &lt;code class=&quot;highlighter-rouge&quot;&gt;LEFT_EYE_UPPER&lt;/code&gt;. These are the exact dot numbers (out of the 478) that outline the eye.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;__init__&lt;/code&gt; method is a special function called a &lt;strong&gt;constructor&lt;/strong&gt;. 
Whenever we create an &lt;code class=&quot;highlighter-rouge&quot;&gt;ExpressionAnalyzer&lt;/code&gt;, this code runs automatically to set everything up. 
It downloads the MediaPipe AI models from Google’s servers and loads them into memory so they are ready to process faces.&lt;/p&gt;

&lt;p&gt;Next, we add the logic to extract features:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;c1&quot;&gt;# ... (Add this inside the ExpressionAnalyzer class) ...
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extract_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndarray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Analyzes an image and returns facial/hand features as a dictionary.&quot;&quot;&quot;&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;face_landmarker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_mesh_image&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_mesh_video&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;hand_landmarker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_detector_image&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_detector_video&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;COLOR_BGR2RGB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;mp_image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ImageFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SRGB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;face_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;face_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mp_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;hand_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mp_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_skip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;last_features&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
            &lt;span class=&quot;n&quot;&gt;face_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;face_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detect_for_video&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mp_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;hand_res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand_landmarker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;detect_for_video&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mp_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;face_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_landmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;landmarks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;face_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;face_landmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# Calculate the mathematical features
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_compute_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_compute_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ndarray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Helper function to calculate Eye Aspect Ratio (How open the eye is)&quot;&quot;&quot;&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;vert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linalg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;norm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;horiz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linalg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;norm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;horiz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1e-6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 

        &lt;span class=&quot;n&quot;&gt;left_ear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT_EYE_UPPER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT_EYE_LOWER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_ear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT_EYE_UPPER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT_EYE_LOWER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;avg_ear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left_ear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_ear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Mouth calculations
&lt;/span&gt;        
        &lt;span class=&quot;n&quot;&gt;mouth_top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_bottom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mouth_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linalg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;norm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mouth_top&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mouth_left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_right&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;61&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;291&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mouth_width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linalg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;norm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mouth_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mouth_ar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mouth_width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1e-6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Eyebrow calculations
&lt;/span&gt;        
        &lt;span class=&quot;n&quot;&gt;left_brow_y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT_EYEBROW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_brow_y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT_EYEBROW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;left_eye_center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT_EYE_UPPER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LEFT_EYE_LOWER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;right_eye_center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;landmark_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT_EYE_UPPER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RIGHT_EYE_LOWER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;avg_brow_h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left_eye_center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;left_brow_y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right_eye_center&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;right_brow_y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Check for hands
&lt;/span&gt;        
        &lt;span class=&quot;n&quot;&gt;num_hands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_landmarks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand_res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hand_landmarks&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;hand_raised&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_hands&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;'eye_openness'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg_ear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;'mouth_openness'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_ar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;'eyebrow_height'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg_brow_h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;'hand_raised'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand_raised&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;'surprise_score'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg_ear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg_brow_h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_ar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;'smile_score'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mouth_ar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This section might look heavily mathematical, but it’s just measuring distances! 
For instance, &lt;code class=&quot;highlighter-rouge&quot;&gt;mouth_height&lt;/code&gt; calculates the distance from the top lip to the bottom lip. 
We bundle all these measurements into a neat little package (a Python dictionary) and return it.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;step-2-building-the-database&quot;&gt;Step 2: Building the Database&lt;/h2&gt;

&lt;p&gt;Now that our brain can understand expressions, we need a library to hold our memes.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MemeLibrary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Acts as a database for our memes. 
    It 'has-a' relationship with ExpressionAnalyzer (Dependency Injection).
    &quot;&quot;&quot;&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;CACHE_FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;meme_features_cache.pkl&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExpressionAnalyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;assets&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meme_height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt; 
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meme_height&lt;/span&gt;

        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'surprise_score'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'smile_score'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'hand_raised'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'eye_openness'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'mouth_openness'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'eyebrow_height'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_weights&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_factors&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load_memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Loads memes from disk or a cache file to save time.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CACHE_FILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CACHE_FILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;rb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;assets_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;image_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Analyze multiple memes at the same time
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;executor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_process_single_meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CACHE_FILE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;wb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_process_single_meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;img_resized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_resized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_static&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
            
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'image'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img_resized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'_'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'path'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compute_similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Mathematical formula to compare two dictionaries of facial features.&quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;features2&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;vec1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;features1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vec2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;features2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vec1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vec2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;diff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_factors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;feature_weights&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_best_match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_features&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compute_similarity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mf&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;best_idx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;best_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;best_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-magic-of-dependency-injection&quot;&gt;The Magic of Dependency Injection&lt;/h3&gt;

&lt;p&gt;Did you notice how the &lt;code class=&quot;highlighter-rouge&quot;&gt;__init__&lt;/code&gt; method takes &lt;code class=&quot;highlighter-rouge&quot;&gt;analyzer: ExpressionAnalyzer&lt;/code&gt; as an argument?&lt;/p&gt;

&lt;p&gt;This is a concept called &lt;strong&gt;Dependency Injection&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of the Library trying to build its own AI model, we just hand it the Brain we already built. 
This keeps our code completely separate and organized!&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;find_best_match&lt;/code&gt; function is where the matching happens. 
It takes the dictionary of your face (how wide your eyes are, etc.) and compares it to the dictionaries of all the memes. 
The meme with the closest numbers wins!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;step-3-building-the-app-controller&quot;&gt;Step 3: Building the App Controller&lt;/h2&gt;

&lt;p&gt;With our AI brain and meme database built, it’s time to bring them to life! 
We need an application class to turn on your webcam, capture the video, and draw the results on your screen.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MemeMatcherApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    The main Application class. 
    It initializes the other classes and contains the main while loop.
    &quot;&quot;&quot;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;assets&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExpressionAnalyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MemeLibrary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VideoCapture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CAP_PROP_FRAME_WIDTH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;640&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CAP_PROP_FRAME_HEIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;480&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;🎥 Camera started! Press 'q' to quit&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isOpened&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Mirror effect
&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# 1. Ask the Analyzer to look at the webcam frame
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;user_features&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analyzer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extract_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# 2. Ask the Library to find the best matching meme
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;best_meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;score&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_best_match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_features&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;# 3. Handle the User Interface (Displaying the result)
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;best_meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;meme_img&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;best_meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'image'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;meme_h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meme_w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meme_img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                
                &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meme_h&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;new_w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;meme_resized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meme_img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

                &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uint8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;               
                &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meme_resized&lt;/span&gt; 

                &lt;span class=&quot;c1&quot;&gt;# Draw UI Text boxes
&lt;/span&gt;                &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;putText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;YOU&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FONT_HERSHEY_SIMPLEX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                
                &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;putText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;best_meme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FONT_HERSHEY_SIMPLEX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;putText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No face detected!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FONT_HERSHEY_SIMPLEX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imshow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Meme Matcher - Press Q to quit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;waitKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xFF&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;q&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destroyAllWindows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-infinite-loop&quot;&gt;The Infinite Loop&lt;/h3&gt;

&lt;p&gt;The core of any video application is a &lt;code class=&quot;highlighter-rouge&quot;&gt;while&lt;/code&gt; loop. 
The application reads one picture from your webcam, asks the &lt;code class=&quot;highlighter-rouge&quot;&gt;ExpressionAnalyzer&lt;/code&gt; for the features, asks the &lt;code class=&quot;highlighter-rouge&quot;&gt;MemeLibrary&lt;/code&gt; for a match, glues the webcam picture and the meme picture together side-by-side using NumPy, and displays it. 
Then, it repeats this instantly for the next frame!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;step-4-putting-it-all-together&quot;&gt;Step 4: Putting it All Together&lt;/h2&gt;

&lt;p&gt;Finally, we just need to start the application. At the very bottom of your file, add the entry point:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Meme Matcher Starting...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Create the application object and run it
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MemeMatcherApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assets_folder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;assets&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Congratulations! You have just built a complex Artificial Intelligence application using advanced Computer Vision techniques.&lt;/p&gt;

&lt;p&gt;More importantly, you built it the &lt;em&gt;right way&lt;/em&gt;. 
By structuring your code using Object-Oriented Programming, your project is scalable. 
Want to add a Graphical User Interface (GUI) with buttons later? 
You don’t have to touch the math inside the Brain or the Database; you only have to modify the App class.&lt;/p&gt;

&lt;p&gt;To see the real magic, download a few distinct meme images, put them in an &lt;code class=&quot;highlighter-rouge&quot;&gt;assets&lt;/code&gt; folder next to your script, and run it. 
Try raising your eyebrows, opening your mouth wide, or throwing up a peace sign.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;Check out all our books that you can read for free from this page &lt;a href=&quot;https://10xdev.blog/library&quot;&gt;https://10xdev.blog/library&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 10 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: The Real Python Podcast – Episode #290: Advice on Managing Projects &amp;amp; Making Python Classes Friendly</title>
	<guid>https://realpython.com/podcasts/rpp/290/</guid>
	<link>https://realpython.com/podcasts/rpp/290/</link>
	<description>&lt;p&gt;What goes into managing a major project? What techniques can you employ for a project that's in crisis? Christopher Trudeau is back on the show this week with another batch of PyCoder's Weekly articles and projects.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 10 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: Quiz: Exploring Protocols in Python</title>
	<guid>https://realpython.com/quizzes/exploring-protocols-python/</guid>
	<link>https://realpython.com/quizzes/exploring-protocols-python/</link>
	<description>&lt;p&gt;In this quiz, you&amp;rsquo;ll test your understanding of
&lt;a href=&quot;https://realpython.com/courses/exploring-protocols-python/&quot;&gt;Exploring Protocols in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The questions review Python protocols, how they define required methods and attributes, and how static type checkers use them. You&amp;rsquo;ll also explore structural subtyping, generic protocols, and subprotocols.&lt;/p&gt;
&lt;p&gt;This quiz helps you confirm the concepts covered in the course and shows you where to focus further study. If you want to review the material, the course covers these topics in depth at the link above.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 10 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>Rodrigo Girão Serrão: Who wants to be a millionaire: iterables edition</title>
	<guid>https://mathspp.com/blog/who-wants-to-be-a-millionaire-iterables-edition</guid>
	<link>https://mathspp.com/blog/who-wants-to-be-a-millionaire-iterables-edition</link>
	<description>&lt;img alt=&quot;&quot; src=&quot;https://mathspp.com/images/d/a/f/f/f/dafff6dece430b72fbcf74f9f834f586606da8be-thumbnail.webp&quot; /&gt;
                                &lt;p&gt;Play this short quiz to test your Python knowledge!&lt;/p&gt;



&lt;p&gt;At PyCon Lithuania 2026 I did a lightning talk where I presented a “Who wants to be a millionaire?” Python quiz, themed around iterables.
There's a whole performance during the lightning talk which was recorded and will be eventually linked to from here.
This article includes only the four questions, the options presented, and a basic system that allows you to check whether you got it right or not.&lt;/p&gt;
&lt;h2 id=&quot;question-1&quot;&gt;Question 1&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#question-1&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is an easy one to get you started.
It makes more sense if you watch the &lt;em&gt;performance&lt;/em&gt; of the lightning talk.&lt;/p&gt;
&lt;div class=&quot;quiz-question&quot;&gt;
  &lt;div class=&quot;question-text&quot;&gt;&lt;p&gt;What is the output of the following Python program?&lt;/p&gt;&lt;/div&gt;
  &lt;pre&gt;&lt;code class=&quot;language-py hljs language-python&quot;&gt;print(&quot;Hello, world!&quot;)&lt;/code&gt;&lt;/pre&gt;
  &lt;ul class=&quot;choices&quot;&gt;&lt;li&gt;Hello, world!&lt;/li&gt;
    &lt;li&gt;Hello world!&lt;/li&gt;
    &lt;li&gt;Hello world&lt;/li&gt;
    &lt;li&gt;Hello world!!&lt;/li&gt;
  &lt;/ul&gt;&lt;p class=&quot;feedback&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;question-2&quot;&gt;Question 2&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#question-2&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;quiz-question&quot;&gt;
  &lt;div class=&quot;question-text&quot;&gt;&lt;p&gt;What is the output of the following Python program?&lt;/p&gt;&lt;/div&gt;
  &lt;pre&gt;&lt;code class=&quot;language-py hljs language-python&quot;&gt;squares = (x ** 2 for x in range(3))
print(type(squares))&lt;/code&gt;&lt;/pre&gt;
  &lt;ul class=&quot;choices&quot;&gt;&lt;li&gt;&lt;code&gt;&amp;lt;class 'generator'&amp;gt;&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;&amp;lt;class 'gen_expr'&amp;gt;&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;&amp;lt;class 'list'&amp;gt;&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;&amp;lt;class 'tuple'&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;&lt;p class=&quot;feedback&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;question-3&quot;&gt;Question 3&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#question-3&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This was a reference to the talk I'd given earlier today, where I talked about &lt;code&gt;tee&lt;/code&gt;.
The only object in &lt;code&gt;itertools&lt;/code&gt; that is not an iterable.&lt;/p&gt;
&lt;div class=&quot;quiz-question&quot;&gt;
  &lt;div class=&quot;question-text&quot;&gt;&lt;p&gt;Out of the 20, how many objects in &lt;code&gt;itertools&lt;/code&gt; are iterables?&lt;/p&gt;&lt;/div&gt;
  &lt;ul class=&quot;choices&quot;&gt;&lt;li&gt;19&lt;/li&gt;
    &lt;li&gt;20&lt;/li&gt;
    &lt;li&gt;1&lt;/li&gt;
    &lt;li&gt;0&lt;/li&gt;
  &lt;/ul&gt;&lt;p class=&quot;feedback&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;question-4&quot;&gt;Question 4&lt;a href=&quot;https://mathspp.com/blog/tags/python.rss#question-4&quot; class=&quot;toc-anchor after&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;quiz-question&quot;&gt;
  &lt;div class=&quot;question-text&quot;&gt;&lt;p&gt;What is the output of the following Python program?&lt;/p&gt;&lt;/div&gt;
  &lt;pre&gt;&lt;code class=&quot;language-py hljs language-python&quot;&gt;from itertools import *

print(sum(chain.from_iterable(chain(*next(
islice(permutations(islice(batched(pairwise(
count()),5),3,9)),15,None)))))&lt;/code&gt;&lt;/pre&gt;
  &lt;ul class=&quot;choices&quot;&gt;&lt;li&gt;1800&lt;/li&gt;
    &lt;li&gt;0&lt;/li&gt;
    &lt;li&gt;🇱🇹❤️🐍&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;SyntaxError&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;&lt;p class=&quot;feedback&quot;&gt;&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Thu, 09 Apr 2026 21:17:00 +0000</pubDate>
</item>
<item>
	<title>Rodrigo Girão Serrão: uv skills for coding agents</title>
	<guid>https://mathspp.com/blog/uv-skills</guid>
	<link>https://mathspp.com/blog/uv-skills</link>
	<description>&lt;img alt=&quot;&quot; src=&quot;https://mathspp.com/images/3/9/3/7/a/3937a2df98700141aee91c6f7d322ff9730b6f00-thumbnail.webp&quot; /&gt;
                                &lt;p&gt;This article shares two skills you can add to your coding agents so they use uv workflows.&lt;/p&gt;

&lt;p&gt;I have fully adopted uv into my workflows and most of the time I want my coding agents to use uv workflows as well, like when running any Python code or managing and running scripts that may or may not have dependencies.&lt;/p&gt;
&lt;p&gt;To make this more convenient for me, I created two &lt;code&gt;SKILL.md&lt;/code&gt; files for two of the most common workflows that the coding agents get wrong on the first few tries:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;code&gt;python-via-uv&lt;/code&gt;: this skill tells the agent that it should use uv whenever it wants to run any piece of Python code, be it one-liners or scripts. This is relevant because I don't even have the command &lt;code&gt;python&lt;/code&gt;/&lt;code&gt;python3&lt;/code&gt; in the shell path, so whenever the LLM tries running something with &lt;code&gt;python ...&lt;/code&gt;, it fails.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uv-script-workflow&lt;/code&gt;: this skill is specifically for when the agent wants to create and run a script. It instructs the LLM to initalise the script with &lt;code&gt;uv init --script ...&lt;/code&gt; and then tells it about the relevant commands to manage the script dependencies.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The two skills also add a note about sandboxing, since uv's default cache directory will be outside your sandbox.
When that's the case, the agent is already instructed to use a valid temporary location for the uv cache.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installing&lt;/em&gt; a skill usually just means dropping a Markdown file in the correct folder, but you should check the documentation for the tools you use.&lt;/p&gt;
&lt;p&gt;Here are the two skills for you to download:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://mathspp.com/blog/uv-skills/./SKILL-python-via-uv.txt&quot;&gt;Skill for &lt;code&gt;python-via-uv&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mathspp.com/blog/uv-skills/./SKILL-uv-script-workflow.txt&quot;&gt;Skill for &lt;code&gt;uv-script-workflow&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;I also included the skills verbatim here, for your convenience:&lt;/p&gt;
Skill for &lt;code&gt;python-via-uv&lt;/code&gt;&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;---
name: python-via-uv
description: Enforce Python execution through `uv` instead of direct interpreter calls. Use when Codex needs to run Python scripts, modules, one-liners, tools, test runners, or package commands in a workspace and should avoid invoking `python` or `python3` directly.
---

# Python Via Uv

Use `uv` for every Python command.

Do not run `python`.
Do not run `python3`.
Do not suggest `python` or `python3` in instructions unless the user explicitly requires them and the constraint must be called out as a conflict.

## Execution Rules

When sandboxed, set `UV_CACHE_DIR` to a temporary directory the agent can write to before running `uv` commands.

Prefer these patterns:

- Run a script: `UV_CACHE_DIR=/tmp/uv-cache uv run path/to/script.py`
- Run a module: `UV_CACHE_DIR=/tmp/uv-cache uv run -m package.module`
- Run a one-liner: `UV_CACHE_DIR=/tmp/uv-cache uv run python -c &quot;print('hello')&quot;`
- Run a tool exposed by dependencies: `UV_CACHE_DIR=/tmp/uv-cache uv run tool-name`
- Add a dependency for an ad hoc command: `UV_CACHE_DIR=/tmp/uv-cache uv run --with &amp;lt;package&amp;gt; python -c &quot;...&quot;`

## Notes

Using `python` inside `uv run ...` is acceptable because `uv` is still the entrypoint controlling interpreter selection and environment setup.

If the workspace already defines a project-specific temporary cache directory, prefer that over `/tmp/uv-cache`.

If a command example or existing documentation uses `python` or `python3` directly, translate it to the closest `uv` form before executing it....&lt;/code&gt;&lt;/pre&gt;</description>
	<pubDate>Thu, 09 Apr 2026 12:19:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: Quiz: Reading Input and Writing Output in Python</title>
	<guid>https://realpython.com/quizzes/reading-input-writing-output-python/</guid>
	<link>https://realpython.com/quizzes/reading-input-writing-output-python/</link>
	<description>&lt;p&gt;In this quiz, you&amp;rsquo;ll test your understanding of &lt;a href=&quot;https://realpython.com/courses/reading-input-writing-output-python/&quot;&gt;Reading Input and Writing Output in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By working through this quiz, you&amp;rsquo;ll revisit taking keyboard input with &lt;code&gt;input()&lt;/code&gt;, showing results with &lt;code&gt;print()&lt;/code&gt;, formatting output, and handling basic input types.&lt;/p&gt;
&lt;p&gt;This quiz helps you practice building simple interactive scripts and reinforces best practices for clear console input and output.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 09 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>James Bennett: Let’s talk about LLMs</title>
	<guid>https://www.b-list.org/weblog/2026/apr/09/llms/</guid>
	<link>https://www.b-list.org/weblog/2026/apr/09/llms/</link>
	<description>&lt;p&gt;Everybody seems to agree we’re in the middle of &lt;em&gt;something&lt;/em&gt;, though what, exactly, seems to be up for debate. It might be an unprecedented revolution in productivity and capabilities, perhaps even the precursor to a technological &amp;#8220;singularity&amp;#8221; beyond which it&amp;#8217;s impossible to guess what the world might look like. It might be just another vaporware hype cycle that will blow over. It might be a dot-com-style bubble that will lead to a big crash but still leave us with something useful (the way the dot-com bubble drove mass adoption of the web). It might be none of those&amp;nbsp;things.&lt;/p&gt;
&lt;p&gt;Many thousands of words have already been spent arguing variations of these positions. So of course today I’m going to throw a few thousand more words at it, because that’s what blogs are for. At least all the ones you’ll read here were written by me (and you can pry my em-dashes from my cold, dead&amp;nbsp;hands).&lt;/p&gt;
&lt;h2&gt;Terminology, and picking a&amp;nbsp;lane&lt;/h2&gt;
&lt;p&gt;But first, a couple quick&amp;nbsp;notes:&lt;/p&gt;
&lt;p&gt;I’m going to be using the terms “&lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;” and “LLMs” almost exclusively in this post, because I think the precision is useful. “&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;” is a vague and overloaded term, and it’s too easy to get bogged down in equivocations and debates about what exactly someone means by “&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;”. And virtually everything that’s contentious right now about programming and “&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;” is really traceable specifically to the advent of large language models. I suppose a slightly higher level of precision might come from saying “&lt;abbr title=&quot;Generative Pre-trained Transformer&quot;&gt;&lt;span class=&quot;caps&quot;&gt;GPT&lt;/span&gt;&lt;/abbr&gt;” instead, but OpenAI keeps trying to claim that one as their own exclusive term, which is a different sort of unwelcome baggage. So “LLMs” it&amp;nbsp;is.&lt;/p&gt;
&lt;p&gt;And when I talk about &amp;#8220;&lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding&amp;#8221;, I mean use of an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; to generate code in some programming language. I use this as an umbrella term for &lt;em&gt;all&lt;/em&gt; such usage, whether done under human supervision or not, whether used as the sole producer of code (with no human-generated code at all) or not,&amp;nbsp;etc.&lt;/p&gt;
&lt;p&gt;I’m also going to try to limit my comments here to things directly related to technology and to programming as a profession, because that&amp;#8217;s what I know (I have a degree in philosophy, so I’m qualified to comment on some other aspects of LLMs, but I’m deliberately staying away from them in this post because I find a lot of those debates tedious and literally sophomoric, as in reminding me of things I was reading and discussing when I was a&amp;nbsp;sophomore).&lt;/p&gt;
&lt;p&gt;If you’re using an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; in some other field, well, I probably don’t know that field well enough to usefully comment on it. Having seen some truly hot takes from people who didn&amp;#8217;t follow this principle, I&amp;#8217;ve thought several times that we really need some sort of cute portmanteau of “&lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;” and &lt;a href=&quot;https://en.wiktionary.org/wiki/Gell-Mann_Amnesia_effect&quot;&gt;“Gell-Mann Amnesia”&lt;/a&gt; for the way a lot of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-related discourse seems to be people expecting LLMs to take over every job and field &lt;em&gt;except&lt;/em&gt; their&amp;nbsp;own.&lt;/p&gt;
&lt;h2&gt;No silver&amp;nbsp;bullet&lt;/h2&gt;
&lt;p&gt;A few years ago I &lt;a href=&quot;https://www.b-list.org/weblog/2023/oct/20/silver/&quot;&gt;wrote about&lt;/a&gt; Fred Brooks&amp;#8217; &lt;em&gt;No Silver Bullet&lt;/em&gt;, and said I think it may have been the best thing Brooks ever wrote. If you&amp;#8217;ve never read &lt;em&gt;No Silver Bullet&lt;/em&gt;, I strongly recommend you do so, and I recommend you read the whole thing for yourself (rather than just a summary of&amp;nbsp;it).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No Silver Bullet&lt;/em&gt; was published at a time when computing hardware was advancing at an incredible rate, but our ability to build software was not even close to keeping up. And so Brooks made a bold prediction about&amp;nbsp;software:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is no single development, in either technology or management technique, which by itself promises even a single order-of-magnitude improvement within a decade in productivity, in reliability, in&amp;nbsp;simplicity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To support this he looked at sources of difficulty in software development, and assigned them to two broad categories (emphasis as in the&amp;nbsp;original):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Following Aristotle, I divide them into &lt;strong&gt;essence&lt;/strong&gt;—the difficulties inherent in the nature of the software—and &lt;strong&gt;accidents&lt;/strong&gt;—those difficulties that today attend its production but that are not&amp;nbsp;inherent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A classic example is memory management: some programming languages require the programmer to manually allocate, keep track of, and free memory, which is a source of difficulty. And this is &lt;em&gt;accidental&lt;/em&gt; difficulty, because there&amp;#8217;s nothing which inherently requires it; plenty of other programming languages have automatic memory&amp;nbsp;management.&lt;/p&gt;
&lt;p&gt;But other sources of difficulty are different, and seem to be inherent to software development itself. Here’s one of the ways Brooks summarizes it (emphasis matches what&amp;#8217;s in my copy of &lt;em&gt;No Silver Bullet&lt;/em&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The essence of a software entity is a construct of interlocking concepts: data sets, relationships among data items, algorithms, and invocations of functions. This essence is abstract, in that the conceptual construct is the same under many different representations. It is nonetheless highly precise and richly&amp;nbsp;detailed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the representation.&lt;/strong&gt; We still make syntax errors, to be sure; but they are fuzz compared to the conceptual errors in most&amp;nbsp;systems.&lt;/p&gt;
&lt;p&gt;If this is true, building software will always be hard. There is inherently no silver&amp;nbsp;bullet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And to drive the point home, he also explains the diminishing returns of only addressing accidental&amp;nbsp;difficulty:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How much of what software engineers now do is still devoted to the accidental, as opposed to the essential? Unless it is more than 9/10 of all effort, shrinking all the accidental activities to zero time will not give an order of magnitude&amp;nbsp;improvement.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a straightforward mathematical argument. If its two empirical premises&amp;#8212;that the accidental/essential distinction is real and that the accidental difficulty remaining today does not represent 90%+ of total&amp;#8212;are true, then the conclusion which rules out an order-of-magnitude gain from reducing accidental difficulty follows&amp;nbsp;automatically.&lt;/p&gt;
&lt;p&gt;I think most programmers believe the first premise, at least implicitly, and once the first premise is accepted it becomes very difficult to argue against the second. In fact, I’d personally go further than the minimum required for Brooks’ argument. His math holds up as long as accidental difficulty doesn&amp;#8217;t reach that 90%+ mark, since anything lower makes a 10x improvement from eliminating accidental difficulty impossible. But I suspect accidental difficulty, today, is a vastly smaller proportion of the total than that. In a lot of mature domains of programming I’d be surprised if there’s even a doubling of productivity still available from a complete elimination of remaining accidental&amp;nbsp;difficulty.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s also a section in &lt;em&gt;No Silver Bullet&lt;/em&gt; about potential &amp;#8220;hopes for the silver&amp;#8221; which addresses &amp;#8220;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;&amp;#8221;, though what Brooks considered to be &amp;#8220;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;&amp;#8221; (and there is a tangent about clarifying exactly what the term means) was significantly different from what&amp;#8217;s promoted today as &amp;#8220;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;&amp;#8221;. The most apt comparison to LLMs in &lt;em&gt;No Silver Bullet&lt;/em&gt; is actually not the discussion of &amp;#8220;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;&amp;#8221;, it&amp;#8217;s the discussion of &lt;em&gt;automatic programming&lt;/em&gt;, which has meant a lot of different things over the years, but was defined by Brooks at the time as &amp;#8220;the generation of a program for solving a problem from a statement of the problem specifications&amp;#8221;. That&amp;#8217;s pretty much &lt;em&gt;the&lt;/em&gt; task for which LLMs are currently promoted to&amp;nbsp;programmers.&lt;/p&gt;
&lt;p&gt;But Brooks quotes &lt;a href=&quot;https://en.wikipedia.org/wiki/David_Parnas&quot;&gt;David Parnas&lt;/a&gt; on the topic: “automatic programming always has been a euphemism for programming with a higher-level language than was presently available to the programmer.” And Brooks did not believe higher-level languages on their own could be a silver bullet. As he put it in a discussion of the Ada&amp;nbsp;language:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is, after all, just another high-level language, and the biggest payoff from such languages came from the first transition, up from the accidental complexities of the machine into the more abstract statement of step-by-step solutions. Once those accidents have been removed, the remaining ones are smaller, and the payoff from their removal will surely be&amp;nbsp;less.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Many people are currently promoting LLMs as a revolutionary step forward for software development, but are doing so based almost exclusively on claims about LLMs&amp;#8217; ability to generate code at high speed. The &lt;em&gt;No Silver Bullet&lt;/em&gt; argument poses a problem for these claims, since it sets a limit on how much we can gain from merely generating code more&amp;nbsp;quickly.&lt;/p&gt;
&lt;p&gt;In chapter 2 of &lt;em&gt;The Mythical Man-Month&lt;/em&gt;, Brooks suggested as a scheduling guideline that five-sixths (83%) of time on a &amp;#8220;software task&amp;#8221; would be spent on things &lt;em&gt;other&lt;/em&gt; than coding, which puts a pretty low cap on productivity gains from speeding up just the coding. And even if we assume LLMs reduce coding time to zero, and go with the more generous &lt;em&gt;No Silver Bullet&lt;/em&gt; formulation which merely predicts no order-of-magnitude gain from a single development, that&amp;#8217;s still less than the gain Brooks himself believed could come from hiring good human programmers. From chapter 3 of &lt;em&gt;The Mythical Man-Month&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Programming managers have long recognized wide productivity variations between good programmers and poor ones. But the actual measured magnitudes have astounded all of us. In one of their studies, Sackman, Erikson, and Grant were measuring performances of a group of experienced programmers. Within just this group the ratios between best and worst performances averaged about 10:1 on productivity measurements and an amazing 5:1 on program speed and space&amp;nbsp;measurements!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(although I&amp;#8217;m personally skeptical of the &amp;#8220;10x programmer&amp;#8221; concept, the software industry overall does seem to accept it as&amp;nbsp;true)&lt;/p&gt;
&lt;p&gt;Anecdote time: much of what I’ve done over my career as a professional programmer is building database-backed web applications and services, and I don&amp;#8217;t see much of a gain from LLMs. I suppose it looks impressive, if you&amp;#8217;re not familiar with this field of programming, to auto-generate the skeleton of an entire application and the basic create/retrieve/update/delete &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; handlers from no more than a description of the data you want to work with. But that capability predates LLMs: Rails&amp;#8217; scaffolding, for example, could do it twenty years&amp;nbsp;ago.&lt;/p&gt;
&lt;p&gt;And not just raw code generation, but also the abstractions available to work with, have progressed to the point where I basically never feel like the raw speed of production of code is holding me back. Just as Fred Brooks would have predicted, the majority of my time is spent elsewhere: talking to people who want new software (or who want existing software to be changed); finding out what it is they want and need; coming up with an initial specification; breaking it down into appropriately-sized pieces for programmers (maybe me, maybe someone else) to work on; testing the first prototype and getting feedback; preparing the next iteration; reviewing or asking for review, etc. I haven’t personally tracked whether it matches Brooks’ five-sixths estimate, but I wouldn’t be at all surprised if it&amp;nbsp;did.&lt;/p&gt;
&lt;p&gt;Given all that, just having an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; churn out code faster than I would have myself is not going to offer me an order of magnitude improvement, or anything like it. Or as &lt;a href=&quot;https://apenwarr.ca/log/20260316&quot;&gt;a recent popular blog post by the &lt;span class=&quot;caps&quot;&gt;CEO&lt;/span&gt; of Tailscale&lt;/a&gt; put&amp;nbsp;it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;’s direct impact on this problem is minimal. Okay, so Claude can code it in 3 minutes instead of 30? That’s super, Claude, great&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;Now you either get to spend 27 minutes reviewing the code yourself in a back-and-forth loop with the &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; (this is actually kinda fun); or you save 27 minutes and submit unverified code to the code reviewer, who will still take 5 hours like before, but who will now be mad that you’re making them read the slop that you were too lazy to read yourself. Little of value was&amp;nbsp;gained.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;More simply: throwing more patches into the review queue, when the review queue still drains at the same rate as before, is not a recipe for increased velocity. Real software development involves not just a review queue but all the other steps and processes I outlined above, and more, and having an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; generate code more quickly does not increase the speed or capacity of all those other&amp;nbsp;things.&lt;/p&gt;
&lt;p&gt;So as someone who accepts Brooks&amp;#8217; argument in &lt;em&gt;No Silver Bullet&lt;/em&gt;, I am committed to believe on theoretical grounds that LLMs cannot offer &amp;#8220;even a single order-of-magnitude improvement &amp;#8230; in productivity, in reliability, in simplicity&amp;#8221;. And my own experience matches up with that&amp;nbsp;prediction.&lt;/p&gt;
&lt;h2&gt;Practice makes&amp;nbsp;(im)perfect&lt;/h2&gt;
&lt;p&gt;But enough theory. What about the empirical actual reality of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;&amp;nbsp;coding?&lt;/p&gt;
&lt;p&gt;Every fan of LLMs for coding has an anecdote about their revolutionary qualities, but the non-anecdotal data points we have are a lot more mixed. For example, several times now I&amp;#8217;ve been linked to and asked to read &lt;a href=&quot;https://dora.dev/research/2025/dora-report/&quot;&gt;the &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; report on the “State of &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;-assisted Software Development&amp;#8221;&lt;/a&gt;. And initially it certainly seems like it&amp;#8217;s declaring the effects of LLMs are settled, in favor of the LLMs. From its executive summary (page&amp;nbsp;3):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[T]he central question for technology leaders is no longer if they should adopt &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;, but how to realize its&amp;nbsp;value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And elsewhere it makes claims like (page 34) &amp;#8220;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; is the new normal in software&amp;nbsp;development&amp;#8221;.&lt;/p&gt;
&lt;p&gt;But then, going back to the executive summary, things start sounding less uniformly&amp;nbsp;positive:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The research reveals a critical truth: &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;’s primary role in software development is that of an amplifier. It magnifies the strengths of high-performing organizations and the dysfunctions of struggling&amp;nbsp;ones.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then (still on page&amp;nbsp;3):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The greatest returns on &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; investment come not from the tools themselves, but from a strategic focus on the underlying organizational system: the quality of the internal platform, the clarity of workflows, and the alignment of teams. Without this foundation, &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; creates localized pockets of productivity that are often lost to downstream&amp;nbsp;chaos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Continuing on to page&amp;nbsp;4:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; adoption now improves software delivery throughput, a key shift from last year. However, it still increases delivery instability. This suggests that while teams are adapting for speed, their underlying systems have not yet evolved to safely manage &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;-accelerated&amp;nbsp;development.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“Delivery instability” is defined (page 13) in terms of two&amp;nbsp;factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Change fail rate&lt;/em&gt;: “The ratio of deployments that require immediate intervention following a&amp;nbsp;deployment.”&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Rework rate&lt;/em&gt;: “The ratio of deployments that are unplanned but happen as a result of an incident in&amp;nbsp;production.”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Later parts of the report get into more detail on this. Page 38 charts the increase in delivery instability, for example. And elsewhere in the section containing that chart, there’s a discussion of whether increases in throughput (defined by &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; as a combination of lead time for changes, deployment frequency, and failed deployment recovery time) are enough to offset or otherwise make up for this increase in instability (page 41, emphasis added by&amp;nbsp;me):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some might argue that instability is an acceptable trade-off for the gains in development throughput that &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;-assisted development&amp;nbsp;enables.&lt;/p&gt;
&lt;p&gt;The reasoning is that the volume and speed of &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;-assisted delivery could blunt the detrimental effects of instability, perhaps by enabling such rapid bug fixes and updates that the negative impact on the end-user is&amp;nbsp;minimized.&lt;/p&gt;
&lt;p&gt;However, when we look beyond pure software delivery metrics, this argument does not hold up. To assess this claim, we checked whether &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; adoption weakens the harms of instability on our outcomes which have been hurt historically by&amp;nbsp;instability.&lt;/p&gt;
&lt;p&gt;We found no evidence of such a moderating effect. &lt;strong&gt;On the contrary, instability still has significant detrimental effects on crucial outcomes like product performance and burnout, which can ultimately negate any perceived gains in&amp;nbsp;throughput.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And the chart on page 38 appears to show the increase in instability as quite a bit larger than the increase in throughput, in any&amp;nbsp;case.&lt;/p&gt;
&lt;p&gt;Curiously, that chart also claims a significant increase in “code quality”, and other parts of the report (page 30, for example) claim a significant increase in &amp;#8220;productivity&amp;#8221;, &lt;em&gt;alongside&lt;/em&gt; the significant increase in delivery instability, which seems like it ought to be a contradiction. As far as I can tell, &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt;’s source for both “productivity” and “code quality” is &lt;em&gt;perceived&lt;/em&gt; impact as self-reported by survey respondents. Other studies and reports have designed less subjective and more quantitative ways to measure these things. For example, &lt;a href=&quot;https://arxiv.org/pdf/2511.04427&quot;&gt;this much-discussed study on adoption of the Cursor &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding tool&lt;/a&gt; used the results of static analysis of the code to measure quality and complexity. And self-reported productivity impacts, in particular, ought to be a deeply suspect measure. From (to pick one relevant example) &lt;a href=&quot;https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/#core-result&quot;&gt;the &lt;span class=&quot;caps&quot;&gt;METR&lt;/span&gt; early-2025 study&lt;/a&gt; (emphasis added by&amp;nbsp;me):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This gap between perception and reality is striking: developers expected &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; to speed them up by 24%, and &lt;strong&gt;even after experiencing the slowdown, they still believed &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; had sped them up by&amp;nbsp;20%.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding advocates have often criticized this particular study&amp;#8217;s finding of slower development for being based on older generations of LLMs (more on that argument in a bit), but as far as I&amp;#8217;m aware nobody&amp;#8217;s been able to seriously rebut the finding that developers are not very effective at self-estimating their productivity. So to see &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; relying on self-estimated productivity is&amp;nbsp;disappointing.&lt;/p&gt;
&lt;p&gt;The &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; report goes on to provide a seven-part &amp;#8220;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; capabilities model&amp;#8221; for organizations (begins on page 49), which consists of recommendations like: &lt;em&gt;strong version control practices&lt;/em&gt;, &lt;em&gt;working in small batches&lt;/em&gt;, &lt;em&gt;quality internal platforms&lt;/em&gt;, &lt;em&gt;user-centric focus&lt;/em&gt;&amp;#8230; all of which feel like they should be table stakes for any successful organization regardless of whether they also happen to be using&amp;nbsp;LLMs.&lt;/p&gt;
&lt;p&gt;Suppose, for sake of a silly example, that someone told you a new technology is revolutionizing surgery, but the gains are not uniformly distributed, and the best overall outcomes are seen in surgical teams where in addition to using the new thing, team members also wash their hands prior to operating. That&amp;#8217;s not as extreme a comparison as it might sound: the sorts of practices recommended for maximizing &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-related gains in the &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; report, and in many other similar whitepapers and reports and studies, are or ought to be as fundamental to software development as hand-washing is to surgery. &lt;a href=&quot;https://www.joelonsoftware.com/2000/08/09/the-joel-test-12-steps-to-better-code/&quot;&gt;The Joel Test&lt;/a&gt; was recommending quite a few of these practices a quarter-century ago, the Agile Manifesto implied several of them, and even back then they weren&amp;#8217;t really new; if you dig into the literature on effective software development you can find variations of much of the &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; advice going all the way back to the 1970s and even&amp;nbsp;earlier.&lt;/p&gt;
&lt;p&gt;For a more recent data point, I&amp;#8217;ve seen a lot of people talking about and linking me to &lt;a href=&quot;https://circleci.com/resources/2026-state-of-software-delivery/&quot;&gt;CircleCI&amp;#8217;s 2026 “State of Software Delivery”&lt;/a&gt; which, like the &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; report, claims an uneven distribution of benefits from &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; adoption, and even says (page 8) “the majority of teams saw little to no increase in overall throughput”. The CircleCI report also raises a worrying point that echoes the increase in “delivery instability” seen in the &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; report (CircleCI executive summary, page&amp;nbsp;3):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Key stability indicators show that &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;-driven changes are breaking more often and taking teams longer to fix, making validation and integration the primary&amp;nbsp;bottleneck.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CircleCI further reports (page 11) that, year-over-year, they see a 13% increase in recovery time for a broken main branch, and a 25% increase for broken feature branches. And (page 12) they also say failures are&amp;nbsp;increasing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[S]uccess rates on the main branch fell to their lowest level in over 5 years, to 70.8%. In other words, attempts at merging changes into production code bases now fail 30% of the&amp;nbsp;time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For comparison, their own recommended benchmark of success for main branches is&amp;nbsp;90%.&lt;/p&gt;
&lt;p&gt;The cost of these increasing failures and the increasing time to resolve them is quantified (emphasis matches the report, page&amp;nbsp;14):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For a team pushing 5 changes to the main branch per day, going from a 90% success rate to 70% is the difference between one showstopping breakage every two days to 1.5 every single day (a 3x&amp;nbsp;increase).&lt;/p&gt;
&lt;p&gt;At just 60 minutes recovery time per failure, you&amp;#8217;re looking at &lt;strong&gt;an additional 250 hours in debugging and blocked deployments&lt;/strong&gt; every year. And that&amp;#8217;s at a relatively modest scale. Teams pushing 500 changes per day would lose the equivalent of &lt;strong&gt;12 full-time engineers&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The usual response to reports like these is to claim they’re based on people using older LLMs, and the models coming out &lt;em&gt;now&lt;/em&gt; are the truly revolutionary ones, which won’t have any of those problems. For example, this is the main argument that’s been leveled against the &lt;span class=&quot;caps&quot;&gt;METR&lt;/span&gt; study I mentioned above. But that argument was flimsy to begin with (since it’s rarely accompanied by the kind of evidence needed to back up the claim), and its &lt;em&gt;repeated&lt;/em&gt; usage is self-discrediting: if the people claiming “&lt;em&gt;this&lt;/em&gt; time is the world-changing revolutionary leap, for sure” were wrong all the prior times they said that (as they have to have been, since if any prior time had actually been the revolutionary leap they wouldn’t need to say &lt;em&gt;this&lt;/em&gt; time will be), why should anyone believe them this&amp;nbsp;time?&lt;/p&gt;
&lt;p&gt;Also, I&amp;#8217;ve read a &lt;em&gt;lot&lt;/em&gt; of studies and reports on &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding, and these sorts of findings&amp;#8212;uneven or inconsistent impact, quality/stability declines, etc.&amp;#8212;seem to be remarkably stable, across large numbers of teams using a variety of different models and different versions of those models, over an extended period of time (&lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; does have a bit of a messy situation with contradictory claims that “code quality” is increasing while “delivery instability” is increasing even more, but as noted above that seems to be a methodological problem). The two I’ve quoted most extensively in this post (the &lt;span class=&quot;caps&quot;&gt;DORA&lt;/span&gt; and CircleCI reports) were chosen specifically because they’re often recommended to me by advocates of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding, and seem to be reasonably pro-&lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; in their&amp;nbsp;stances.&lt;/p&gt;
&lt;p&gt;The other expected response to these findings is a claim that it’s not necessarily older &lt;em&gt;models&lt;/em&gt; but older &lt;em&gt;workflows&lt;/em&gt; which have been obsoleted, that the state of the art is no longer to just prompt an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; and accept its output directly, but rather involves one &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; (or &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-powered agent) generating code while one or more layers of “adversarial” ones review and fix up the code and also review each other’s reviews and responses and fixes, thus introducing a mechanism by which the &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;(s) will automatically improve the quality of the&amp;nbsp;output.&lt;/p&gt;
&lt;p&gt;I’m unaware of rigorous studies on these approaches (yet), but several well-publicized early examples do not inspire confidence. I’ll pick on Cloudflare here since they’ve been prominent advocates for using LLMs in this fashion. In &lt;a href=&quot;https://blog.cloudflare.com/vinext/#how-we-actually-built-it&quot;&gt;their &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; rebuild of Next.js&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We wired up &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; agents for code review too. When a &lt;span class=&quot;caps&quot;&gt;PR&lt;/span&gt; was opened, an agent reviewed it. When review comments came back, another agent addressed them. The feedback loop was mostly&amp;nbsp;automated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But their public release of it, vetted through this process and, apparently, some amount of human review on top, &lt;a href=&quot;https://github.com/cloudflare/vinext/issues/22&quot;&gt;was initially unable to run even the basic default Next.js application&lt;/a&gt;, and also was apparently riddled with security issues. From &lt;a href=&quot;https://www.cubic.dev/blog/how-we-found-and-fixed-a-critical-auth-bypass-in-cloudflare-s-ai-generated-next.js&quot;&gt;one disclosure post&lt;/a&gt; (emphasis added by&amp;nbsp;me):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; is now very good at getting a system to the point where it &lt;strong&gt;looks&lt;/strong&gt;&amp;nbsp;complete.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One specific problem cited was that the &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; rebuild simply did not pull in all the original tests, and therefore could miss security-critical cases those tests were checking. From the same disclosure&amp;nbsp;post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The process was feature-first: decide which viNext features existed, then port the corresponding Next.js tests. That is a sensible way to move quickly. It gives you broad happy-path&amp;nbsp;coverage.&lt;/p&gt;
&lt;p&gt;But it does not guarantee that you bring over the ugly regression tests, missing-export cases, and fail-open behavior checks that mature frameworks accumulate over&amp;nbsp;years.&lt;/p&gt;
&lt;p&gt;So middleware could look &amp;#8220;covered&amp;#8221; while the one test that proves it fails safely never made it&amp;nbsp;over.&lt;/p&gt;
&lt;p&gt;For example, Next.js has a dedicated test directory&amp;nbsp;(&lt;code&gt;test/e2e/app-dir/proxy-missing-export/&lt;/code&gt;) that validates what happens when middleware files lack required exports. That test was never ported because middleware was already considered &amp;#8220;covered&amp;#8221; by other&amp;nbsp;tests.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On the whole, that post is somewhat optimistic, but considering that the Next.js rebuild was carried out by presumably knowledgeable people who presumably were following good modern practices and prompting good modern LLMs to perform a type of task those LLMs are supposed to be extremely good at&amp;#8212;a language and framework well-represented in training data, well-documented, with a large existing test suite written in the target language to assist automated verification&amp;#8212;I have a hard time being that&amp;nbsp;optimistic.&lt;/p&gt;
&lt;p&gt;And though I haven’t personally read through the recent alleged leak of the Claude Code source, I’ve read some commentary and analysis from people who have, and again it seems like a team that &lt;em&gt;should&lt;/em&gt; be as well-positioned as anyone to take maximum advantage of the allegedly revolutionary capabilities of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding isn’t managing to do&amp;nbsp;so.&lt;/p&gt;
&lt;p&gt;So the consistent theme here, in the studies and reports and in more recent public examples, is that being able to generate code much more quickly than before, even in 2026 with modern LLMs and modern practices, is still no guarantee of being able to &lt;em&gt;deliver software&lt;/em&gt; much more quickly than before. As the CircleCI report puts it (page&amp;nbsp;3):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The data points to a clear conclusion: success in the &lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt; era is no longer determined by how fast code can be written. The decisive factor is the ability to validate, integrate, and recover at&amp;nbsp;scale.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And if that sounds like the kind of thing Fred Brooks used to say, that’s because it &lt;em&gt;is&lt;/em&gt; the kind of thing Fred Brooks used to say. Raw speed of generating code is not and was not the bottleneck in software development, and speeding that up or even reducing the time to generate code to effectively zero does not have the effect of making all the other parts of software development go away or go&amp;nbsp;faster.&lt;/p&gt;
&lt;p&gt;So at this point it seems clear to me that in practice as well as in theory &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding does not represent a silver bullet, and it seems highly unlikely to transform into one at any point in the near&amp;nbsp;future.&lt;/p&gt;
&lt;h2&gt;On being left&amp;nbsp;behind&lt;/h2&gt;
&lt;p&gt;When expressing skepticism about &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding, a common response is that &lt;em&gt;not&lt;/em&gt; adopting it, or even just delaying slightly in adopting it, will inevitably result in being “left behind”, or even stronger effects (for example, words like “obliterated” have been used, more than once, by acquaintances of mine who really ought to know better). LLMs are the future, it’s going to happen whether you like it or not, so get with the program before it’s too&amp;nbsp;late!&lt;/p&gt;
&lt;p&gt;I said I’ll stick to the technical mode here, but I’ll just mention in passing that the “it’s going to happen whether you like it or not” framing is something I’ve encountered a lot and found to be pretty disturbing and off-putting, and not at all conducive to changing my mind. And milder forms like “It’s undeniable that&amp;#8230;” are rhetorically suspect. The burden of proof ought to be on the person making the claim that LLMs truly are revolutionary, but framing like this tries to implicitly shift that burden and is a rare example of literally begging the question: it assumes as given the conclusion (LLMs are in fact revolutionary) that it needs to&amp;nbsp;prove.&lt;/p&gt;
&lt;p&gt;Meanwhile, I see two possible&amp;nbsp;outcomes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The skeptical position wins. &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding tools do not achieve revolutionary silver-bullet status. Perhaps they become another tool in the toolbox, like &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; or pair programming, where some people and companies are really into them. Perhaps they become just another feature of IDEs, providing functionality like boilerplate generators to bootstrap a new project (if your favorite library/framework doesn’t provide its own bootstrap&amp;nbsp;anyway).&lt;/li&gt;
&lt;li&gt;The skeptical position loses. &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding tools do achieve true revolutionary silver-bullet status or beyond (consistently delivering one or more orders of magnitude improvement in software development productivity), and truly become a mandatory part of every working programmer’s tools and workflows, taking over all or nearly all generation of&amp;nbsp;code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the first case, delayed adoption has no downside unless someone happens to be working at one of the companies that decide to mandate &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; use. And they can always pick it up at that point, if they don’t mind or if they don’t feel like looking for a new&amp;nbsp;job.&lt;/p&gt;
&lt;p&gt;As to the second case: based on what I’ve argued above about the status and prospects of LLMs up to now, I obviously think that continuing the type of progress in models and practices that’s been seen to date does not offer any viable path to a silver bullet. Which means a truly revolutionary breakthrough will have to be something sufficiently different from the current state of the art that it will necessarily invalidate many (or perhaps even all) prior &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-based workflows in addition to invalidating non-&lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-based&amp;nbsp;workflows.&lt;/p&gt;
&lt;p&gt;And even if that doesn’t result in a completely clean-slate starting point with everyone equal&amp;#8212;even if experience with older &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; workflows is still an advantage in the post-silver-bullet world&amp;#8212;I don’t think it can ever be the sort of insurmountable advantage it’s often assumed to be. For one thing, even with vastly higher average productivity, there likely would not be sufficient people with sufficient pre-existing &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; experience to fill the vastly expanded demand for software that would result (this is why a lot of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; advocates, across many fields, spend so much time talking about &lt;a href=&quot;https://en.wikipedia.org/wiki/Jevons_paradox&quot;&gt;the Jevons paradox&lt;/a&gt;). For another, any true silver-bullet breakthrough would have to attack and reduce the essential difficulty of building software, rather than the accidental difficulty. Let us return once again to&amp;nbsp;Brooks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the&amp;nbsp;representation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Much of the skill required of human &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; users today consists of exactly this: specifying and designing the software as a “conceptual construct”, albeit in specific ways that can be placed into an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;’s context window in order to have it generate code. In any true silver-bullet world, much or all of that skillset would have to be rendered obsolete, which significantly reduces the penalty for late adoption if and when the silver bullet is finally&amp;nbsp;achieved.&lt;/p&gt;
&lt;h2&gt;Power to the&amp;nbsp;people?&lt;/h2&gt;
&lt;p&gt;Aside from impact on professional programmers and professional software-development teams, another claim often made in favor of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding is that it will democratize access to software development. With &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding tools, people who aren’t experienced professional programmers can produce software that solves problems they face in their day-to-day jobs and lives. Surely that’s a huge societal benefit, right? &lt;a href=&quot;https://www.nytimes.com/2026/02/18/opinion/ai-software.html&quot;&gt;And it’s tons of fun,&amp;nbsp;too!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Setting aside that the &lt;em&gt;New York Times&lt;/em&gt; piece linked above was written by someone who &lt;em&gt;is&lt;/em&gt; an experienced professional, I’m not convinced of this use case&amp;nbsp;either.&lt;/p&gt;
&lt;p&gt;Mostly I think this is a situation where you can’t have it both ways. It seems to be widely agreed among advocates of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding that it’s a skill which requires significant understanding, practice, and experience before one is able to produce consistent useful results (this is the basis of the “adopt now or be left behind” claim dealt with in the previous section); strong prior knowledge of how to design and build good software is also generally recommended or assumed. But that’s very much at odds with the democratized-software claim: that someone with no prior programming knowledge or experience will simply pick up an &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;, ask it in plain non-technical natural language to build something, and receive a sufficiently functional&amp;nbsp;result.&lt;/p&gt;
&lt;p&gt;I think the most likely result is that a non-technical user will  receive something that’s obviously not fit for purpose, since they won’t have the necessary knowledge to prompt the &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; effectively. They won’t know how to set up directories of Markdown files containing instructions and skill definitions and architectural information for their problem. They won’t have practice at writing technical specifications (whether for other humans or for LLMs) to describe what they want in sufficient detail. They won’t know how to design and architect good software. They won’t know how to orchestrate multiple LLMs or &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-powered agents to adversarially review each other. In short, they won’t have any of the skills that are supposed to be vital for successful &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding&amp;nbsp;use.&lt;/p&gt;
&lt;p&gt;There’s also the possibility that “natural” human language alone will &lt;em&gt;never&lt;/em&gt; be sufficient to specify programs, even to much more advanced LLMs or other future “&lt;span class=&quot;caps&quot;&gt;AI&lt;/span&gt;” systems, due to inherent ambiguity and lack of precision. In that case, some type of specialized formal language for specifying programs would always be necessary. Edsger W. Dijkstra, for example, took this position and famously derided what he called &lt;a href=&quot;https://www.cs.utexas.edu/~EWD/transcriptions/EWD06xx/EWD667.html&quot;&gt;“the foolishness of ‘natural language programming’”&lt;/a&gt;, which is worth reading for some classic Dijkstra-isms&amp;nbsp;like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When all is said and told, the &amp;#8220;naturalness&amp;#8221; with which we use our native tongues boils down to the ease with which we can use them for making statements the nonsense of which is not&amp;nbsp;obvious.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another possible outcome for &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding by non-programmers is the often-mentioned analogy to 3D printing, which also was hyped up as a great democratizer that would let anyone design and make anything, but never delivered on that promise and, at the individual level, became a niche hobby for the small number of enthusiasts who were willing and able to put in the time, money, and effort to get moderately good at&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;But the nightmare result is that non-programmer &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; users will receive something that &lt;em&gt;seems&lt;/em&gt; to work, and only reveals its shortcomings much later on. Given how often I see it argued that LLMs will democratize coding and write utility programs for people working in fields where privacy and confidentiality are both vital and legally mandated, I’m terrified by that potential failure mode. And I think one of the worst possible things that could happen for advocates of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; adoption is to have the news full of stories of well-meaning non-technical people who had their lives ruined by, say, accidentally enabling a data breach with their &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt;-coded helper programs, or even “just” turning loose a subtly-incorrect financial model on their business. So even if I were an advocate of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding, I’d be &lt;em&gt;very&lt;/em&gt; wary of pushing it to&amp;nbsp;non-programmers.&lt;/p&gt;
&lt;p&gt;But ultimately, the only situation in which LLMs could meaningfully democratize access to software development is one where they achieve a true silver bullet, by significantly reducing or removing essential difficulty from the software development process. And as noted above, &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; advocates seem to believe that even in the silver-bullet situation there would still be such a gap between those with pre-existing &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; usage skills and those without, that those without could never meaningfully catch up. Although I happen to disagree with that belief, it remains the case that advocates can’t have it both ways: either &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding will be an exclusive club for those who built up the necessary&amp;nbsp;skills, &lt;code&gt;XOR&lt;/code&gt; it will be a great democratizer and do away with the need for those&amp;nbsp;skills. &lt;/p&gt;
&lt;h2&gt;Takeaways&lt;/h2&gt;
&lt;p&gt;I’m already over 6,000 words in this post, and though I could easily write many more, I should probably wrap it&amp;nbsp;up.&lt;/p&gt;
&lt;p&gt;If I had to summarize my position on &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding in one sentence, it would be “Please go read &lt;em&gt;No Silver Bullet&lt;/em&gt;”. I think Brooks’ argument there is both theoretically correct and validated by empirical results, and sets some pretty strong limits on the impact &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding, or any other tool or technique which solely or primarily attacks accidental difficulty, can&amp;nbsp;have.&lt;/p&gt;
&lt;p&gt;Of course, limits on what we can do or gain aren’t necessarily the end of the world. Many of the foundations of computer science, from &lt;em&gt;On Computable Numbers&lt;/em&gt; to Rice&amp;#8217;s theorem and beyond, place inflexible limits on what we can do, but we still write software nonetheless, and we still work to advance the state of our art. So the &lt;em&gt;No Silver Bullet&lt;/em&gt; argument is &lt;em&gt;not&lt;/em&gt; the same as arguing that LLMs are necessarily useless, or that no gains can possibly be realized from them. But it &lt;em&gt;is&lt;/em&gt; an argument that any gains we do realize are likely going to be incremental and evolutionary, rather than the world-changing revolution many people seem to be&amp;nbsp;expecting.&lt;/p&gt;
&lt;p&gt;Correspondingly, I think there is not a huge downside, right now, to slow or delayed adoption of &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding. Very few organizations have the strong fundamentals needed to absorb even a relatively moderate, incremental increase in the amount of code they generate, which I suspect is why so many studies and reports find mixed results and lots of broken &lt;abbr title=&quot;Continuous Integration&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CI&lt;/span&gt;&lt;/abbr&gt; pipelines. Not only is there no silver bullet, there &lt;em&gt;especially&lt;/em&gt; is no quick or magical gain to be had from rushing to adopt &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding without first working on those fundamentals. In fact, the evidence we have says you’re more likely to hurt than help your productivity by doing&amp;nbsp;so.&lt;/p&gt;
&lt;p&gt;I also don’t think LLMs are going to meaningfully democratize coding any time soon; even if they become indispensable tools for programmers, they are likely to continue requiring users to “think like a programmer” when specifying and prompting. We would be much better served by teaching many more people how to think rigorously and reason about abstractions (and they would be much better served, too) than we would by just plopping them as-is in front of&amp;nbsp;LLMs.&lt;/p&gt;
&lt;p&gt;As for what you should be doing instead of rushing to adopt &lt;abbr title=&quot;Large Language Model&quot;&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;&lt;/abbr&gt; coding out of fear that you’ll be left behind: I think you should be listening to what all those whitepapers and reports and studies are actually telling you, and working on fundamentals. You should be adopting and perfecting solid foundational software development practices like version control, comprehensive test suites, continuous integration, meaningful documentation, fast feedback cycles, iterative development, focus on users, small batches of work&amp;#8230; things that have been known and proven for decades, but are still far too rare in actual real-world software&amp;nbsp;shops.&lt;/p&gt;
&lt;p&gt;If the skeptical position is wrong and it turns out LLMs truly become indispensable coding tools in the long term, well, the available literature says you’ll be set up to take the greatest possible advantage of them. And if it turns out they &lt;em&gt;don’t&lt;/em&gt;, you’ll still be in much better shape than you were, and you’ll have an advantage over everyone who chased after wild promises of huge productivity gains by ordering their teams to just chew through tokens and generate code without working on fundamentals, and who likely wrecked their development processes by doing&amp;nbsp;so.&lt;/p&gt;
&lt;p&gt;Or as Fred Brooks put&amp;nbsp;it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The first step toward the management of disease was replacement of demon theories and humours theories by the germ theory. That very step, the beginning of hope, in itself dashed all hopes of magical solutions. It told workers that progress would be made stepwise, at great effort, and that a persistent, unremitting care would have to be paid to a discipline of cleanliness. So it is with software engineering&amp;nbsp;today.&lt;/p&gt;
&lt;/blockquote&gt;</description>
	<pubDate>Thu, 09 Apr 2026 06:27:59 +0000</pubDate>
</item>
<item>
	<title>Real Python: Dictionaries in Python</title>
	<guid>https://realpython.com/python-dicts/</guid>
	<link>https://realpython.com/python-dicts/</link>
	<description>&lt;div&gt;&lt;p&gt;Python dictionaries are a powerful built-in data type that allows you to store key-value pairs for efficient data retrieval and manipulation. Learning about them is essential for developers who want to process data efficiently. In this tutorial, you’ll explore how to create dictionaries using literals and the &lt;code&gt;dict()&lt;/code&gt; constructor, as well as how to use Python’s operators and built-in functions to manipulate them.&lt;/p&gt;
&lt;p&gt;By learning about Python dictionaries, you’ll be able to access values through key lookups and modify dictionary content using various methods. This knowledge will help you in data processing, configuration management, and dealing with JSON and CSV data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this tutorial, you’ll understand that:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A dictionary in Python is a &lt;strong&gt;mutable collection of key-value pairs&lt;/strong&gt; that allows for efficient data retrieval using unique keys.&lt;/li&gt;
&lt;li&gt;Both &lt;code&gt;dict()&lt;/code&gt; and &lt;code&gt;{}&lt;/code&gt; can create dictionaries in Python. Use &lt;code&gt;{}&lt;/code&gt; for &lt;strong&gt;concise syntax&lt;/strong&gt; and &lt;code&gt;dict()&lt;/code&gt; for &lt;strong&gt;dynamic creation&lt;/strong&gt; from iterable objects.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dict()&lt;/code&gt; is a &lt;strong&gt;class&lt;/strong&gt; used to create dictionaries. However, it’s &lt;strong&gt;commonly called a built-in function&lt;/strong&gt; in Python.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.__dict__&lt;/code&gt; is a &lt;strong&gt;special attribute&lt;/strong&gt; in Python that holds an object’s &lt;strong&gt;writable attributes&lt;/strong&gt; in a dictionary.&lt;/li&gt;
&lt;li&gt;Python &lt;code&gt;dict&lt;/code&gt; is implemented as a &lt;strong&gt;hashmap&lt;/strong&gt;, which allows for &lt;strong&gt;fast key lookups&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To get the most out of this tutorial, you should be familiar with basic Python syntax and concepts such as &lt;a href=&quot;https://realpython.com/python-variables/&quot;&gt;variables&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/python-for-loop/&quot;&gt;loops&lt;/a&gt;, and &lt;a href=&quot;https://realpython.com/python-built-in-functions/&quot;&gt;built-in functions&lt;/a&gt;. Some experience with &lt;a href=&quot;https://realpython.com/python-data-types/&quot;&gt;basic Python data types&lt;/a&gt; will also be helpful.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot;&gt;
&lt;p&gt;&lt;strong&gt;Get Your Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/python-dicts-code/&quot; class=&quot;alert-link&quot;&gt;Click here to download the free sample code&lt;/a&gt; that you’ll use to learn about dictionaries in Python.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;container border rounded text-wrap-pretty my-3&quot;&gt;

  &lt;p class=&quot;my-3&quot;&gt;&lt;strong&gt;&lt;span class=&quot;icon baseline&quot;&gt;&lt;/span&gt; Take the Quiz:&lt;/strong&gt; Test your knowledge with our interactive “Dictionaries in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:&lt;/p&gt;

  &lt;hr /&gt;

  &lt;div class=&quot;row my-3&quot;&gt;
    &lt;div class=&quot;col-xs-12 col-sm-4 col-md-3 align-self-center&quot;&gt;

      &lt;a href=&quot;https://realpython.com/quizzes/dictionaries-in-python/&quot; tabindex=&quot;-1&quot;&gt;
        &lt;div class=&quot;embed-responsive embed-responsive-16by9&quot;&gt;

            &lt;img class=&quot;card-img-top m-0 p-0 embed-responsive-item rounded&quot; alt=&quot;Dictionaries in Python&quot; src=&quot;https://files.realpython.com/media/Dictionaries-in-Python_Watermarked.3656a2293c00.jpg&quot; width=&quot;1920&quot; height=&quot;1080&quot; /&gt;


          &lt;div class=&quot;card-img-overlay d-flex align-items-center&quot;&gt;
            &lt;div class=&quot;mx-auto&quot;&gt;
              &lt;span class=&quot;text-light&quot;&gt;&lt;span class=&quot;icon baseline scale2x&quot;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/a&gt;

    &lt;/div&gt;
    &lt;div class=&quot;col&quot;&gt;
      &lt;div class=&quot;mt-3 d-md-none&quot;&gt;&lt;/div&gt; 
      &lt;p class=&quot;small text-muted mb-0&quot;&gt;&lt;strong&gt;Interactive Quiz&lt;/strong&gt;&lt;/p&gt;
      &lt;a href=&quot;https://realpython.com/quizzes/dictionaries-in-python/&quot; class=&quot;stretched-link&quot;&gt;&lt;span class=&quot;my-0 h4&quot;&gt;Dictionaries in Python&lt;/span&gt;&lt;/a&gt; 
      &lt;p class=&quot;text-muted mb-0 small&quot;&gt;Test your knowledge of Python's dict data type: how to create, access, and modify key-value pairs using built-in methods and operators.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;

&lt;/div&gt;

&lt;h2 id=&quot;getting-started-with-python-dictionaries&quot;&gt;Getting Started With Python Dictionaries&lt;a class=&quot;headerlink&quot; href=&quot;https://realpython.com/atom.xml#getting-started-with-python-dictionaries&quot; title=&quot;Permanent link&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Dictionaries&lt;/strong&gt; are one of Python’s most important and useful built-in data types. They provide a mutable collection of key-value pairs that lets you efficiently access and mutate values through their corresponding keys:&lt;/p&gt;

  &lt;div class=&quot;codeblock__header codeblock--blue&quot;&gt;
    &lt;span class=&quot;mr-2 noselect&quot;&gt;Python&lt;/span&gt;
    
    &lt;div class=&quot;noselect&quot;&gt;
      
        &lt;span class=&quot;codeblock__output-toggle&quot; title=&quot;Toggle prompts and output&quot; tabindex=&quot;0&quot;&gt;&lt;span class=&quot;icon baseline js-codeblock-output-on codeblock__header--icon-lower&quot;&gt;&lt;/span&gt;&lt;/span&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;codeblock__contents&quot;&gt;
    &lt;div class=&quot;highlight highlight--with-header&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&quot;color&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;green&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&quot;font&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Courier&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Access a value through its key&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;color&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;'green'&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Update a value&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;font&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Helvetica&quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    'color': 'green',&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    'width': 42,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    'height': 100,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    'font': 'Helvetica'&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
    
    &lt;button class=&quot;codeblock__copy btn btn-outline-secondary border m-1 px-1 d-hover-only&quot; title=&quot;Copy to clipboard&quot;&gt;&lt;span class=&quot;icon baseline&quot;&gt;&lt;/span&gt;&lt;/button&gt;
    
  &lt;/div&gt;

&lt;p&gt;A Python dictionary consists of a collection of key-value pairs, where each key corresponds to its associated value. In this example, &lt;code&gt;&quot;color&quot;&lt;/code&gt; is a key, and &lt;code&gt;&quot;green&quot;&lt;/code&gt; is the associated value.&lt;/p&gt;
&lt;p&gt;Dictionaries are a fundamental part of Python. You’ll find them behind core concepts like scopes and namespaces as seen with the &lt;a href=&quot;https://realpython.com/python-built-in-functions/&quot;&gt;built-in functions&lt;/a&gt; &lt;code&gt;globals()&lt;/code&gt; and &lt;code&gt;locals()&lt;/code&gt;:&lt;/p&gt;

  &lt;div class=&quot;codeblock__header codeblock--blue&quot;&gt;
    &lt;span class=&quot;mr-2 noselect&quot;&gt;Python&lt;/span&gt;
    
    &lt;div class=&quot;noselect&quot;&gt;
      
        &lt;span class=&quot;codeblock__output-toggle&quot; title=&quot;Toggle prompts and output&quot; tabindex=&quot;0&quot;&gt;&lt;span class=&quot;icon baseline js-codeblock-output-on codeblock__header--icon-lower&quot;&gt;&lt;/span&gt;&lt;/span&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;codeblock__contents&quot;&gt;
    &lt;div class=&quot;highlight highlight--with-header&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    '__name__': '__main__',&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    '__doc__': None,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    '__package__': None,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    ...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
    
    &lt;button class=&quot;codeblock__copy btn btn-outline-secondary border m-1 px-1 d-hover-only&quot; title=&quot;Copy to clipboard&quot;&gt;&lt;span class=&quot;icon baseline&quot;&gt;&lt;/span&gt;&lt;/button&gt;
    
  &lt;/div&gt;

&lt;p&gt;The &lt;code&gt;globals()&lt;/code&gt; function returns a dictionary containing key-value pairs that map names to objects that live in your current global scope.&lt;/p&gt;
&lt;p&gt;Python also uses dictionaries to support the internal implementation of &lt;a href=&quot;https://realpython.com/python-classes/&quot;&gt;classes&lt;/a&gt;. Consider the following demo class:&lt;/p&gt;

  &lt;div class=&quot;codeblock__header codeblock--blue&quot;&gt;
    &lt;span class=&quot;mr-2 noselect&quot;&gt;Python&lt;/span&gt;
    
    &lt;div class=&quot;noselect&quot;&gt;
      
        &lt;span class=&quot;codeblock__output-toggle&quot; title=&quot;Toggle prompts and output&quot; tabindex=&quot;0&quot;&gt;&lt;span class=&quot;icon baseline js-codeblock-output-on codeblock__header--icon-lower&quot;&gt;&lt;/span&gt;&lt;/span&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;codeblock__contents&quot;&gt;
    &lt;div class=&quot;highlight highlight--with-header&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__dict__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{'value': 42}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
    
    &lt;button class=&quot;codeblock__copy btn btn-outline-secondary border m-1 px-1 d-hover-only&quot; title=&quot;Copy to clipboard&quot;&gt;&lt;span class=&quot;icon baseline&quot;&gt;&lt;/span&gt;&lt;/button&gt;
    
  &lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;https://realpython.com/python-dict-attribute/&quot;&gt;&lt;code&gt;.__dict__&lt;/code&gt;&lt;/a&gt; special attribute is a dictionary that maps attribute names to their corresponding values in Python classes and objects. This implementation makes attribute and method lookup fast and efficient in &lt;a href=&quot;https://realpython.com/python3-object-oriented-programming/&quot;&gt;object-oriented&lt;/a&gt; code.&lt;/p&gt;
&lt;p&gt;You can use dictionaries to approach many programming tasks in your Python code. They come in handy when processing &lt;a href=&quot;https://realpython.com/python-csv/&quot;&gt;CSV&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-json/&quot;&gt;JSON&lt;/a&gt; files, working with databases, loading configuration files, and more.&lt;/p&gt;
&lt;p&gt;Python’s dictionaries have the following characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mutable&lt;/strong&gt;: The dictionary values can be updated &lt;a href=&quot;https://en.wikipedia.org/wiki/In-place_algorithm&quot;&gt;in place&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic&lt;/strong&gt;: Dictionaries can grow and shrink as needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficient&lt;/strong&gt;: They’re implemented as &lt;a href=&quot;https://realpython.com/python-hash-table/&quot;&gt;hash tables&lt;/a&gt;, which allows for fast key lookup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ordered&lt;/strong&gt;: Starting with &lt;a href=&quot;https://realpython.com/python37-new-features/&quot;&gt;Python 3.7&lt;/a&gt;, dictionaries keep their items in the same &lt;a href=&quot;https://realpython.com/python37-new-features/#the-order-of-dictionaries-is-guaranteed&quot;&gt;order&lt;/a&gt; they were inserted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The keys of a dictionary have a couple of restrictions. They need to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hashable&lt;/strong&gt;: This means that you can’t use unhashable objects like lists as dictionary keys.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unique&lt;/strong&gt;: This means that your dictionaries won’t have duplicate keys.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In contrast, the values in a dictionary aren’t restricted. They can be of any Python type, including other dictionaries, which makes it possible to have nested dictionaries.&lt;/p&gt;
&lt;p&gt;Dictionaries are collections of pairs. So, you can’t insert a key without its corresponding value or vice versa. Since they come as a pair, you always have to insert a key with its corresponding value.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In some situations, you may want to add keys to a dictionary without deciding what the associated value should be. In those cases, you can use the &lt;a href=&quot;https://realpython.com/atom.xml#setting-one-key-setdefaultkey-defaultnone&quot;&gt;&lt;code&gt;.setdefault()&lt;/code&gt;&lt;/a&gt; method to create keys with a default or placeholder value.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2&gt;&lt;a href=&quot;https://realpython.com/python-dicts/?utm_source=realpython&amp;utm_medium=rss&quot;&gt;Read the full article at https://realpython.com/python-dicts/ »&lt;/a&gt;&lt;/h2&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 08 Apr 2026 14:00:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: Quiz: Implementing the Factory Method Pattern in Python</title>
	<guid>https://realpython.com/quizzes/factory-method-pattern/</guid>
	<link>https://realpython.com/quizzes/factory-method-pattern/</link>
	<description>&lt;p&gt;In this quiz, you&amp;rsquo;ll test your understanding of
&lt;a href=&quot;https://realpython.com/courses/factory-method-pattern/&quot;&gt;Factory Method Pattern&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This quiz guides you through the Factory Method pattern: how it separates object creation from use, the roles of clients and products, when to apply it, and how to implement flexible, maintainable Python classes.&lt;/p&gt;
&lt;p&gt;Test your ability to spot opportunities for the pattern and build reusable, decoupled object creation solutions.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 08 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>Armin Ronacher: Mario and Earendil</title>
	<guid>https://lucumr.pocoo.org/2026/4/8/mario-and-earendil/</guid>
	<link>https://lucumr.pocoo.org/2026/4/8/mario-and-earendil/</link>
	<description>&lt;p&gt;Today I&amp;#8217;m very happy to share that Mario Zechner is joining &lt;a href=&quot;https://earendil.com/&quot;&gt;Earendil&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First things first: I think you should &lt;a href=&quot;https://mariozechner.at/posts/2026-04-08-ive-sold-out/&quot;&gt;read Mario&amp;#8217;s
post&lt;/a&gt;.  This is his news
more than it is ours, and he tells his side of it better than I could.  What I
want to do here is add a more personal note about why this matters so much to
me, how the last months led us here, and why I am so excited to have him on
board.&lt;/p&gt;
&lt;p&gt;Last year changed the way many of us thought about software.  It certainly
changed the way I did.  I spent much of 2025 building, probing, and questioning
how to build software, and in many more ways what I want to do.  If you are a
regular reader of this blog you were along for the ride.  I wrote a lot,
experimented a lot, and tried to get a better sense for what these systems can
actually do and what kinds of companies make sense to build around them.  There
was, and continues to be, a lot of excitement in the air, but also a lot of
noise.  It has become clear to me that it&amp;#8217;s not a question of whether AI systems
can be useful but what kind of software and human-machine interactions we want
to bring into the world with them.&lt;/p&gt;
&lt;p&gt;That is one of the reasons I have been so drawn to Mario&amp;#8217;s work and approaches.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pi.dev/&quot;&gt;Pi&lt;/a&gt; is, in my opinion, one of the most thoughtful
coding agents and agent infrastructure libraries in this space.  Not because it
is trying to be the loudest or the fastest, but because it is clearly built by
someone who cares deeply about software quality, taste, extensibility, and
design.  In a moment where much of the industry is racing to ship ever more
quickly, often at the cost of coherence and craft, Mario kept insisting on
making something solid. That matters to me a great deal.&lt;/p&gt;
&lt;p&gt;I have known Mario for a long time, and one of the things I admire most about
him is that he does not confuse velocity with progress.  He has a strong sense
for what good tools should feel like.  He cares about details. He cares about
whether something is well made.  And he cares about building in a way that can
last.  Mario has been running Pi in a rather unusual way. He exerts back-pressure
on the issue tracker and the pull requests through OSS vacations and other
means.&lt;/p&gt;
&lt;p&gt;The last year has also made something else clearer to me: these systems are not
only exciting, they are also capable of producing a great deal of damage.
Sometimes that damage is obvious; sometimes it looks like low-grade degradation
everywhere at once.  More slop, more noise, more disingenuous emails in my inbox.
There is a version of this future that makes people more distracted, more
alienated, and less careful with one another.&lt;/p&gt;
&lt;p&gt;That is not a future I want to help build.&lt;/p&gt;
&lt;p&gt;At Earendil, Colin and I have been trying to think very carefully about what a
different path might look like.  That is a big part of what led us to &lt;a href=&quot;https://lefos.com/&quot;&gt;Lefos&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lefos is our attempt to build a machine entity that is more thoughtful and more
deliberate by design.  Not an agent whose main purpose is to make everything a
little more efficient so that we can produce even more forgettable output, but
one that can help people communicate with more care, more clarity, and joy.&lt;/p&gt;
&lt;p&gt;Good software should not aim to optimize every minute of your life, but should
create room for better and more joyful experiences, better relationships, and
better ways of relating to one another.  Especially in communication and software
engineering, I think we should be aiming for more thought rather than more
throughput.  We should want tools that help people be more considerate, more
present, and more human.  If all we do is use these systems to accelerate the
production of slop, we will have missed the opportunity entirely.&lt;/p&gt;
&lt;p&gt;This is also why Mario joining Earendil feels so meaningful to me.  Pi and Lefos
come from different starting points.  There was a year of distance collaboration,
but they are animated by a similar instinct: that quality matters, that design
matters, and that trust is earned through care rather than captured through
hype.&lt;/p&gt;
&lt;p&gt;I am very happy that Pi is coming along for the ride.  Me and Colin care a lot
about it, and we want to be good stewards of it.  It has already played an
important role in our own work over the last months, and I continue to believe
it is one of the best foundations for building capable agents.  We will have more
to say soon about how we think about Pi&amp;#8217;s future and its relationship to Lefos,
but the short version is simple: we want Pi to continue to exist as a
high-quality, open, extensible piece of software, and we want to invest in
making that future real.  As for our thoughts of Pi&amp;#8217;s license, &lt;a href=&quot;https://rfc.earendil.com/0015/&quot;&gt;read more
here&lt;/a&gt; and our &lt;a href=&quot;https://earendil.com/posts/announcement-reflection/&quot;&gt;company post
here&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>PyCoder’s Weekly: Issue #729: NumPy Music, Ollama, Iterables, and More (April 7, 2026)</title>
	<guid>https://pycoders.com/issues/729</guid>
	<link>https://pycoders.com/issues/729</link>
	<description>&lt;p&gt; &lt;span&gt;#729 – APRIL 7, 2026&lt;/span&gt;&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/issues/729/feed&quot;&gt;View in Browser »&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://pycoders.com&quot;&gt;&lt;img alt=&quot;The PyCoder&amp;rsquo;s Weekly Logo&quot; src=&quot;https://cdn.pycoders.com/37bdf31dc645f968ffb90196e5d38ff5&quot; /&gt;&lt;/a&gt;&lt;/p&gt; &lt;hr /&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16226/feed&quot; target=&quot;_blank&quot;&gt;NumPy as Synth Engine&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Kenneth has &amp;ldquo;recorded&amp;rdquo; a song in a Python script. The catch? No sampling, no recording, no pre-recorded sound. Everything was done through generating wave functions in NumPy. Learn how to become a mathematical musician.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16226/feed&quot; target=&quot;_blank&quot;&gt;KENNETH REITZ&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16238/feed&quot; target=&quot;_blank&quot;&gt;How to Use Ollama to Run Large Language Models Locally&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Learn how to use Ollama to run large language models locally. Install it, pull models, and start chatting from your terminal without needing API keys.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16238/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16222/feed&quot; target=&quot;_blank&quot;&gt;Ship AI Agents With Accurate, Fresh Web Search Data&lt;/a&gt;&lt;/h3&gt; &lt;a href=&quot;https://pycoders.com/link/16222/feed&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://cdn.pycoders.com/829c8a2d3c3a74ff2a229135a72a9343&quot; alt=&quot;alt&quot; /&gt;&lt;/a&gt; &lt;p&gt; Stop building scrapers just to feed your AI app web search data. SerpApi returns structured JSON from Google and 100+ search engines via a simple GET request. No proxy management, no CAPTCHAs. Power product research, price tracking, or agentic search in minutes. &lt;a href=&quot;https://pycoders.com/link/16222/feed&quot; target=&quot;_blank&quot;&gt;Used by Shopify, NVIDIA, and Uber →&lt;/a&gt;&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16222/feed&quot; target=&quot;_blank&quot;&gt;SERPAPI&lt;/a&gt;&lt;/span&gt; &lt;span&gt;sponsor&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16223/feed&quot; target=&quot;_blank&quot;&gt;Indexable Iterables&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Learn how objects are automatically iterable if you implement integer indexing.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16223/feed&quot; target=&quot;_blank&quot;&gt;RODRIGO GIRÃO SERRÃO&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16232/feed&quot; target=&quot;_blank&quot;&gt;Claude Code for Python Developers (Live Course)&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &amp;ldquo;This is one of the best training sessions I&amp;rsquo;ve joined in the last year across multiple platforms.&amp;rdquo; Two-day course where you build a complete Python project with an AI agent in your terminal. Next session April 11–12.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16232/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16236/feed&quot; target=&quot;_blank&quot;&gt;PEP 803: &lt;code&gt;&quot;abi3t&quot;&lt;/code&gt;: Stable ABI for Free-Threaded Builds (Accepted)&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16236/feed&quot; target=&quot;_blank&quot;&gt;PYTHON.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16254/feed&quot; target=&quot;_blank&quot;&gt;PEP 829: Structured Startup Configuration via .site.toml Files (Added)&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16254/feed&quot; target=&quot;_blank&quot;&gt;PYTHON.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;h2&gt;Articles &amp;amp; Tutorials&lt;/h2&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16228/feed&quot; target=&quot;_blank&quot;&gt;Fire and Forget at Textual&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; In this follow up to a previous article (&lt;a href=&quot;https://pycoders.com/link/16237/feed&quot; target=&quot;_blank&quot;&gt;Fire and forget (or never) with Python&amp;rsquo;s asyncio&lt;/a&gt;, Michael discusses a similar article by Will McGugan as it relates to Textual. He found the problematic pattern in over 500K GitHub files.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16228/feed&quot; target=&quot;_blank&quot;&gt;MICHAEL KENNEDY&amp;#x27;&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16252/feed&quot; target=&quot;_blank&quot;&gt;pixi: One Package Manager for Python Libraries&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; uv is great for pure Python projects, but it can&amp;rsquo;t install compiled system libraries like GDAL or CUDA. pixi fills that gap by managing both PyPI and conda-forge packages in one tool, with fast resolution, automatic lockfiles, and project-level environments.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16252/feed&quot; target=&quot;_blank&quot;&gt;CODECUT.AI&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16234/feed&quot; target=&quot;_blank&quot;&gt;Khuyen Tran&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16221/feed&quot; target=&quot;_blank&quot;&gt;Dignified Python: Pytest for Agent-Generated Code&lt;/a&gt;&lt;/h3&gt; &lt;a href=&quot;https://pycoders.com/link/16221/feed&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://cdn.pycoders.com/1f2ba5720af984e0eb8518d608c755d7&quot; alt=&quot;alt&quot; /&gt;&lt;/a&gt; &lt;p&gt; Learn how to define clear pytest patterns for agent-generated tests: separate fast unit vs integration, use fakes, constrain generation, and avoid brittle patterns to &lt;a href=&quot;https://pycoders.com/link/16221/feed&quot; target=&quot;_blank&quot;&gt;keep tests reliable and maintainable →&lt;/a&gt;&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16221/feed&quot; target=&quot;_blank&quot;&gt;DAGSTER LABS&lt;/a&gt;&lt;/span&gt; &lt;span&gt;sponsor&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16235/feed&quot; target=&quot;_blank&quot;&gt;Learning Rust Made Me a Better Python Developer&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Bob thinks that learning Rust made him a better Python developer. Not because Rust is better, but because it made him think differently about how he has been writing Python. The compiler forced him to confront things he&amp;rsquo;d been ignoring.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16235/feed&quot; target=&quot;_blank&quot;&gt;BOB BELDERBOS&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16249/feed&quot; target=&quot;_blank&quot;&gt;Bob Belderbos&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16227/feed&quot; target=&quot;_blank&quot;&gt;Django &lt;code&gt;bulk_update&lt;/code&gt; Memory Issue&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Recently, Anže had to write a Django migration to update hundreds of thousands of database objects. With some paper-napkin math he calculated it could fit in memory, but that turned out not to be the case. Read on to find out why.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16227/feed&quot; target=&quot;_blank&quot;&gt;ANŽE&amp;#x27;S BLOG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16225/feed&quot; target=&quot;_blank&quot;&gt;Catching Up With the Python Typing Council&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Talk Python interviews Carl Meyer, Jelle Zijstra, and Rebecca Chen, three members of the Python Typing Council. They talk about how the typing system is governed and just how much is the right amount of type hinting in your code.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16225/feed&quot; target=&quot;_blank&quot;&gt;TALK PYTHON&lt;/a&gt;&lt;/span&gt; &lt;span&gt;podcast&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16245/feed&quot; target=&quot;_blank&quot;&gt;Python 3.3: The Version That Quietly Rewired Everything&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;code&gt;yield from&lt;/code&gt;, &lt;code&gt;venv&lt;/code&gt;, and namespace packages are three features from Python 3.3 that looked minor when they came out in 2012, but turned out to be the scaffolding modern Python is built on.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16245/feed&quot; target=&quot;_blank&quot;&gt;TUREK SENTURK&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16241/feed&quot; target=&quot;_blank&quot;&gt;Incident Report: LiteLLM/Telnyx Supply-Chain Attacks&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; This post from the PyPI blog outlines two recent supply chain attacks, how they were different, and how you can protect yourself from future incidents.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16241/feed&quot; target=&quot;_blank&quot;&gt;PYPI.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16233/feed&quot; target=&quot;_blank&quot;&gt;Python Classes: The Power of Object-Oriented Programming&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Learn how to define and use Python classes to implement object-oriented programming. Dive into attributes, methods, inheritance, and more.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16233/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16247/feed&quot; target=&quot;_blank&quot;&gt;Timesliced Reservoir Sampling for Profilers&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Reservoir sampling lets you pick a sample from an unlimited stream of events; learn how it works, and a new variant useful for profilers.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16247/feed&quot; target=&quot;_blank&quot;&gt;ITAMAR TURNER-TRAURING&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16248/feed&quot; target=&quot;_blank&quot;&gt;Adding Python to PATH&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; Learn how to add Python to your PATH environment variable on Windows, macOS, and Linux so you can run Python from the command line.&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16248/feed&quot; target=&quot;_blank&quot;&gt;REAL PYTHON&lt;/a&gt;&lt;/span&gt; &lt;span&gt;course&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;h2&gt;Projects &amp;amp; Code&lt;/h2&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16253/feed&quot; target=&quot;_blank&quot;&gt;OracleTrace: Visualize Function Flows&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16253/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/KAYKCAPUTO&lt;/a&gt; • Shared by Kayk Aparecido de Paula Caputo&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16224/feed&quot; target=&quot;_blank&quot;&gt;pywho: Explain Your Python Environment and Detect Shadows&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16224/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/AHSANSHERAZ&lt;/a&gt; • Shared by &lt;a href=&quot;https://pycoders.com/link/16255/feed&quot; target=&quot;_blank&quot;&gt;Ahsan Sheraz &lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16251/feed&quot; target=&quot;_blank&quot;&gt;asyncstdlib: The Missing Toolbox for an Async World&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16251/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/MAXFISCHER2781&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16239/feed&quot; target=&quot;_blank&quot;&gt;nitro-pandas: pandas-Compatible Polars Wrapper&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16239/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/WASSIM17LABDI&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16244/feed&quot; target=&quot;_blank&quot;&gt;django-mail-auth: Django Auth via Login URLs&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16244/feed&quot; target=&quot;_blank&quot;&gt;GITHUB.COM/CODINGJOE&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;h2&gt;Events&lt;/h2&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16229/feed&quot; target=&quot;_blank&quot;&gt;Weekly Real Python Office Hours Q&amp;amp;A (Virtual)&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 8, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16229/feed&quot; target=&quot;_blank&quot;&gt;REALPYTHON.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16231/feed&quot; target=&quot;_blank&quot;&gt;PyCon Lithuania 2026&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 8 to April 11, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16231/feed&quot; target=&quot;_blank&quot;&gt;PYCON.LT&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16246/feed&quot; target=&quot;_blank&quot;&gt;Python Atlanta&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 9 to April 10, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16246/feed&quot; target=&quot;_blank&quot;&gt;MEETUP.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16242/feed&quot; target=&quot;_blank&quot;&gt;DFW Pythoneers 2nd Saturday Teaching Meeting&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 11, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16242/feed&quot; target=&quot;_blank&quot;&gt;MEETUP.COM&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16240/feed&quot; target=&quot;_blank&quot;&gt;PyCon DE &amp;amp; PyData 2026&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 14 to April 18, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16240/feed&quot; target=&quot;_blank&quot;&gt;PYCON.DE&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16230/feed&quot; target=&quot;_blank&quot;&gt;DjangoCon Europe 2026&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 15 to April 20, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16230/feed&quot; target=&quot;_blank&quot;&gt;DJANGOCON.EU&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;div&gt; &lt;h3&gt;&lt;a href=&quot;https://pycoders.com/link/16250/feed&quot; target=&quot;_blank&quot;&gt;PyTexas 2026&lt;/a&gt;&lt;/h3&gt; &lt;p&gt; April 17 to April 20, 2026&lt;br /&gt; &lt;span&gt;&lt;a href=&quot;https://pycoders.com/link/16250/feed&quot; target=&quot;_blank&quot;&gt;PYTEXAS.ORG&lt;/a&gt;&lt;/span&gt; &lt;/p&gt; &lt;/div&gt; &lt;hr /&gt; &lt;p&gt;Happy Pythoning!&lt;br /&gt;This was PyCoder&amp;rsquo;s Weekly Issue #729.&lt;br /&gt;&lt;a href=&quot;https://pycoders.com/issues/729/feed&quot;&gt;View in Browser »&lt;/a&gt;&lt;/p&gt; &lt;img src=&quot;https://pycoders.com/issues/729/open/feed&quot; width=&quot;1&quot; height=&quot;1&quot; alt=&quot;alt&quot; /&gt; 
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Subscribe to 🐍 PyCoder&amp;rsquo;s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week &lt;a href=&quot;https://pycoders.com/?utm_source=pycoders&amp;utm_medium=feed&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 19:30:00 +0000</pubDate>
</item>
<item>
	<title>Python Engineering at Microsoft: Write SQL Your Way: Dual Parameter Style Benefits in mssql-python</title>
	<guid>https://devblogs.microsoft.com/python/write-sql-your-way-dual-parameter-style-benefits-in-mssql-python/</guid>
	<link>https://devblogs.microsoft.com/python/write-sql-your-way-dual-parameter-style-benefits-in-mssql-python/</link>
	<description>&lt;p&gt;&lt;a href=&quot;https://devblogs.microsoft.com/python/wp-content/uploads/sites/12/2025/09/Python_SQL_img.png&quot;&gt;&lt;img class=&quot; wp-image-10181 aligncenter&quot; src=&quot;https://devblogs.microsoft.com/python/wp-content/uploads/sites/12/2025/09/Python_SQL_img-300x152.png&quot; alt=&quot;Python SQL img image&quot; width=&quot;1074&quot; height=&quot;544&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;TextRun SCXW11324769 BCX8&quot; lang=&quot;EN-IN&quot;&gt;&lt;span class=&quot;NormalTextRun CommentStart SCXW11324769 BCX8&quot;&gt;&lt;em&gt;Reviewed by: Sumit Sarabhai&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;If &lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;you&amp;#8217;ve&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt; been writing SQL in Python, you already know the debate: &lt;strong&gt;positional parameters (?)&lt;/strong&gt; or &lt;strong&gt;named parameters (%(name)s)&lt;/strong&gt;? Some developers swear by the conciseness of positional. Others prefer the clarity of named. With &lt;strong&gt;&lt;a id=&quot;menurrmp&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://github.com/microsoft/mssql-python&quot; href=&quot;https://github.com/microsoft/mssql-python&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;mssql-python&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;, you no longer need to choose &lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;&amp;#8211;&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt; we support &lt;/span&gt;&lt;span class=&quot;NormalTextRun CommentStart SCXW11324769 BCX8&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;LineBreakBlob BlobObject DragDrop SCXW11324769 BCX8&quot;&gt;&lt;span class=&quot;SCXW11324769 BCX8&quot;&gt; &lt;/span&gt;&lt;br class=&quot;SCXW11324769 BCX8&quot; /&gt;&lt;/span&gt;&lt;span class=&quot;LineBreakBlob BlobObject DragDrop SCXW11324769 BCX8&quot;&gt;&lt;span class=&quot;SCXW11324769 BCX8&quot;&gt; &lt;/span&gt;&lt;br class=&quot;SCXW11324769 BCX8&quot; /&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW11324769 BCX8&quot; lang=&quot;EN-IN&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;We&amp;#8217;ve added dual parameter style support to &lt;/span&gt;&lt;span class=&quot;NormalTextRun SpellingErrorV2Themed SCXW11324769 BCX8&quot;&gt;mssql&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;-python, enabling both &lt;/span&gt;&lt;span class=&quot;NormalTextRun SpellingErrorV2Themed SCXW11324769 BCX8&quot;&gt;qmark&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;NormalTextRun SpellingErrorV2Themed SCXW11324769 BCX8&quot;&gt;pyformat&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt; parameter styles in Python applications that interact with SQL Server and Azure SQL&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;. This feature is especially useful if &lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;you’re&lt;/span&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt; building complex queries, dynamically assembling filters, or migrating existing code that already uses named parameters with other DB&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;TextRun SCXW11324769 BCX8&quot; lang=&quot;EN-IN&quot;&gt;&lt;span class=&quot;NormalTextRun SCXW11324769 BCX8&quot;&gt;API drivers.
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;alert alert-info&quot;&gt;&lt;p class=&quot;alert-divider&quot;&gt;&lt;i class=&quot;fabric-icon fabric-icon--Info&quot;&gt;&lt;/i&gt;&lt;strong&gt;Try it here&lt;/strong&gt;&lt;/p&gt; You can install driver using &lt;a id=&quot;menurrq4&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://github.com/microsoft/mssql-python&quot; href=&quot;https://pypi.org/project/mssql-python/&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;&lt;strong&gt;pip install mssql-python&lt;/strong&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Calling all Python + SQL developers! We invite the community to try out mssql-python and help us shape the future of high-performance &lt;a id=&quot;menurrq6&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://github.com/microsoft/mssql-python&quot; href=&quot;https://github.com/microsoft/mssql-python&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;SQL Server connectivity in Python&lt;/a&gt;.!&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;What Are Parameter Styles?&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The &lt;/span&gt;&lt;a href=&quot;https://peps.python.org/pep-0249/#paramstyle&quot;&gt;&lt;span&gt;DB-API 2.0 specification (PEP 249)&lt;/span&gt;&lt;/a&gt;&lt;span&gt; defines several ways to pass parameters to SQL queries. The two most popular are:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;qmark&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &amp;#8211; Positional &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; placeholders with a tuple/list of values.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;pyformat&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &amp;#8211; Named &lt;/span&gt;&lt;span&gt;%(name)s&lt;/span&gt;&lt;span&gt; placeholders with a dictionary of values.&lt;/span&gt;&lt;span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;# qmark style 
cursor.execute(&quot;SELECT * FROM users WHERE id = ? AND status = ?&quot;, (42, &quot;active&quot;)) 
 
# pyformat style 
cursor.execute(&quot;SELECT * FROM users WHERE id = %(id)s AND status = %(status)s&quot;, 
               {&quot;id&quot;: 42, &quot;status&quot;: &quot;active&quot;}) &lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;span&gt;&lt;b&gt;Business Requirement&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Previously, &lt;/span&gt;&lt;span&gt;mssql-python&lt;/span&gt;&lt;span&gt; only supported &lt;/span&gt;&lt;span&gt;qmark&lt;/span&gt;&lt;span&gt;. It works fine for simple queries, but as parameters multiply, tracking their order becomes error-prone:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;# Which ? corresponds to which value? 
cursor.execute( 
    &quot;UPDATE users SET name=?, email=?, age=? WHERE id=? AND status=?&quot;, 
    (name, email, age, user_id, status) 
) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;Mix up the order and it’s easy to introduce subtle, hard &lt;/span&gt;&lt;span&gt;to &lt;/span&gt;&lt;span&gt;spot bugs.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;Why Named Parameters?&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Self-documenting queries&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &amp;#8211; No more guessing which &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; maps to what:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;qmark — 6 parameters, which is which? 
cursor.execute( &quot;&quot;&quot;INSERT INTO employees (first_name, last_name, email, department, salary, hire_date) VALUES (?, ?, ?, ?, ?, ?)&quot;&quot;&quot;, (&quot;Jane&quot;, &quot;Doe&quot;, &quot;jane.doe@company.com&quot;, &quot;Engineering&quot;, 95000, &quot;2025-03-01&quot;) ) 
pyformat — every value is labeled 
cursor.execute( &quot;&quot;&quot;INSERT INTO employees (first_name, last_name, email, department, salary, hire_date) VALUES (%(first_name)s, %(last_name)s, %(email)s, %(dept)s, %(salary)s, %(hire_date)s)&quot;&quot;&quot;, {&quot;first_name&quot;: &quot;Jane&quot;, &quot;last_name&quot;: &quot;Doe&quot;, &quot;email&quot;: &quot;jane.doe@company.com&quot;, &quot;dept&quot;: &quot;Engineering&quot;, &quot;salary&quot;: 95000, &quot;hire_date&quot;: &quot;2025-03-01&quot;} ) &lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Parameter reuse&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &amp;#8211; Use the same value multiple times without repeating it:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;Audit log: record who made the change and when 
cursor.execute( &quot;&quot;&quot;UPDATE orders SET status = %(new_status)s, modified_by = %(user)s, approved_by = %(user)s, modified_at = %(now)s, approved_at = %(now)s WHERE order_id = %(order_id)s&quot;&quot;&quot;, {&quot;new_status&quot;: &quot;approved&quot;, &quot;user&quot;: &quot;admin@company.com&quot;, &quot;now&quot;: datetime.now(), &quot;order_id&quot;: 5042} ) 
3 unique values, used 5 times — no duplication needed &lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Dynamic query building&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &amp;#8211; Add filters without tracking parameter positions:&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;def search_orders(customer=None, status=None, min_total=None, date_from=None): 
    query_parts = [&quot;SELECT * FROM orders WHERE 1=1&quot;] 
    params = {} 
  
    if customer: 
        query_parts.append(&quot;AND customer_id = %(customer)s&quot;) 
        params[&quot;customer&quot;] = customer 
  
    if status: 
        query_parts.append(&quot;AND status = %(status)s&quot;) 
        params[&quot;status&quot;] = status 
  
    if min_total is not None: 
        query_parts.append(&quot;AND total &amp;gt;= %(min_total)s&quot;) 
        params[&quot;min_total&quot;] = min_total 
  
    if date_from: 
        query_parts.append(&quot;AND order_date &amp;gt;= %(date_from)s&quot;) 
        params[&quot;date_from&quot;] = date_from 
  
    query_parts.append(&quot;ORDER BY order_date DESC&quot;) 
    cursor.execute(&quot; &quot;.join(query_parts), params) 
    return cursor.fetchall() 
  
# Callers use only the filters they need 
recent_big_orders = search_orders(min_total=500, date_from=&quot;2025-01-01&quot;) 
pending_for_alice = search_orders(customer=42, status=&quot;pending&quot;) &lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Dictionary Reuse Across Queries&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;The same parameter dictionary can drive multiple queries:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;report_params = {&quot;region&quot;: &quot;West&quot;, &quot;year&quot;: 2025, &quot;status&quot;: &quot;active&quot;} 
  
# Summary count 
cursor.execute( 
    &quot;&quot;&quot;SELECT COUNT(*) FROM customers 
       WHERE region = %(region)s AND status = %(status)s&quot;&quot;&quot;, 
    report_params 
) 
total = cursor.fetchone()[0] 
  
# Revenue breakdown 
cursor.execute( 
    &quot;&quot;&quot;SELECT department, SUM(revenue) 
       FROM sales 
       WHERE region = %(region)s AND fiscal_year = %(year)s 
       GROUP BY department 
       ORDER BY SUM(revenue) DESC&quot;&quot;&quot;, 
    report_params 
) 
breakdown = cursor.fetchall() 
  
# Top performers 
cursor.execute( 
    &quot;&quot;&quot;SELECT name, revenue 
       FROM sales_reps 
       WHERE region = %(region)s AND fiscal_year = %(year)s AND status = %(status)s 
       ORDER BY revenue DESC&quot;&quot;&quot;, 
    report_params 
) 
top_reps = cursor.fetchall() 
# Same dict, three different queries — change the filters once, all queries update &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;The Solution: Automatic Detection&lt;/b&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;mssql-python&lt;/span&gt;&lt;span&gt; now detects which style you&amp;#8217;re using based on the parameter type:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;tuple/list&lt;/span&gt;&lt;/b&gt;&lt;span&gt; → &lt;/span&gt;&lt;span&gt;qmark&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;dict&lt;/span&gt;&lt;/b&gt;&lt;span&gt; → &lt;/span&gt;&lt;span&gt;pyformat&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;%(name)s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;No configuration needed. Existing &lt;/span&gt;&lt;span&gt;qmark&lt;/span&gt;&lt;span&gt; code requires &lt;/span&gt;&lt;b&gt;&lt;span&gt;zero changes&lt;/span&gt;&lt;/b&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;from mssql_python import connect 
 
# qmark - works exactly as before 
cursor.execute(&quot;SELECT * FROM users WHERE id = ?&quot;, (42,)) 
 
# pyformat - just pass a dict! 
cursor.execute(&quot;SELECT * FROM users WHERE id = %(id)s&quot;, {&quot;id&quot;: 42})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;How It Works&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;When you pass a dict to &lt;/span&gt;&lt;span&gt;execute()&lt;/span&gt;&lt;span&gt;, the driver:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Scans&lt;/span&gt;&lt;/b&gt;&lt;span&gt; the SQL for &lt;/span&gt;&lt;span&gt;%(name)s&lt;/span&gt;&lt;span&gt; placeholders (context-aware &amp;#8211; skips string literals, comments, and bracketed identifiers).&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Validates&lt;/span&gt;&lt;/b&gt;&lt;span&gt; that every placeholder has a matching key in the dict.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Builds&lt;/span&gt;&lt;/b&gt;&lt;span&gt; a positional tuple in placeholder order (duplicating values for reused parameters).&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Replaces&lt;/span&gt;&lt;/b&gt;&lt;span&gt; each &lt;/span&gt;&lt;span&gt;%(name)s&lt;/span&gt;&lt;span&gt; with &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; and sends the rewritten query to ODBC.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;User Code                                  ODBC Layer 
─────────                                  ────────── 
cursor.execute(                            SQLBindParameter(1, &quot;active&quot;) 
  &quot;WHERE status = %(status)s               SQLBindParameter(2, &quot;USA&quot;) 
   AND country = %(country)s&quot;,      →      SQLExecute( 
  {&quot;status&quot;: &quot;active&quot;,                       &quot;WHERE status = ? 
   &quot;country&quot;: &quot;USA&quot;}                          AND country = ?&quot; 
)                                          ) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;The ODBC layer always works with positional &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; placeholders. The pyformat conversion is purely a developer-facing convenience with zero overhead to database communication.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;Clear Error Messages&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Mismatched styles or missing parameters produce actionable errors &amp;#8211; not cryptic database exceptions:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;cursor.execute(&quot;WHERE id = %(id)s AND name = %(name)s&quot;, {&quot;id&quot;: 42}) 
# KeyError: Missing required parameter(s): 'name'. 
 
cursor.execute(&quot;WHERE id = ?&quot;, {&quot;id&quot;: 42}) 
# TypeError: query uses positional placeholders (?), but dict was provided. 
 
cursor.execute(&quot;WHERE id = %(id)s&quot;, (42,)) 
# TypeError: query uses named placeholders (%(name)s), but tuple was provided.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;Real-World Examples&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;Example 1: &lt;/strong&gt;&lt;/span&gt;Web Application&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;def add_user(name, email): 
    with connect(connection_string) as conn: 
        with conn.cursor() as cursor: 
            cursor.execute( 
                &quot;INSERT INTO users (name, email) VALUES (%(name)s, %(email)s)&quot;, 
                {&quot;name&quot;: name, &quot;email&quot;: email} 
            ) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;Example 2: &lt;/strong&gt;&lt;/span&gt;Batch Operations&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;cursor.executemany( 
    &quot;INSERT INTO users (name, age) VALUES (%(name)s, %(age)s)&quot;, 
    [{&quot;name&quot;: &quot;Alice&quot;, &quot;age&quot;: 30}, {&quot;name&quot;: &quot;Bob&quot;, &quot;age&quot;: 25}] 
) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;Example 3: &lt;/strong&gt;&lt;/span&gt;Financial Transactions&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;def transfer_funds(from_acct, to_acct, amount): 
    with connect(connection_string) as conn: 
        with conn.cursor() as cursor: 
            cursor.execute( 
                &quot;UPDATE accounts SET balance = balance - %(amount)s WHERE id = %(id)s&quot;, 
                {&quot;amount&quot;: amount, &quot;id&quot;: from_acct} 
            ) 
            cursor.execute( 
                &quot;UPDATE accounts SET balance = balance + %(amount)s WHERE id = %(id)s&quot;, 
                {&quot;amount&quot;: amount, &quot;id&quot;: to_acct} 
            ) 
    # Automatic commit on success, rollback on failure &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;Things to Keep in Mind&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Don&amp;#8217;t mix styles in one query&lt;/span&gt;&lt;/b&gt;&lt;span&gt;. Use either ? or %(name)s, not both. The driver determines which style you&amp;#8217;re using from the parameter type (tuple vs dict), not from the SQL text. If placeholders don&amp;#8217;t match the parameter type, you&amp;#8217;ll get a clear TypeError explaining the mismatch. If both placeholder types appear in the SQL, only one set gets substituted, leading to parameter count mismatches at execution time.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;# Mixing styles - raises TypeError 
cursor.execute( &quot;SELECT * FROM users WHERE id = ? AND name = %(name)s&quot;, {&quot;name&quot;: &quot;Alice&quot;} # Driver finds %(name)s but also sees unmatched ? ) 
# ODBC error: parameter count mismatch (2 placeholders, 1 value) 
# Pick one style and use it consistently 
cursor.execute( &quot;SELECT * FROM users WHERE id = %(id)s AND name = %(name)s&quot;, {&quot;id&quot;: 42, &quot;name&quot;: &quot;Alice&quot;} ) &lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Extra dict keys are OK.&lt;/span&gt;&lt;/b&gt;&lt;span&gt;  Unused parameters are silently ignored, this is by design to enable parameter dictionary reuse across different queries.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;SQL injection safe.&lt;/span&gt;&lt;/b&gt;&lt;span&gt; Both styles use ODBC parameter binding under the hood. Values are never interpolated into the SQL string, they are always safely bound by the driver.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;Literal &lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;%&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt; in SQL.&lt;/span&gt;&lt;/b&gt;&lt;span&gt; Use &lt;/span&gt;&lt;span&gt;%%&lt;/span&gt;&lt;span&gt; to escape if you need a literal &lt;/span&gt;&lt;span&gt;%(&amp;#8230;)s&lt;/span&gt;&lt;span&gt; pattern in your query text.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;cursor.execute( 
    &quot;SELECT * FROM users WHERE name LIKE %(pattern)s&quot;, 
    {&quot;pattern&quot;: &quot;%alice%&quot;}  # The % inside the VALUE is fine 
) 
 
# But if you need a literal %(...)s in SQL text itself, use %% 
cursor.execute( 
    &quot;SELECT '%%(example)s' AS literal WHERE id = %(id)s&quot;, 
    {&quot;id&quot;: 42} 
) &lt;/code&gt;&lt;span&gt; &lt;/span&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;mssql_python.paramstyle reports &amp;#8220;pyformat&amp;#8221;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;. The DB-API 2.0 spec only allows a single value for this module-level constant. We set it to pyformat because it&amp;#8217;s the more expressive style and the one we recommend for new code. But qmark is fully supported at runtime, the driver accepts both styles transparently based on whether you pass a tuple or a dict. Think of paramstyle = &amp;#8220;pyformat&amp;#8221; as the advertised default, not a limitation.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;Compatibility at a Glance&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;Feature&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;qmark (?)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;pyformat (%&lt;/span&gt;&lt;/b&gt;&lt;strong&gt;(name)s&lt;/strong&gt;&lt;b&gt;&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;cursor.execute()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;cursor.executemany()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;connection.execute()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Parameter reuse&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png&quot; alt=&quot;❌&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Stored procedures&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;All SQL data types&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;Backward compatible with qmark paramstyle&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;N/A (new)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span&gt;&lt;b&gt;Takeaway&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Use &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; for quick, simple queries. Use &lt;/span&gt;&lt;span&gt;%(name)s&lt;/span&gt;&lt;span&gt; for complex, multi-parameter queries where clarity and reuse matter. You don&amp;#8217;t have to pick a side &amp;#8211; use whichever fits the situation. The driver handles the rest.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Whether you&amp;#8217;re building dynamic queries, or simply want more readable SQL, dual paramstyle support makes &lt;/span&gt;&lt;span&gt;mssql-python&lt;/span&gt;&lt;span&gt; work the way you already think.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;Try It and Share Your Feedback! &lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We invite you to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check-out the &lt;a id=&quot;menurrmp&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://github.com/microsoft/mssql-python&quot; href=&quot;https://github.com/microsoft/mssql-python&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;mssql-python &lt;/a&gt;driver and integrate it into your projects.&lt;/li&gt;
&lt;li&gt;Share your thoughts: Open &lt;a id=&quot;menurrmr&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://github.com/microsoft/mssql-python/issues&quot; href=&quot;https://github.com/microsoft/mssql-python/issues&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;issues&lt;/a&gt;, suggest features, and contribute to the project.&lt;/li&gt;
&lt;li&gt;Join the conversation: &lt;a id=&quot;menurrmt&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://github.com/microsoft/mssql-python/discussions&quot; href=&quot;https://github.com/microsoft/mssql-python/discussions&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;GitHub Discussions&lt;/a&gt; | &lt;a id=&quot;menurrmv&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://techcommunity.microsoft.com/category/sql-server/blog/sqlserver&quot; href=&quot;https://techcommunity.microsoft.com/category/sql-server/blog/sqlserver&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;SQL Server Tech Community&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;div class=&quot;alert alert-success&quot;&gt;&lt;p class=&quot;alert-divider&quot;&gt;&lt;i class=&quot;fabric-icon fabric-icon--Lightbulb&quot;&gt;&lt;/i&gt;&lt;strong&gt;Use Python Driver with Free Azure SQL Database&lt;/strong&gt;&lt;/p&gt;You can use the Python Driver with the free version of Azure SQL Database!&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt; &lt;a id=&quot;menurrn1&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://learn.microsoft.com/en-us/azure/azure-sql/database/free-offer?view=azuresql&quot; href=&quot;https://learn.microsoft.com/en-us/azure/azure-sql/database/free-offer?view=azuresql&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Deploy Azure SQL Database for free&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png&quot; alt=&quot;✅&quot; class=&quot;wp-smiley&quot; /&gt; &lt;a id=&quot;menurrn3&quot; class=&quot;fui-Link ___1q1shib f2hkw1w f3rmtva f1ewtqcl fyind8e f1k6fduh f1w7gpdv fk6fouc fjoy568 figsok6 f1s184ao f1mk8lai fnbmjn9 f1o700av f13mvf36 f1cmlufx f9n3di6 f1ids18y f1tx3yz7 f1deo86v f1eh06m1 f1iescvh fhgqx19 f1olyrje f1p93eir f1nev41a f1h8hb77 f1lqvz6u f10aw75t fsle3fq f17ae5zn&quot; title=&quot;https://learn.microsoft.com/en-us/azure/azure-sql/managed-instance/free-offer?view=azuresql&quot; href=&quot;https://learn.microsoft.com/en-us/azure/azure-sql/managed-instance/free-offer?view=azuresql&quot; target=&quot;_blank&quot; rel=&quot;noreferrer noopener&quot;&gt;Deploy Azure SQL Managed Instance for free&lt;/a&gt; Perfect for testing, development, or learning scenarios without incurring costs.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The post &lt;a href=&quot;https://devblogs.microsoft.com/python/write-sql-your-way-dual-parameter-style-benefits-in-mssql-python/&quot;&gt;Write SQL Your Way: Dual Parameter Style Benefits in mssql-python&lt;/a&gt; appeared first on &lt;a href=&quot;https://devblogs.microsoft.com/python&quot;&gt;Microsoft for Python Developers Blog&lt;/a&gt;.&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 16:12:05 +0000</pubDate>
</item>
<item>
	<title>Django Weblog: Django security releases issued: 6.0.4, 5.2.13, and 4.2.30</title>
	<guid>https://www.djangoproject.com/weblog/2026/apr/07/security-releases/</guid>
	<link>https://www.djangoproject.com/weblog/2026/apr/07/security-releases/</link>
	<description>&lt;p&gt;In accordance with &lt;a class=&quot;reference external&quot; href=&quot;https://docs.djangoproject.com/en/dev/internals/security/&quot;&gt;our security release policy&lt;/a&gt;, the Django team
is issuing releases for
&lt;a class=&quot;reference external&quot; href=&quot;https://docs.djangoproject.com/en/dev/releases/6.0.4/&quot;&gt;Django 6.0.4&lt;/a&gt;,
&lt;a class=&quot;reference external&quot; href=&quot;https://docs.djangoproject.com/en/dev/releases/5.2.13/&quot;&gt;Django 5.2.13&lt;/a&gt;, and
&lt;a class=&quot;reference external&quot; href=&quot;https://docs.djangoproject.com/en/dev/releases/4.2.30/&quot;&gt;Django 4.2.30&lt;/a&gt;.
These releases address the security issues detailed below. We encourage all
users of Django to upgrade as soon as possible.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;s-django-4-2-has-reached-the-end-of-extended-support&quot;&gt;
&lt;h3&gt;Django 4.2 has reached the end of extended support&lt;/h3&gt;
&lt;p&gt;Note that with this release, Django 4.2 has reached the end of extended support. All Django 4.2 users are encouraged to &lt;a class=&quot;reference external&quot; href=&quot;https://docs.djangoproject.com/en/dev/howto/upgrade-version/&quot;&gt;upgrade&lt;/a&gt; to Django 5.2 or later to continue receiving fixes for security issues.&lt;/p&gt;
&lt;p&gt;See the &lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/#supported-versions&quot;&gt;downloads page&lt;/a&gt; for a table of supported versions and the future release schedule.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-3902-asgi-header-spoofing-via-underscore-hyphen-conflation&quot;&gt;
&lt;h3&gt;CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation&lt;/h3&gt;
&lt;p&gt;&lt;tt class=&quot;docutils literal&quot;&gt;ASGIRequest&lt;/tt&gt; normalizes header names following WSGI conventions, mapping
hyphens to underscores. As a result, even in configurations where reverse
proxies carefully strip security-sensitive headers named with hyphens, such a
header could be spoofed by supplying a header named with underscores.&lt;/p&gt;
&lt;p&gt;Under WSGI, it is the responsibility of the server or proxy to avoid ambiguous
mappings. (Django's &lt;tt class=&quot;docutils literal&quot;&gt;runserver&lt;/tt&gt; was patched in CVE-2015-0219.) But
under ASGI, there is not the same uniform expectation, even if many proxies
protect against this under default configuration (including &lt;tt class=&quot;docutils literal&quot;&gt;nginx&lt;/tt&gt; via
&lt;tt class=&quot;docutils literal&quot;&gt;underscores_in_headers off;&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;Headers containing underscores are now ignored by &lt;tt class=&quot;docutils literal&quot;&gt;ASGIRequest&lt;/tt&gt;, matching the
behavior of &lt;tt class=&quot;docutils literal&quot;&gt;Daphne&lt;/tt&gt;, the reference server for ASGI.&lt;/p&gt;
&lt;p&gt;This issue has severity &amp;quot;low&amp;quot; according to the Django Security Policy.&lt;/p&gt;
&lt;p&gt;Thanks to Tarek Nakkouch for the report.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-4277-privilege-abuse-in-genericinlinemodeladmin&quot;&gt;
&lt;h3&gt;CVE-2026-4277: Privilege abuse in &lt;tt class=&quot;docutils literal&quot;&gt;GenericInlineModelAdmin&lt;/tt&gt;&lt;/h3&gt;
&lt;p&gt;Add permissions on inline model instances were not validated on submission of
forged &lt;tt class=&quot;docutils literal&quot;&gt;POST&lt;/tt&gt; data in &lt;tt class=&quot;docutils literal&quot;&gt;GenericInlineModelAdmin&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This issue has severity &amp;quot;low&amp;quot; according to the Django Security Policy.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a class=&quot;reference external&quot; href=&quot;mailto:N05ec@LZU-DSLab&quot;&gt;N05ec&amp;#64;LZU-DSLab&lt;/a&gt; for the report.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-4292-privilege-abuse-in-modeladmin-list-editable&quot;&gt;
&lt;h3&gt;CVE-2026-4292: Privilege abuse in &lt;tt class=&quot;docutils literal&quot;&gt;ModelAdmin.list_editable&lt;/tt&gt;&lt;/h3&gt;
&lt;p&gt;Admin changelist forms using &lt;tt class=&quot;docutils literal&quot;&gt;ModelAdmin.list_editable&lt;/tt&gt; incorrectly allowed new
instances to be created via forged &lt;tt class=&quot;docutils literal&quot;&gt;POST&lt;/tt&gt; data.&lt;/p&gt;
&lt;p&gt;This issue has severity &amp;quot;low&amp;quot; according to the Django Security Policy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-33033-potential-denial-of-service-vulnerability-in-multipartparser-via-base64-encoded-file-upload&quot;&gt;
&lt;h3&gt;CVE-2026-33033: Potential denial-of-service vulnerability in &lt;tt class=&quot;docutils literal&quot;&gt;MultiPartParser&lt;/tt&gt; via base64-encoded file upload&lt;/h3&gt;
&lt;p&gt;When using &lt;tt class=&quot;docutils literal&quot;&gt;django.http.multipartparser.MultiPartParser&lt;/tt&gt;, multipart uploads
with &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;Content-Transfer-Encoding:&lt;/span&gt; base64&lt;/tt&gt; that include excessive whitespace
may trigger repeated memory copying, potentially degrading performance.&lt;/p&gt;
&lt;p&gt;This issue has severity &amp;quot;moderate&amp;quot; according to the Django Security Policy.&lt;/p&gt;
&lt;p&gt;Thanks to Seokchan Yoon for the report.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-33034-potential-denial-of-service-vulnerability-in-asgi-requests-via-memory-upload-limit-bypass&quot;&gt;
&lt;h3&gt;CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass&lt;/h3&gt;
&lt;p&gt;ASGI requests with a missing or understated &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;Content-Length&lt;/span&gt;&lt;/tt&gt; header could
bypass the &lt;tt class=&quot;docutils literal&quot;&gt;DATA_UPLOAD_MAX_MEMORY_SIZE&lt;/tt&gt; limit when reading
&lt;tt class=&quot;docutils literal&quot;&gt;HttpRequest.body&lt;/tt&gt;, potentially loading an unbounded request body into
memory and causing service degradation.&lt;/p&gt;
&lt;p&gt;This issue has severity &amp;quot;low&amp;quot; according to the Django Security Policy.&lt;/p&gt;
&lt;p&gt;Thanks to Superior for the report.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-affected-supported-versions&quot;&gt;
&lt;h3&gt;Affected supported versions&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Django main&lt;/li&gt;
&lt;li&gt;Django 6.0&lt;/li&gt;
&lt;li&gt;Django 5.2&lt;/li&gt;
&lt;li&gt;Django 4.2&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-resolution&quot;&gt;
&lt;h3&gt;Resolution&lt;/h3&gt;
&lt;p&gt;Patches to resolve the issue have been applied to Django's
main, 6.0, 5.2, and 4.2 branches.
The patches may be obtained from the following changesets.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-3902-asgi-header-spoofing-via-underscore-hyphen-conflation-1&quot;&gt;
&lt;h4&gt;CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation&lt;/h4&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/caf90a971f09323775ed0cacf94eadaf39d040e0&quot;&gt;main branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/a623c3982857e80324448f85c7faf9a6710330ef&quot;&gt;6.0 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/1cc2a7612f97c109b92415fc11ba9bd0501852e0&quot;&gt;5.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/4412731aa64d62a6dd7edae79e0c15b72666d7ca&quot;&gt;4.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-4277-privilege-abuse-in-genericinlinemodeladmin-1&quot;&gt;
&lt;h4&gt;CVE-2026-4277: Privilege abuse in &lt;tt class=&quot;docutils literal&quot;&gt;GenericInlineModelAdmin&lt;/tt&gt;&lt;/h4&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/ef8b25dcc06d158683a5623ce406d561638f4073&quot;&gt;main branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/08a752c1cd8f378b4c64d96c319da23726df6ed3&quot;&gt;6.0 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/60ffa957c427e10a2eb0fc80d1674a8a8ccc30b0&quot;&gt;5.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/051f3909e820360bbe84a21350e82f4961e3d917&quot;&gt;4.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-4292-privilege-abuse-in-modeladmin-list-editable-1&quot;&gt;
&lt;h4&gt;CVE-2026-4292: Privilege abuse in &lt;tt class=&quot;docutils literal&quot;&gt;ModelAdmin.list_editable&lt;/tt&gt;&lt;/h4&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/6afe7ce93964f56e33a29d477c269436f9b60cbf&quot;&gt;main branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/428c48f358c5a0ed5ca2834fb721d615eb2b0e11&quot;&gt;6.0 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/397c22048244db2cd4bb78f570e6c72a3967bf36&quot;&gt;5.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/abfe1a1c57a57cfaf6dd4a0571c029401a0fe743&quot;&gt;4.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-33033-potential-denial-of-service-vulnerability-in-multipartparser-via-base64-encoded-file-upload-1&quot;&gt;
&lt;h4&gt;CVE-2026-33033: Potential denial-of-service vulnerability in &lt;tt class=&quot;docutils literal&quot;&gt;MultiPartParser&lt;/tt&gt; via base64-encoded file upload&lt;/h4&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/7e9885f99cee771b51692fadc5592bdbf19641aa&quot;&gt;main branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/0910af60468216c856dfbcac1177372c225deb76&quot;&gt;6.0 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/0b467893bdde69a2d23034338e76021a1e4f4322&quot;&gt;5.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/f13c20f81b56108ac477213fa5ada2524b5e5c98&quot;&gt;4.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-cve-2026-33034-potential-denial-of-service-vulnerability-in-asgi-requests-via-memory-upload-limit-bypass-1&quot;&gt;
&lt;h4&gt;CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass&lt;/h4&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/953c238058c0ce387a1a41cb491bfc1875d73ad0&quot;&gt;main branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/393dbc53e848876fdba92fbf02e10ee6a6eace6b&quot;&gt;6.0 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/49e1e2b548999a35a025f9682598946bda9e9921&quot;&gt;5.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/django/django/commit/ed4dfda62718a0bb644b80ac8b1d3099861f2295&quot;&gt;4.2 branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-the-following-releases-have-been-issued&quot;&gt;
&lt;h3&gt;The following releases have been issued&lt;/h3&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;Django 6.0.4 (&lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/6.0.4/tarball/&quot;&gt;download Django 6.0.4&lt;/a&gt; |
&lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/6.0.4/checksum/&quot;&gt;6.0.4 checksums&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Django 5.2.13 (&lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/5.2.13/tarball/&quot;&gt;download Django 5.2.13&lt;/a&gt; |
&lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/5.2.13/checksum/&quot;&gt;5.2.13 checksums&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Django 4.2.30 (&lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/4.2.30/tarball/&quot;&gt;download Django 4.2.30&lt;/a&gt; |
&lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/download/4.2.30/checksum/&quot;&gt;4.2.30 checksums&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The PGP key ID used for this release is Jacob Walls: &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/jacobtylerwalls.gpg&quot;&gt;131403F4D16D8DC7&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;s-general-notes-regarding-security-reporting&quot;&gt;
&lt;h3&gt;General notes regarding security reporting&lt;/h3&gt;
&lt;p&gt;As always, we ask that potential security issues be reported via private email
to &lt;tt class=&quot;docutils literal&quot;&gt;security&amp;#64;djangoproject.com&lt;/tt&gt;, and not via Django's Trac instance, nor via
the Django Forum. Please see &lt;a class=&quot;reference external&quot; href=&quot;https://www.djangoproject.com/security/&quot;&gt;our security policies&lt;/a&gt; for further information.&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Tue, 07 Apr 2026 14:00:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: Using Loguru to Simplify Python Logging</title>
	<guid>https://realpython.com/courses/using-loguru-to-simplify-python-logging/</guid>
	<link>https://realpython.com/courses/using-loguru-to-simplify-python-logging/</link>
	<description>&lt;p&gt;Logging is a vital programming practice that helps you track, understand, and debug your application&amp;rsquo;s behavior. Loguru is a Python library that provides simpler, more intuitive logging compared to Python&amp;rsquo;s built-in &lt;code&gt;logging&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;Good logging gives you insights into your program&amp;rsquo;s execution, helps you diagnose issues, and provides valuable information about your application&amp;rsquo;s health in production. Without proper logging, you risk missing critical errors, spending countless hours &lt;a href=&quot;https://realpython.com/python-debugging-pdb/&quot;&gt;debugging&lt;/a&gt; blind spots, and potentially undermining your project&amp;rsquo;s overall stability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this video course, you&amp;rsquo;ll understand that:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Logging&lt;/strong&gt; in Python can be &lt;strong&gt;simple and intuitive&lt;/strong&gt; with the right tools.&lt;/li&gt;
&lt;li&gt;Using Loguru lets you &lt;strong&gt;start logging immediately&lt;/strong&gt; without complex configuration.&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;customize log formats&lt;/strong&gt; and send logs to multiple destinations like files, the standard error stream, or external services.&lt;/li&gt;
&lt;li&gt;Loguru provides &lt;strong&gt;powerful debugging capabilities&lt;/strong&gt; that make troubleshooting easier.&lt;/li&gt;
&lt;li&gt;Loguru supports &lt;strong&gt;structured logging&lt;/strong&gt; with JSON formatting for modern applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After watching this course, you&amp;rsquo;ll be able to quickly implement better logging in your Python applications. You&amp;rsquo;ll spend less time wrestling with logging configuration and more time using logs effectively to debug issues. This will help you build production-ready applications that are easier to troubleshoot when problems occur.&lt;/p&gt;
&lt;p&gt;To get the most from this course, you should be familiar with Python concepts like &lt;a href=&quot;https://realpython.com/defining-your-own-python-function/&quot;&gt;functions&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/primer-on-python-decorators/&quot;&gt;decorators&lt;/a&gt;, and &lt;a href=&quot;https://realpython.com/python-with-statement/&quot;&gt;context managers&lt;/a&gt;. You might also find it helpful to have some experience with Python&amp;rsquo;s built-in &lt;a href=&quot;https://realpython.com/python-logging/&quot;&gt;&lt;code&gt;logging&lt;/code&gt;&lt;/a&gt; module, though this isn&amp;rsquo;t required.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t worry if you&amp;rsquo;re new to logging in Python. This course will guide you through everything you need to know to get started with Loguru and implement effective logging in your applications.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 14:00:00 +0000</pubDate>
</item>
<item>
	<title>Django Weblog: Could you host DjangoCon Europe 2027? Call for organizers</title>
	<guid>https://www.djangoproject.com/weblog/2026/apr/07/could-you-host-djangocon-europe-2027-call-for-orga/</guid>
	<link>https://www.djangoproject.com/weblog/2026/apr/07/could-you-host-djangocon-europe-2027-call-for-orga/</link>
	<description>&lt;p&gt;We are looking for the next group of organizers to own and lead the 2027 DjangoCon Europe conference. Could your town's football stadium, theatre, cinema, city hall, circus tent or a private island host this wonderful community event?&lt;/p&gt;
&lt;p&gt;DjangoCon Europe is a major pillar of the Django community, as people from across the world meet and share. Many qualities make it a unique event: Unconventional and conventional venues, creative happenings, a feast of talks and a dedication to inclusion and diversity.&lt;/p&gt;
&lt;p&gt;Hosting a DjangoCon is an ambitious undertaking. It's hard work, but each year it has been successfully run by a team of community volunteers, not all of whom have had previous experience - more important is enthusiasm, organizational skills, the ability to plan and manage budgets, time and people - and plenty of time to invest in the project.&lt;/p&gt;
&lt;p&gt;For 2027, rest assured that we will be there to answer questions and put you in touch with previous organizers through the brand new &lt;a href=&quot;https://github.com/django/dsf-working-groups/blob/main/active/events-support.md&quot;&gt;DSF Events Support Working Group&lt;/a&gt; (a reboot of the previous DjangoCon Europe Support Working Group).&lt;/p&gt;
&lt;h4 id=&quot;s-step-1-submit-your-expression-of-interest&quot;&gt;Step 1: Submit your expression of interest&lt;/h4&gt;
&lt;p&gt;If you're considering organizing DjangoCon Europe (🙌 great!), fill in our &lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSc4OuhWG2DRsWSH_S1M313_RrdHdi9ozBWl0rtDAsvlRospCw/viewform&quot;&gt;DjangoCon Europe 2027 expression of interest form&lt;/a&gt; with your contact details. No need to fill in all the information at this stage if you don't have it all already, we'll reach out and help you figure it out.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSc4OuhWG2DRsWSH_S1M313_RrdHdi9ozBWl0rtDAsvlRospCw/viewform&quot;&gt;Express your interest in organizing&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;s-step-2-were-here-to-help&quot;&gt;Step 2: We're here to help!&lt;/h4&gt;
&lt;p&gt;We've set up a &lt;a href=&quot;https://github.com/django/dsf-working-groups/blob/main/active/events-support.md&quot;&gt;DjangoCon Europe support working group&lt;/a&gt; of previous organizers that you can reach out to with questions about organizing and running a DjangoCon Europe.&lt;/p&gt;
&lt;p&gt;The group will be in touch with everyone submitting the expression of interest form, or you can reach out to them directly: events-support@djangoproject.com&lt;/p&gt;
&lt;p&gt;We'd love to hear from you as soon as possible, so your proposal can be finalized and sent to the DSF board by June 1st 2026.&lt;/p&gt;
&lt;h4 id=&quot;s-step-3-submitting-the-proposal&quot;&gt;Step 3: Submitting the proposal&lt;/h4&gt;
&lt;p&gt;The more detailed and complete your final proposal is, the better. Basic details include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Organizing committee members: You won't have a full team yet, probably, naming just some core team members is enough.&lt;/li&gt;
&lt;li&gt;The legal entity that is intended to run the conference: Even if the entity does not exist yet, please share how you are planning to set it up.&lt;/li&gt;
&lt;li&gt;Dates: See &quot;What dates are possible in 2027?&quot; below. We must avoid conflicts with major holidays, EuroPython, DjangoCon US, and PyCon US.&lt;/li&gt;
&lt;li&gt;Venue(s), including size, number of possible attendees, pictures, accessibility concerns, catering, etc.&lt;/li&gt;
&lt;li&gt;Transport links and accommodation: Can your venue be reached by international travelers?&lt;/li&gt;
&lt;li&gt;Budgets and ticket prices: Talk to the DjangoCon Europe Support group to get help with this, including information on past event budgets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also like to see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Timelines&lt;/li&gt;
&lt;li&gt;Pictures&lt;/li&gt;
&lt;li&gt;Plans for online participation, and other ways to make the event more inclusive and reduce its environmental footprint&lt;/li&gt;
&lt;li&gt;Draft agreements with providers&lt;/li&gt;
&lt;li&gt;Alternatives you have considered&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Have a look at our proposed (draft, feedback welcome) &lt;a href=&quot;https://docs.google.com/document/d/1pxx8Zzu9CJz-rCtZyLPVe6FtdOKrzwH_tDyw2wpVOCA/edit?usp=sharing&quot;&gt;DjangoCon Europe 2027 Licensing Agreement&lt;/a&gt; for the fine print on contractual requirements and involvement of the Django Software Foundation.&lt;/p&gt;
&lt;p&gt;Submit your completed proposal by June 1st 2026 via our &lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSc4OuhWG2DRsWSH_S1M313_RrdHdi9ozBWl0rtDAsvlRospCw/viewform&quot;&gt;DjangoCon Europe 2027 expression of interest form&lt;/a&gt;, this time filling in as many fields as possible. We look forward to reviewing great proposals that continue the excellence the whole community associates with DjangoCon Europe.&lt;/p&gt;
&lt;h4 id=&quot;s-qa&quot;&gt;Q&amp;amp;A&lt;/h4&gt;
&lt;h5 id=&quot;s-can-i-organize-a-conference-alone&quot;&gt;Can I organize a conference alone?&lt;/h5&gt;
&lt;p&gt;We strongly recommend that a team of people submit an application.&lt;/p&gt;
&lt;h5 id=&quot;s-iwe-dont-have-a-legal-entity-yet-is-that-a-problem&quot;&gt;I/we don't have a legal entity yet, is that a problem?&lt;/h5&gt;
&lt;p&gt;Depending on your jurisdiction, this is usually not a problem. But please share your plans about the entity you will use or form in your application.&lt;/p&gt;
&lt;h5 id=&quot;s-do-iwe-need-experience-with-organizing-conferences&quot;&gt;Do I/we need experience with organizing conferences?&lt;/h5&gt;
&lt;p&gt;The support group is here to help you succeed. From experience, we know that many core groups of 2-3 people have been able to run a DjangoCon with guidance from previous organizers and help from volunteers.&lt;/p&gt;
&lt;h5 id=&quot;s-what-is-required-in-order-to-announce-an-event&quot;&gt;What is required in order to announce an event?&lt;/h5&gt;
&lt;p&gt;Ultimately, a contract with the venue confirming the dates is crucial, since announcing a conference makes people book calendars, holidays, buy transportation and accommodation etc. This, however, would only be relevant after the DSF board has concluded the application process. Naturally, the application itself cannot contain any guarantees, but it's good to check concrete dates with your venues to ensure they are actually open and currently available, before suggesting these dates in the application.&lt;/p&gt;
&lt;h5 id=&quot;s-do-we-have-to-do-everything-ourselves&quot;&gt;Do we have to do everything ourselves?&lt;/h5&gt;
&lt;p&gt;No. You will definitely be offered lots of help by the community. Typically, conference organizers will divide responsibilities into different teams, making it possible for more volunteers to join. Local organizers are free to choose which areas they want to invite the community to help out with, and a call will go out through a blog post announcement on djangoproject.com and social media.&lt;/p&gt;
&lt;h5 id=&quot;s-what-kind-of-support-can-we-expect-from-the-django-software-foundation&quot;&gt;What kind of support can we expect from the Django Software Foundation?&lt;/h5&gt;
&lt;p&gt;The DSF regularly provides grant funding to DjangoCon organizers, to the extent of $6,000 in recent editions. We also offer support via specific working groups:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The dedicated &lt;a href=&quot;https://github.com/django/dsf-working-groups/blob/main/active/dceu.md&quot;&gt;DjangoCon Europe support working group&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/django/dsf-working-groups/blob/main/active/social-media.md&quot;&gt;social media working group&lt;/a&gt; can help you promote the event.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://github.com/django/dsf-working-groups/blob/main/active/code-of-conduct.md&quot;&gt;Code of Conduct working group&lt;/a&gt; works with all event organizers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, a lot of &lt;a href=&quot;https://www.djangoproject.com/foundation/individual-members/&quot;&gt;Individual Members&lt;/a&gt; of the DSF regularly volunteer at community events. If your team aren't Individual Members, we can reach out to them on your behalf to find volunteers.&lt;/p&gt;
&lt;h5 id=&quot;s-what-dates-are-possible-in-2027&quot;&gt;What dates are possible in 2027?&lt;/h5&gt;
&lt;p&gt;For 2027, DjangoCon Europe should happen between January 4th and April 26th, or June 3rd and June 27th. This is to avoid the following community events' provisional dates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PyCon US 2027: May 2027&lt;/li&gt;
&lt;li&gt;EuroPython 2027: July 2027&lt;/li&gt;
&lt;li&gt;DjangoCon US 2027: September - October 2027&lt;/li&gt;
&lt;li&gt;DjangoCon Africa 2027: August - September 2027&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also want to avoid the following holidays:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New Year's Day: Friday 1st January 2027&lt;/li&gt;
&lt;li&gt;Chinese New Year: Saturday 6th February 2027&lt;/li&gt;
&lt;li&gt;Eid Al-Fitr: Tuesday 9th March 2027&lt;/li&gt;
&lt;li&gt;Easter: Sunday 28th March 2027&lt;/li&gt;
&lt;li&gt;Passover: Wednesday 21st - Thursday 29th April 2027&lt;/li&gt;
&lt;li&gt;Eid Al-Adha: Monday 17th - Thursday 20th May 2027&lt;/li&gt;
&lt;li&gt;Rosh Hashanah: Saturday 2nd - Monday 4th October 2027&lt;/li&gt;
&lt;li&gt;Yom Kippur: Monday 11th - Tuesday 12th October 2027&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;s-what-cities-or-countries-are-possible&quot;&gt;What cities or countries are possible?&lt;/h5&gt;
&lt;p&gt;Any city in Europe. This can be a city or country where DjangoCon Europe has happened in the past (Athens, Vigo, Edinburgh, Porto, Copenhagen, Heidelberg, Florence, Budapest, Cardiff, Toulon, Warsaw, Zurich, Amsterdam, Berlin), or a new locale.&lt;/p&gt;
&lt;h4 id=&quot;s-references&quot;&gt;References&lt;/h4&gt;
&lt;h5 id=&quot;s-past-calls&quot;&gt;Past calls&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2015/may/18/interested-organizing-djangocon-europe-2016/&quot;&gt;Interested in organizing DjangoCon Europe 2016? | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2016/mar/04/host-djangocon-europe-2017/&quot;&gt;Could you host DjangoCon Europe 2017? | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2018/may/10/djangocon-europe-2019-where-will-it-be/&quot;&gt;DjangoCon Europe 2019 - where will it be? | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2022/feb/03/could-you-host-djangocon-europe-2023/&quot;&gt;Could you host DjangoCon Europe 2023? | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2022/jun/12/last-chance-for-a-djangocon-europe-2023/&quot;&gt;Last Chance for a DjangoCon Europe 2023 | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2023/mar/20/want-to-host-djangocon-europe-2024/&quot;&gt;Want to host DjangoCon Europe 2024? | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2024/jan/15/djangocon-europe-2025-call-for-proposals/&quot;&gt;DjangoCon Europe 2025 Call for Proposals | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2024/may/05/last-call-djangocon-europe-2025-organizers/&quot;&gt;Last call for DjangoCon Europe 2025 organizers | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.djangoproject.com/weblog/2024/aug/28/could-you-host-djangocon-europe-2026-cfp/&quot;&gt;Could you host DjangoCon Europe 2026? Call for organizers | Weblog | Django&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Tue, 07 Apr 2026 13:06:33 +0000</pubDate>
</item>
<item>
	<title>Real Python: Quiz: Building a Python GUI Application With Tkinter</title>
	<guid>https://realpython.com/quizzes/building-gui-application-tkinter/</guid>
	<link>https://realpython.com/quizzes/building-gui-application-tkinter/</link>
	<description>&lt;p&gt;In this quiz, you&amp;rsquo;ll test your understanding of
&lt;a href=&quot;https://realpython.com/courses/building-gui-application-tkinter/&quot;&gt;Building a Python GUI Application With Tkinter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Test your Tkinter knowledge by identifying core widgets, managing layouts, handling text with &lt;code&gt;Entry&lt;/code&gt; and &lt;code&gt;Text&lt;/code&gt; widgets, and connecting buttons to Python functions.&lt;/p&gt;
&lt;p&gt;This quiz also covers event loops, widget sizing, and file dialogs, helping you solidify the essentials for building interactive, cross-platform Python GUI apps.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>Real Python: Quiz: Using Loguru to Simplify Python Logging</title>
	<guid>https://realpython.com/quizzes/using-loguru-to-simplify-python-logging/</guid>
	<link>https://realpython.com/quizzes/using-loguru-to-simplify-python-logging/</link>
	<description>&lt;p&gt;In this quiz, you&amp;rsquo;ll test your understanding of &lt;a href=&quot;https://realpython.com/courses/using-loguru-to-simplify-python-logging/&quot;&gt;Using Loguru to Simplify Python Logging&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By working through this quiz, you&amp;rsquo;ll revisit key concepts like the pre-configured logger, log levels, format placeholders, adding context with &lt;code&gt;.bind()&lt;/code&gt; and &lt;code&gt;.contextualize()&lt;/code&gt;, and saving logs to files.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;utm_medium=rss&amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 12:00:00 +0000</pubDate>
</item>
<item>
	<title>PyCharm: How to Train Your First TensorFlow Model in PyCharm</title>
	<guid>https://blog.jetbrains.com/pycharm/2026/04/how-to-train-your-first-tensorflow-model/</guid>
	<link>https://blog.jetbrains.com/pycharm/2026/04/how-to-train-your-first-tensorflow-model/</link>
	<description>&lt;p&gt;&lt;em&gt;This is a guest post from &lt;/em&gt;&lt;strong&gt;&lt;em&gt;&lt;a href=&quot;https://blog.jetbrains.com/pycharm/2026/04/how-to-train-your-first-tensorflow-model/#author&quot;&gt;Iulia Feroli&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, founder of the Back To Engineering community on YouTube.&lt;/em&gt;&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/PC-social-BlogFeatured-1280x720-1-1.png&quot; alt=&quot;How to Train Your First TensorFlow Model in PyCharm&quot; class=&quot;wp-image-697465&quot; /&gt;



&lt;p&gt;&lt;a href=&quot;https://www.tensorflow.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TensorFlow&lt;/a&gt; is a powerful open-source framework for building machine learning and deep learning systems. At its core, it works with tensors (a.k.a multi‑dimensional arrays) and provides high‑level libraries (like Keras) that make it easy to transform raw data into models you can train, evaluate, and deploy.&lt;/p&gt;



&lt;p&gt;TensorFlow helps you handle the full pipeline: loading and preprocessing data, assembling models from layers and activations, training with optimizers and loss functions, and exporting for serving or even running on edge devices (including lightweight TensorFlow Lite models on Raspberry Pi and other microcontrollers).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you want to make data-driven applications, prototyping neural networks, or ship models to production or devices, learning TensorFlow gives you a consistent, well-supported toolkit to go from idea to deployment.&lt;/p&gt;



&lt;p&gt;If you’re brand new to TensorFlow, start by watching the &lt;strong&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hm07b8ETaso&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;short overview video&lt;/a&gt;&lt;/strong&gt; where I explain tensors, neural networks, layers, and why TensorFlow is great for taking data → model → deployment, and how all of this can be explained with a LEGO-style pieces sorting example.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;In this blog post, I’ll walk you through a first, stripped-down TensorFlow implementation notebook so we can get started with some practical experience. You can also watch the walkthrough video to follow along.&lt;/p&gt;



&lt;div class=&quot;wp-block-embed__wrapper&quot;&gt;

&lt;/div&gt;



&lt;p&gt;We&amp;#8217;ll be exploring a very simple use case today: load the Fashion MNIST dataset, build two very simple Keras models, train and compare them, then dig into visualizations (predictions, confidence bars, confusion matrix). I kept the code minimal and readable so you can focus on the ideas – and you’ll see how &lt;a href=&quot;https://www.jetbrains.com/pycharm/data-science/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PyCharm&lt;/a&gt; helps along the way.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Training TensorFlow models step by step&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Getting started in PyCharm&lt;/h3&gt;



&lt;p&gt;We&amp;#8217;ll be leveraging PyCharm&amp;#8217;s native Notebook integration to build out &lt;a href=&quot;https://github.com/iuliaferoli/TensorFlow_with_pycharm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;our project&lt;/a&gt;. This way, we can inspect each step of the pipeline and use some supporting visualization along the way. We&amp;#8217;ll &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/creating-empty-project.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;create a new project&lt;/a&gt; and &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;generate a virtual environment&lt;/a&gt; to manage our dependencies.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;If you&amp;#8217;re running the code from the attached repo, you can install directly from the requirements file. If you wish to expand this example with additional visualizations for further models, you can easily add more packages to your requirements as you go by using the PyCharm package manager helpers for &lt;a href=&quot;https://www.jetbrains.com/guide/python/tips/install-and-import/)%20and&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;installing&lt;/a&gt; and &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/installing-uninstalling-and-upgrading-packages.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;upgrading&lt;/a&gt;.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Load &lt;code&gt;Fashion MNIST&lt;/code&gt; and inspect the data&lt;/h3&gt;



&lt;p&gt;&lt;code&gt;Fashion MNIST&lt;/code&gt; is a great starter because the images are small (28×28 pixels), visually meaningful, and easy to interpret. They represent various garment types as pixelated black-and-white images, and provide the relevant labels for a well-contained classification task. We can first take a look at our data sample by printing some of these images with various matplotlib functions:&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image1.png&quot; alt=&quot;&quot; class=&quot;wp-image-699830&quot; /&gt;



&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;```
fig, axes = plt.subplots(2, 5, figsize=(10, 4))
for i, ax in enumerate(axes.flat):
    ax.imshow(x_train[i], cmap='gray')
    ax.set_title(class_names[y_train[i]])
    ax.axis('off')
plt.show()
```
# Two simple models (a quick experiment)
```
model1 = models.Sequential([
    layers.Flatten(input_shape=(28, 28)),
    layers.Dense(128, activation='relu'),
    layers.Dense(10, activation='softmax')
])
model2 = models.Sequential([
    layers.Flatten(input_shape=(28, 28)),
    layers.Dense(128, activation='relu'),
    layers.Dense(128, activation='relu'),
    layers.Dense(10, activation='softmax')
])
```&lt;/pre&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Compile and train your first model&lt;/h3&gt;



&lt;p&gt;From here, we can compile and train our first TensorFlow model(s). With PyCharm’s code completion features and documentation access, you can get instant suggestions for building out these simple code blocks.&lt;/p&gt;



&lt;p&gt;For a first try at TensorFlow, this allows us to spin up a working model with just a few presses of &lt;em&gt;Tab&lt;/em&gt; in our IDE. We&amp;#8217;re using the recommended standard optimizer and loss function, and we&amp;#8217;re tracking for accuracy. We can choose to build multiple models by playing around with the number or type of layers, along with the other parameters.&amp;nbsp;&lt;/p&gt;



&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;```
model1.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)
model1.fit(x_train, y_train, epochs=10)
model2.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)
model2.fit(x_train, y_train, epochs=15)
```&lt;/pre&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Evaluate and compare your TensorFlow model performance&lt;/h3&gt;



&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;```
loss1, accuracy1 = model1.evaluate(x_test, y_test)
print(f'Accuracy of model1: {accuracy1:.2f}')
loss2, accuracy2 = model2.evaluate(x_test, y_test)
print(f'Accuracy of model2: {accuracy2:.2f}')
```&lt;/pre&gt;



&lt;p&gt;Once the models are trained (and you can see the epochs progressing visually as each cell is run), we can immediately evaluate the performance of the models.&lt;/p&gt;



&lt;p&gt;In my experiment, &lt;code&gt;model1&lt;/code&gt; sits around ~0.88 accuracy, and while &lt;code&gt;model2&lt;/code&gt; is a little higher than that, it took 50% longer to train. That’s the kind of trade‑off you should be thinking about: Is a tiny accuracy gain worth the additional compute and complexity?&amp;nbsp;&lt;/p&gt;



&lt;p&gt;We can dive further into the results of the model run by generating a DataFrame instance of our new prediction dataset. Here we can also leverage built-in functions like `describe` to quickly get some initial statistical impressions:&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image2.png&quot; alt=&quot;&quot; class=&quot;wp-image-699841&quot; /&gt;



&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;```
predictions = model1.predict(x_test)
import pandas as pd
df_pred = pd.DataFrame(predictions, columns=class_names)
df_pred.describe()
```&lt;/pre&gt;



&lt;p&gt;However, the most useful statistics will compare our model&amp;#8217;s prediction with the ground truth &amp;#8220;real&amp;#8221; labels of our dataset. We can also break this down by item category:&lt;/p&gt;



&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;```
y_pred = model1.predict(x_test).argmax(axis=1)
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8,6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Confusion Matrix')
plt.show()
print('Classification report:')
print(classification_report(y_test, y_pred, target_names=class_names))
```&lt;/pre&gt;



&lt;p&gt;From here, we can notice that the accuracy differs quite a bit by type of garment. A possible interpretation of this is that trousers are quite a distinct type of clothing from, say, t-shirts and shirts, which can be more commonly confused.&amp;nbsp;&lt;/p&gt;



&lt;p&gt;This is, of course, the type of nuance that, as humans, we can pick up by looking at the images, but the model only has access to a matrix of pixel values. The data does seem, however, to confirm our intuition. We can further build a more comprehensive visualization to test this hypothesis.&amp;nbsp;&lt;/p&gt;



&lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/image-4.png&quot; alt=&quot;&quot; class=&quot;wp-image-697493&quot; /&gt;



&lt;pre class=&quot;EnlighterJSRAW&quot;&gt;```
import numpy as np
import matplotlib.pyplot as plt
# pick 8 wrong examples
y_pred = predictions.argmax(axis=1)
wrong_idx = np.where(y_pred != y_test)[0][:8]  # first 8 mistakes
n = len(wrong_idx)
fig, axes = plt.subplots(n, 2, figsize=(10, 2.2 * n), constrained_layout=True)
for row, idx in enumerate(wrong_idx):
    p = predictions[idx]
    pred = int(np.argmax(p))
    true = int(y_test[idx])
    axes[row, 0].imshow(x_test[idx], cmap=&quot;gray&quot;)
    axes[row, 0].axis(&quot;off&quot;)
    axes[row, 0].set_title(
        f&quot;WRONG  P:{class_names[pred]} ({p[pred]:.2f})  T:{class_names[true]}&quot;,
        color=&quot;red&quot;,
        fontsize=10
    )
    bars = axes[row, 1].bar(range(len(class_names)), p, color=&quot;lightgray&quot;)
    bars[pred].set_color(&quot;red&quot;)
    axes[row, 1].set_ylim(0, 1)
    axes[row, 1].set_xticks(range(len(class_names)))
    axes[row, 1].set_xticklabels(class_names, rotation=90, fontsize=8)
    axes[row, 1].set_ylabel(&quot;conf&quot;, fontsize=9)
plt.show()
```&lt;/pre&gt;



&lt;p&gt;This table generates a view where we can explore the confidence our model had in a prediction: By exploring which weight each class was given, we can see where there was doubt (i.e. multiple classes with a higher weight) versus when the model was certain (only one guess). These examples further confirm our intuition: top-types appear to be more commonly confused by the model.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Conclusion&lt;/h2&gt;



&lt;p&gt;And there we have it! We were able to set up and train our first model and already drive some data science insights from our data and model results. Using some of the PyCharm functionalities at this point can speed up the experimentation process by providing access to our documentation and applying code completion directly in the cells. We can even use AI Assistant to help generate some of the graphs we&amp;#8217;ll need to further evaluate the TensorFlow model performance and investigate our results.&lt;/p&gt;



&lt;p&gt;You can &lt;a href=&quot;https://github.com/iuliaferoli/TensorFlow_with_pycharm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;try out this notebook yourself&lt;/a&gt;, or better yet, try to generate it with these same tools for a more hands-on learning experience.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Where to go next&lt;/h2&gt;



&lt;p&gt;&lt;a href=&quot;https://github.com/iuliaferoli/TensorFlow_with_pycharm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;This notebook&lt;/a&gt; is a minimal, teachable starting point. Here are some practical next steps to try afterwards:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Replace the dense baseline with a small CNN (Conv2D → MaxPooling → Dense).&lt;/li&gt;



&lt;li&gt;Add dropout or batch normalization to reduce overfitting.&lt;/li&gt;



&lt;li&gt;Apply data augmentation (random shifts/rotations) to improve generalization.&lt;/li&gt;



&lt;li&gt;Use callbacks like &lt;code&gt;EarlyStopping&lt;/code&gt; and &lt;code&gt;ModelCheckpoint&lt;/code&gt; so training is efficient, and you keep the best weights.&lt;/li&gt;



&lt;li&gt;Export a &lt;code&gt;SavedModel&lt;/code&gt; for server use or convert to TensorFlow Lite for edge devices (Raspberry Pi, microcontrollers).&lt;/li&gt;
&lt;/ul&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;Frequently asked questions&lt;/h2&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;When should I use TensorFlow?&lt;/h3&gt;



&lt;p&gt;TensorFlow is best used when building machine learning or deep learning models that need to scale, go into production, or run across different environments (cloud, mobile, edge devices).&amp;nbsp;&lt;/p&gt;



&lt;p&gt;TensorFlow is particularly well-suited for large-scale models and neural networks, including scenarios where you need strong deployment support (TensorFlow Serving, TensorFlow Lite). For research prototypes, TensorFlow is viable, but it’s more commonplace to use lightweight frameworks for easier experimentation.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Can TensorFlow run on a GPU?&lt;/h3&gt;



&lt;p&gt;Yes, TensorFlow can run GPUs and TPUs. Additionally, using a GPU can significantly speed up training, especially for deep learning models with large datasets. The best part is, TensorFlow will automatically use an available GPU if it’s properly configured.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;What is loss in TensorFlow?&lt;/h3&gt;



&lt;p&gt;Loss (otherwise known as loss function) measures how far a model’s predictions are from the actual target values. Loss in TensorFlow is a numerical value representing the distance between predictions and actual target values. A few examples include:&amp;nbsp;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;MSE (mean squared error), used in regression tasks.&lt;/li&gt;



&lt;li&gt;Cross-entropy loss, often used in classification tasks.&lt;/li&gt;
&lt;/ul&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;How many epochs should I use?&lt;/h3&gt;



&lt;p&gt;There’s no set number of epochs to use, as it depends on your dataset and model. Typical approaches cover:&amp;nbsp;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Starting with a conservative number (10–50 epochs).&lt;/li&gt;



&lt;li&gt;Monitoring validation loss/accuracy and adjusting based on the results you see.&lt;/li&gt;



&lt;li&gt;Using early stopping to halt training when improvements decrease.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;An epoch is one full pass through your training data. Not enough passes through leads to underfitting, and too many can cause overfitting. The sweet spot is where your model generalizes best to unseen data.&amp;nbsp;&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot; id=&quot;author&quot;&gt;About the author&lt;/h2&gt;


    &lt;div class=&quot;about-author &quot;&gt;
        &lt;div class=&quot;about-author__box&quot;&gt;
            &lt;div class=&quot;row&quot;&gt;
                                                            &lt;div class=&quot;about-author__box-img&quot;&gt;
                            &lt;img src=&quot;https://blog.jetbrains.com/wp-content/uploads/2026/04/Iulia-Feroli-e1775558363746.png&quot; alt=&quot;&quot; /&gt;
                        &lt;/div&gt;
                                        &lt;div class=&quot;about-author__box-text&quot;&gt;
                                                    &lt;h4&gt;Iulia Feroli&lt;/h4&gt;
                                                &lt;p&gt;&lt;span&gt;Iulia’s mission is to make tech exciting, understandable, and accessible to the new generation.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;With a background spanning data science, AI, cloud architecture, and open source, she brings a unique perspective on bridging technical depth with approachability.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;She’s building her own brand, Back To Engineering, through which she creates a community for tech enthusiasts, engineers, and makers. From YouTube videos on building robots from scratch, to conference talks or keynotes about real, grounded AI, and technical blogs and tutorials &lt;/span&gt;&lt;span&gt;–&lt;/span&gt;&lt;span&gt; Iulia shares her message worldwide on how to turn complex concepts into tools developers can use every day.&lt;/span&gt;&lt;/p&gt;
                    &lt;/div&gt;
                            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;



&lt;p&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 10:36:35 +0000</pubDate>
</item>
<item>
	<title>PyCon: Stories from the PyCon US Hotels</title>
	<guid>https://pycon.blogspot.com/2026/04/stories-from-pycon-us-hotels.html</guid>
	<link>https://pycon.blogspot.com/2026/04/stories-from-pycon-us-hotels.html</link>
	<description>&lt;p&gt;&lt;span&gt;Friendships, collaborations, and breakthroughs&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span id=&quot;docs-internal-guid-cc92111d-7fff-849b-755a-ebd716d2bf11&quot;&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;The fun, the learning, and the inspiration don't stop when you walk out of the convention center. Some of the most memorable moments from PyCon US happen in the lobby at 10 pm, laughing with someone you only knew as a username until an hour ago; over breakfast, where a casual conversation turns into a collaboration that lasts years; and on the walks to and from the conference. PyCon US hotels have their own lore.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;We asked people about their experiences and were overwhelmed, it turns out that everyone has a story!&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;One story stands out to me beyond getting to know each other and sharing ideas. &lt;/span&gt;&lt;span&gt;When I was getting ready to give my first PyCon talk in Montreal, Selena Deckelmann offered to help review my slides and listen to me practice. We spent a few hours on the floor of her hotel room prepping while her very young daughter crawled around on the floor and chewed on my PyCon badge since she was teething. It's still one of my favorite PyCon and PyLadies memories.” - &lt;/span&gt;&lt;span&gt;Carol Willing, Willing Consulting&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;“The hotel lobby last year turned into a makeshift meetup after the PyLadies Auction. People were having a great time at the auction and kept the energy going in the lobby afterward. Everyone was there, even those who hadn't attended the auction. Luckily, the hotel also sold my favorite chocolate milk in the lobby, so I got to end my evening drinking milk and chatting with Python friends.” &lt;/span&gt;&lt;span&gt;- Cheuk Ting Ho (the PyLady who loves the auction and karaoke)&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;&quot;In Pittsburgh a couple of years ago I was having breakfast at the hotel, when a guy I didn't know spotted my Python T-shirt and introduced himself. It was his first PyCon and my 21st, and we ended up having breakfast together. I gave him a few tips on enjoying a PyCon, but it turned out he was also a guitarist, so we spent most of breakfast talking about music and playing guitar.” - &lt;/span&gt;&lt;span&gt;Naomi Ceder, former board chair and loooong time PyCon goer&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;&quot;I ran into Trey Hunner during my first PyCon US in the hotel lobby as a PSF employee. He was running a Cabo game. He immediately welcomed me and showed me how to play. (He’s a great teacher, so I won three rounds in a row!) I also met a bunch of lovely people who have been attending PyCon US for years and years, and I learned that there is almost always a Cabo game in the hotel lobby.&quot; &lt;/span&gt;&lt;span&gt;- Deb Nicholson (PSF Executive Director &amp;amp; resident Cabo shark)&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;“One of my most memorable hotel lobby moments was a chance encounter with Thomas Wouters. We fell into a natural conversation about his work and his deep, genuine pride in the Python Software Foundation community. He spoke warmly about the people who make the community what it is and what it means to him to be part of it. What I had no idea at the time was that just three days later, he would be called up on stage and announced as a Distinguished Service Award recipient — one of the highest honors the Python Software Foundation gives.” - &lt;/span&gt;&lt;span&gt;Abigail Dogbe, PSF Board Member&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;“Juggling in the hotel lobby turned into an unexpected highlight of the conference. We had started teaching each other — my fault entirely for bringing the juggling balls — when a teenager and his mom wandered through on their way to see Pearl Jam. The kid's eyes lit up the moment he saw us, so I waved them over and started teaching him. Turns out they'd booked that very hotel hoping to cross paths with the band. He was excited about everything, and she was right there with him, every bit as thrilled.” - &lt;/span&gt;&lt;span&gt;Ned Batchelder, Python Core Team and Netflix, Software Engineer&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;And this year, instead of sitting in LA-to-Long Beach traffic, consider staying in the official conference hotel block because there's too much to miss if you're too far away.&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot;&gt;&lt;span&gt;Real Talk: Why booking a room via PyCon US matters&amp;nbsp;&lt;/span&gt;&lt;/h1&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;If you're planning to attend PyCon US, please consider booking your stay within the official conference hotel block.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;When attendees reserve rooms through the block, it helps the conference meet its contractual commitments with the venue, which directly impacts the overall cost of hosting the event.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;Strong participation in the hotel block helps PyCon US:&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;Keep registration prices as low as possible while continuing to invest in programs that support our community, like travel grants, accessibility services, and community events.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;When rooms go unfilled in the block, the conference incurs major financial penalties that ultimately make the event more expensive to run for everyone.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;By booking in the hotel block, you are giving back and helping keep PyCon US sustainable and affordable for the entire Python community.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;h1 dir=&quot;ltr&quot;&gt;&lt;span&gt;PSST! Exclusive swag when you book a room. We can't say more.&lt;/span&gt;&lt;/h1&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;Attendees who book within the official hotel block this year will receive a special mystery swag item. We can't tell you what it is. That's why it's called mystery swag. But we can tell you the only way to get it is to book in the official PyCon US hotel block.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;h1 dir=&quot;ltr&quot;&gt;&lt;span&gt;Where to stay: official PyCon US 2026 hotel block&lt;/span&gt;&lt;/h1&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;All hotels are in Long Beach, within easy reach of the Long Beach Convention Center.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;The Westin Long Beach&lt;/span&gt;&lt;span&gt; Spacious rooms and great amenities, and the block still has availability. &lt;/span&gt;&lt;a href=&quot;https://us.pycon.org/2026/venue/hotels/&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Book here&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;Hyatt Regency Long Beach&lt;/span&gt;&lt;span&gt; is the conference headquarters hotel. Closest to the convention center–just about connected. &lt;/span&gt;&lt;a href=&quot;https://us.pycon.org/2026/venue/hotels/&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Book here&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot;&gt;&lt;span&gt;Marriott Long Beach Downtown&lt;/span&gt;&lt;span&gt; A solid choice with easy access to the convention center and the waterfront. &lt;/span&gt;&lt;a href=&quot;https://us.pycon.org/2026/venue/hotels/&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Book here&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;span&gt;Courtyard by Marriott Long Beach Downtown&lt;/span&gt;&lt;span&gt; A comfortable, more affordable option still within the block. &lt;/span&gt;&lt;a href=&quot;https://us.pycon.org/2026/venue/hotels/&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Book here&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;</description>
	<pubDate>Tue, 07 Apr 2026 10:30:00 +0000</pubDate>
</item>
<item>
	<title>Stéphane Wirtel: Ce livre Python que je voulais juste mettre à jour</title>
	<guid>https://wirtel.be/post/2026/04/07/livre-python-reconstruction/</guid>
	<link>https://wirtel.be/post/2026/04/07/livre-python-reconstruction/</link>
	<description>&lt;h1 id=&quot;ce-livre-python-que-je-voulais-juste-mettre-à-jour&quot;&gt;Ce livre Python que je voulais juste mettre à jour&lt;/h1&gt;
&lt;p&gt;En août dernier, j&amp;rsquo;annonçais la relance de ce livre avec une certaine naïveté : j&amp;rsquo;avais retrouvé mon PDF de 2014, extrait le Markdown avec Docling, et assemblé un pipeline Longform → Pandoc → Typst. Je me disais que ce serait l&amp;rsquo;affaire de quelques semaines — mettre à jour les versions, ajouter quelques chapitres, boucler.&lt;/p&gt;
&lt;p&gt;Huit mois plus tard, le périmètre a triplé, la chaîne d&amp;rsquo;outils a été réécrite, et la façon dont je travaille a complètement changé. Ce n&amp;rsquo;est pas ce que j&amp;rsquo;avais prévu. C&amp;rsquo;est mieux.&lt;/p&gt;</description>
	<pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate>
</item>
<item>
	<title>ListenData: How to Use Gemini API in Python</title>
	<guid>https://www.listendata.com/2024/05/how-to-use-gemini-in-python.html</guid>
	<link>https://www.listendata.com/2024/05/how-to-use-gemini-in-python.html</link>
	<description>&lt;img alt=&quot;Integrating Gemini API with Python&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv7fZDMJQnSKigSmu3bT10rNbDFCUCJjE9vZjSa2Ad0ri3E_9NyEXs32sIu_pvxx77-7ffmAOLbQW9Ip601KaPAPIdpoyXjwKHoQyI0p4uDnY0OEnzOf3W_t600pIt1qyVjD5pNOh0bfzrvHYKpnJ_D3jOQ_QFvd9UIdeGPjgVasQfM3Wt_NisHpE29f4-/s1600/Gemini_API.png&quot; /&gt;
&lt;p&gt;In this tutorial, you will learn how to use Google's Gemini AI model through its API in Python.&lt;/p&gt;
&lt;div class=&quot;note&quot;&gt;&lt;b&gt;Updated (April 3, 2026):&lt;/b&gt; This tutorial has been updated for the latest Gemini models, including &lt;b&gt;Gemini 3.1 Flash&lt;/b&gt; and &lt;b&gt;Gemini 3.1 Pro&lt;/b&gt;. It now supports real-time search, multimodal generation, and the latest Flash/Pro model aliases such as &lt;b&gt;gemini-flash-latest&lt;/b&gt; and &lt;b&gt;gemini-pro-latest&lt;/b&gt;.&lt;/div&gt;

&lt;div class=&quot;db&quot;&gt;Steps to Access Gemini API&lt;/div&gt;
&lt;p&gt;Follow the steps below to access the Gemini API and then use it in python.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Visit &lt;a href=&quot;https://aistudio.google.com/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Google AI Studio&lt;/a&gt; website.&lt;/li&gt;
&lt;li&gt;Sign in using your Google account.&lt;/li&gt;
&lt;li&gt;Create an &lt;a href=&quot;https://aistudio.google.com/app/apikey&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;API key&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install the Google AI Python library for the Gemini API using the command below : &lt;br /&gt; &lt;pre&gt;pip install google-genai&lt;/pre&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;a href=&quot;https://www.listendata.com/2024/05/how-to-use-gemini-in-python.html#more&quot;&gt;To read this article in full, please click here&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;This post appeared first on &lt;a href=&quot;https://www.listendata.com/&quot;&gt;ListenData&lt;/a&gt;&lt;/div&gt;</description>
	<pubDate>Mon, 06 Apr 2026 18:14:28 +0000</pubDate>
</item>

</channel>
</rss>
