Planet Python http://planetpython.org/ en Planet Python - http://planetpython.org/ Ned Batchelder: Testing: exceptions and caches https://nedbatchelder.com/blog/202601/testing_exceptions_and_caches https://nedbatchelder.com/blog/202601/testing_exceptions_and_caches <p>Two testing-related things I found recently.</p><h1 id="h_unified_exception_testing">Unified exception testing<a class="headerlink" href="https://nedbatchelder.com/blog/planetpython.xml#h_unified_exception_testing"></a></h1><p>Kacper Borucki blogged about <a rel="external noopener" href="https://borutzki.github.io/2026/01/15/how-to-parametrize-exception-testing-in-pytest.html">parameterizing exception testing</a>, and linked to <a rel="external noopener" href="https://docs.pytest.org/en/stable/example/parametrize.html#parametrizing-conditional-raising">pytest docs</a> and a <a rel="external noopener" href="https://stackoverflow.com/questions/20274987/how-to-use-pytest-to-check-that-error-is-not-raised/68012715#68012715">StackOverflow answer</a> with similar approaches.</p><p>The common way to test exceptions is to use <a rel="external noopener" href="https://docs.pytest.org/en/7.1.x/how-to/assert.html#assertions-about-expected-exceptions"><code>pytest.raises</code></a> as a context manager, and have separate tests for the cases that succeed and those that fail. Instead, this approach lets you unify them.</p><p>I tweaked it to this, which I think reads nicely:</p><blockquote class="code"><div class="source"><pre class="python"><span class="kn">from</span><span class="w">&#xA0;</span><span class="nn">contextlib</span><span class="w">&#xA0;</span><span class="kn">import</span>&#xA0;<span class="n">nullcontext</span>&#xA0;<span class="k">as</span>&#xA0;<span class="n">produces</span> <br /> <br /><span class="kn">import</span><span class="w">&#xA0;</span><span class="nn">pytest</span> <br /><span class="kn">from</span><span class="w">&#xA0;</span><span class="nn">pytest</span><span class="w">&#xA0;</span><span class="kn">import</span>&#xA0;<span class="n">raises</span> <br /> <br /><span class="nd">@pytest</span><span class="o">.</span><span class="n">mark</span><span class="o">.</span><span class="n">parametrize</span><span class="p">(</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;<span class="s2">&quot;example_input,&#xA0;result&quot;</span><span class="p">,</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">[</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">(</span><span class="mi">3</span><span class="p">,</span>&#xA0;<span class="n">produces</span><span class="p">(</span><span class="mi">2</span><span class="p">)),</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">(</span><span class="mi">2</span><span class="p">,</span>&#xA0;<span class="n">produces</span><span class="p">(</span><span class="mi">3</span><span class="p">)),</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">(</span><span class="mi">1</span><span class="p">,</span>&#xA0;<span class="n">produces</span><span class="p">(</span><span class="mi">6</span><span class="p">)),</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">(</span><span class="mi">0</span><span class="p">,</span>&#xA0;<span class="n">raises</span><span class="p">(</span><span class="ne">ZeroDivisionError</span><span class="p">)),</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">(</span><span class="s2">&quot;Hello&quot;</span><span class="p">,</span>&#xA0;<span class="n">raises</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">)),</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;<span class="p">],</span> <br /><span class="p">)</span> <br /><span class="k">def</span><span class="w">&#xA0;</span><span class="nf">test_division</span><span class="p">(</span><span class="n">example_input</span><span class="p">,</span>&#xA0;<span class="n">result</span><span class="p">):</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">with</span>&#xA0;<span class="n">result</span>&#xA0;<span class="k">as</span>&#xA0;<span class="n">e</span><span class="p">:</span> <br />&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<span class="k">assert</span>&#xA0;<span class="p">(</span><span class="mi">6</span>&#xA0;<span class="o">/</span>&#xA0;<span class="n">example_input</span><span class="p">)</span>&#xA0;<span class="o">==</span>&#xA0;<span class="n">e</span> <br /></pre></div> </blockquote><p>One parameterized test that covers both good and bad outcomes. Nice.</p><h1 id="h_antilru">AntiLRU<a class="headerlink" href="https://nedbatchelder.com/blog/planetpython.xml#h_antilru"></a></h1><p>The <a rel="external noopener" href="https://docs.python.org/3/library/functools.html#functools.lru_cache"><code>@functools.lru_cache</code></a> decorator (and its convenience cousin <code>@cache</code>) are good ways to save the result of a function so that you don&#8217;t have to compute it repeatedly. But, they hide an implicit global in your program: the dictionary of cached results.</p><p>This can interfere with testing. Your tests should all be isolated from each other. You don&#8217;t want a side effect of one test to affect the outcome of another test. The hidden global dictionary will do just that. The first test calls the cached function, then the second test gets the cached value, not a newly computed one.</p><p>Ideally, lru_cache would only be used on <em>pure</em> functions: the result only depends on the arguments. If it&#8217;s only used for pure functions, then you don&#8217;t need to worry about interactions between tests because the answer will be the same for the second test anyway.</p><p>But lru_cache is used on functions that pull information from the environment, perhaps from a network API call. The tests might mock out the API to check the behavior under different API circumstances. Here&#8217;s where the interference is a real problem.</p><p>The lru_cache decorator makes a <code>.clear_cache</code> method available on each decorated function. I had some code that explicitly called that method on the cached functions. But then I added a new cached function, forgot to update the conftest.py code that cleared the caches, and my tests were failing.</p><p>A more convenient approach is provided by <a rel="external noopener" href="https://pypi.org/project/pytest-antilru/">pytest-antilru</a>: it&#8217;s a pytest plugin that monkeypatches <code>@lru_cache</code> to track all of the cached functions, and clears them all between tests. The caches are still in effect during each test, but can&#8217;t interfere between them.</p><p>It works great. I was able to get rid of all of the manually maintained cache clearing in my conftest.py.</p> Sun, 25 Jan 2026 20:32:21 +0000 Talk Python to Me: #535: PyView: Real-time Python Web Apps https://talkpython.fm/episodes/show/535/pyview-real-time-python-web-apps https://talkpython.fm/episodes/show/535/pyview-real-time-python-web-apps Building on the web is like working with the perfect clay. It’s malleable and can become almost anything. But too often, frameworks try to hide the web’s best parts away from us. Today, we’re looking at PyView, a project that brings the real-time power of Phoenix LiveView directly into the Python world. I'm joined by Larry Ogrodnek to dive into PyView.&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;Episode sponsors&lt;/strong&gt;&lt;br/&gt; &lt;br/&gt; &lt;a href='https://talkpython.fm/training'&gt;Talk Python Courses&lt;/a&gt;&lt;br&gt; &lt;a href='https://talkpython.fm/devopsbook'&gt;Python in Production&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;h2 class="links-heading mb-4"&gt;Links from the show&lt;/h2&gt; &lt;div&gt;&lt;strong&gt;Guest&lt;/strong&gt;&lt;br/&gt; &lt;strong&gt;Larry Ogrodnek&lt;/strong&gt;: &lt;a href="https://hachyderm.io/@ogrodnek?featured_on=talkpython" target="_blank" &gt;hachyderm.io&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;pyview.rocks&lt;/strong&gt;: &lt;a href="https://pyview.rocks?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Phoenix LiveView&lt;/strong&gt;: &lt;a href="https://github.com/phoenixframework/phoenix_live_view?featured_on=talkpython" target="_blank" &gt;github.com&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;this section&lt;/strong&gt;: &lt;a href="https://pyview.rocks/getting-started/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Core Concepts&lt;/strong&gt;: &lt;a href="https://pyview.rocks/core-concepts/liveview-lifecycle/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Socket and Context&lt;/strong&gt;: &lt;a href="https://pyview.rocks/core-concepts/socket-and-context/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Event Handling&lt;/strong&gt;: &lt;a href="https://pyview.rocks/core-concepts/event-handling/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;LiveComponents&lt;/strong&gt;: &lt;a href="https://pyview.rocks/core-concepts/live-components/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Routing&lt;/strong&gt;: &lt;a href="https://pyview.rocks/core-concepts/routing/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Templating&lt;/strong&gt;: &lt;a href="https://pyview.rocks/templating/overview/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;HTML Templates&lt;/strong&gt;: &lt;a href="https://pyview.rocks/templating/html-templates/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;T-String Templates&lt;/strong&gt;: &lt;a href="https://pyview.rocks/templating/t-string-templates/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;File Uploads&lt;/strong&gt;: &lt;a href="https://pyview.rocks/features/file-uploads/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Streams&lt;/strong&gt;: &lt;a href="https://pyview.rocks/streams-usage/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Sessions &amp;amp; Authentication&lt;/strong&gt;: &lt;a href="https://pyview.rocks/features/authentication/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Single-File Apps&lt;/strong&gt;: &lt;a href="https://pyview.rocks/single-file-apps/?featured_on=talkpython" target="_blank" &gt;pyview.rocks&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;starlette&lt;/strong&gt;: &lt;a href="https://starlette.dev?featured_on=talkpython" target="_blank" &gt;starlette.dev&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;wsproto&lt;/strong&gt;: &lt;a href="https://github.com/python-hyper/wsproto?featured_on=talkpython" target="_blank" &gt;github.com&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;apscheduler&lt;/strong&gt;: &lt;a href="https://github.com/agronholm/apscheduler?featured_on=talkpython" target="_blank" &gt;github.com&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;t-dom project&lt;/strong&gt;: &lt;a href="https://github.com/t-strings/tdom?featured_on=talkpython" target="_blank" &gt;github.com&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;Watch this episode on YouTube&lt;/strong&gt;: &lt;a href="https://www.youtube.com/watch?v=g0RDxN71azs" target="_blank" &gt;youtube.com&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Episode #535 deep-dive&lt;/strong&gt;: &lt;a href="https://talkpython.fm/episodes/show/535/pyview-real-time-python-web-apps#takeaways-anchor" target="_blank" &gt;talkpython.fm/535&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Episode transcripts&lt;/strong&gt;: &lt;a href="https://talkpython.fm/episodes/transcript/535/pyview-real-time-python-web-apps" target="_blank" &gt;talkpython.fm&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;Theme Song: Developer Rap&lt;/strong&gt;&lt;br/&gt; &lt;strong&gt;🥁 Served in a Flask 🎸&lt;/strong&gt;: &lt;a href="https://talkpython.fm/flasksong" target="_blank" &gt;talkpython.fm/flasksong&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;---== Don't be a stranger ==---&lt;/strong&gt;&lt;br/&gt; &lt;strong&gt;YouTube&lt;/strong&gt;: &lt;a href="https://talkpython.fm/youtube" target="_blank" &gt;&lt;i class="fa-brands fa-youtube"&gt;&lt;/i&gt; youtube.com/@talkpython&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;Bluesky&lt;/strong&gt;: &lt;a href="https://bsky.app/profile/talkpython.fm" target="_blank" &gt;@talkpython.fm&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Mastodon&lt;/strong&gt;: &lt;a href="https://fosstodon.org/web/@talkpython" target="_blank" &gt;&lt;i class="fa-brands fa-mastodon"&gt;&lt;/i&gt; @[email protected]&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;X.com&lt;/strong&gt;: &lt;a href="https://x.com/talkpython" target="_blank" &gt;&lt;i class="fa-brands fa-twitter"&gt;&lt;/i&gt; @talkpython&lt;/a&gt;&lt;br/&gt; &lt;br/&gt; &lt;strong&gt;Michael on Bluesky&lt;/strong&gt;: &lt;a href="https://bsky.app/profile/mkennedy.codes?featured_on=talkpython" target="_blank" &gt;@mkennedy.codes&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Michael on Mastodon&lt;/strong&gt;: &lt;a href="https://fosstodon.org/web/@mkennedy" target="_blank" &gt;&lt;i class="fa-brands fa-mastodon"&gt;&lt;/i&gt; @[email protected]&lt;/a&gt;&lt;br/&gt; &lt;strong&gt;Michael on X.com&lt;/strong&gt;: &lt;a href="https://x.com/mkennedy?featured_on=talkpython" target="_blank" &gt;&lt;i class="fa-brands fa-twitter"&gt;&lt;/i&gt; @mkennedy&lt;/a&gt;&lt;br/&gt;&lt;/div&gt; Fri, 23 Jan 2026 19:29:41 +0000 Real Python: The Real Python Podcast – Episode #281: Continuing to Improve the Learning Experience at Real Python https://realpython.com/podcasts/rpp/281/ https://realpython.com/podcasts/rpp/281/ <p>If you haven't visited the Real Python website lately, then it's time to check out a great batch of updates on realpython.com! Dan Bader returns to the show this week to discuss improvements to the site and more ways to learn Python.</p> <hr /> <p><em>[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp; sweet Python Trick delivered to your inbox every couple of days. <a href="https://realpython.com/python-tricks/?utm_source=realpython&utm_medium=rss&utm_campaign=footer">&gt;&gt; Click here to learn more and see examples</a> ]</em></p> Fri, 23 Jan 2026 12:00:00 +0000 death and gravity: DynamoDB crash course: part 1 – philosophy https://death.andgravity.com/dynamodb https://death.andgravity.com/dynamodb <p>This is part one of a series covering core <strong>DynamoDB</strong> concepts and patterns, from the data model and features all the way up to <strong>single-table design</strong>.</p> <p>The goal is to get you to understand what <strong>idiomatic usage</strong> looks like and what the <strong>trade-offs</strong> are in under an hour, providing entry points to detailed documentation.</p> <p>(Don't get me wrong, the <abbr title="Amazon Web Services">AWS</abbr> documentation is comprehensive, but can be quite complex, and DynamoDB being a relatively low level product with lots of features added over the years doesn't really help with that.)</p> <p>Today, we're looking at <strong>what DynamoDB is</strong> and <strong>why it is the way it is</strong>.</p> <h2 id="what-is-dynamodb">What is DynamoDB?<span class="headerlink">&nbsp;<a href="https://death.andgravity.com/dynamodb#what-is-dynamodb" title="permalink">#</a></span></h2> <p>Quoting <a class="external" href="https://en.wikipedia.org/wiki/Amazon_DynamoDB">Wikipedia</a>:</p> <blockquote> <p><strong>Amazon DynamoDB</strong> is a managed NoSQL database service provided by <abbr title="Amazon Web Services">AWS</abbr>. It supports key-value and document data structures and is designed to handle a wide range of applications requiring scalability and performance.</p> </blockquote> <p class="admonition-title">See also</p> <p>This definition should suffice for now; for a more detailed refresher, see:</p> <ul> <li><a class="external" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html">What is Amazon DynamoDB?</a></li> <li><a class="external" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html">Core components</a></li> </ul> <p>The DynamoDB data model can be summarized as follows:</p> <p><em>A <strong>table</strong> is a collection of <strong>items</strong>, and an item is a collection of named <strong>attributes</strong>. Items are uniquely identified by a <strong>partition key</strong> attribute and an optional <strong>sort key</strong> attribute. The partition key determines where (i.e. on what computer) an item is stored. The sort key is used to get ordered ranges of items from a specific partition.</em></p> <p>That's is, that's the whole data model. Sure, there's indexes and transactions and other features, but at its core, this is it. Put another way:</p> <p>A DynamoDB table is <strong>a <a class="external" href="https://en.wikipedia.org/wiki/Hash_table">hash table</a> of <a class="external" href="https://en.wikipedia.org/wiki/B-tree">B-trees</a></strong><sup class="footnote-ref" id="fnref-1"><a href="https://death.andgravity.com/dynamodb#fn-1">1</a></sup> – partition keys are hash table keys, and sort keys are B-tree keys. Because of this, <strong>any access not based on partition and sort key is expensive</strong>, since you end up doing a full table scan.</p> <!-- TODO simple db footnote --> <p>If you were to implement this model in Python, it'd look something like this:</p> <div class="highlight code-container"><pre class="code"><span></span><code><span class="kn">from</span><span class="w"> </span><span class="nn">collections</span><span class="w"> </span><span class="kn">import</span> <span class="n">defaultdict</span> <span class="kn">from</span><span class="w"> </span><span class="nn">sortedcontainers</span><span class="w"> </span><span class="kn">import</span> <span class="n">SortedDict</span> <span class="k">class</span><span class="w"> </span><span class="nc">Table</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pk_name</span><span class="p">,</span> <span class="n">sk_name</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pk_name</span> <span class="o">=</span> <span class="n">pk_name</span> <span class="bp">self</span><span class="o">.</span><span class="n">_sk_name</span> <span class="o">=</span> <span class="n">sk_name</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="n">SortedDict</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">put_item</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span> <span class="n">pk</span><span class="p">,</span> <span class="n">sk</span> <span class="o">=</span> <span class="n">item</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk_name</span><span class="p">],</span> <span class="n">item</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_sk_name</span><span class="p">]</span> <span class="n">old_item</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">sk</span><span class="p">,</span> <span class="p">{})</span> <span class="n">old_item</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span> <span class="n">old_item</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_item</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pk</span><span class="p">,</span> <span class="n">sk</span><span class="p">):</span> <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span><span class="p">[</span><span class="n">pk</span><span class="p">][</span><span class="n">sk</span><span class="p">])</span> <span class="k">def</span><span class="w"> </span><span class="nf">query</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pk</span><span class="p">,</span> <span class="n">minimum</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">maximum</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">inclusive</span><span class="o">=</span><span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span> <span class="c1"># in the real DynamoDB, this operation is paginated</span> <span class="n">partition</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span> <span class="k">for</span> <span class="n">sk</span> <span class="ow">in</span> <span class="n">partition</span><span class="o">.</span><span class="n">irange</span><span class="p">(</span><span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span><span class="p">,</span> <span class="n">inclusive</span><span class="p">,</span> <span class="n">reverse</span><span class="p">):</span> <span class="k">yield</span> <span class="nb">dict</span><span class="p">(</span><span class="n">partition</span><span class="p">[</span><span class="n">sk</span><span class="p">])</span> <span class="k">def</span><span class="w"> </span><span class="nf">scan</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># in the real DynamoDB, this operation is paginated</span> <span class="k">for</span> <span class="n">partition</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">partition</span><span class="o">.</span><span class="n">values</span><span class="p">():</span> <span class="k">yield</span> <span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">update_item</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span> <span class="n">pk</span><span class="p">,</span> <span class="n">sk</span> <span class="o">=</span> <span class="n">item</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_pk_name</span><span class="p">],</span> <span class="n">item</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_sk_name</span><span class="p">]</span> <span class="n">old_item</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span><span class="p">[</span><span class="n">pk</span><span class="p">]</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">sk</span><span class="p">,</span> <span class="p">{})</span> <span class="n">old_item</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">delete_item</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">pk</span><span class="p">,</span> <span class="n">sk</span><span class="p">):</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_partitions</span><span class="p">[</span><span class="n">pk</span><span class="p">][</span><span class="n">sk</span><span class="p">]</span> </code></pre></div> <div class="highlight code-container"><pre class="code"><span></span><code><span class="gp">&gt;&gt;&gt; </span><span class="n">table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">'Artist'</span><span class="p">,</span> <span class="s1">'SongTitle'</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt;</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">table</span><span class="o">.</span><span class="n">put_item</span><span class="p">({</span><span class="s1">'Artist'</span><span class="p">:</span> <span class="s1">'1000mods'</span><span class="p">,</span> <span class="s1">'SongTitle'</span><span class="p">:</span> <span class="s1">'Vidage'</span><span class="p">,</span> <span class="s1">'Year'</span><span class="p">:</span> <span class="mi">2011</span><span class="p">})</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">table</span><span class="o">.</span><span class="n">put_item</span><span class="p">({</span><span class="s1">'Artist'</span><span class="p">:</span> <span class="s1">'1000mods'</span><span class="p">,</span> <span class="s1">'SongTitle'</span><span class="p">:</span> <span class="s1">'Claws'</span><span class="p">,</span> <span class="s1">'Album'</span><span class="p">:</span> <span class="s1">'Vultures'</span><span class="p">})</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">table</span><span class="o">.</span><span class="n">put_item</span><span class="p">({</span><span class="s1">'Artist'</span><span class="p">:</span> <span class="s1">'Kyuss'</span><span class="p">,</span> <span class="s1">'SongTitle'</span><span class="p">:</span> <span class="s1">'Space Cadet'</span><span class="p">})</span> <span class="gp">&gt;&gt;&gt;</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">table</span><span class="o">.</span><span class="n">get_item</span><span class="p">(</span><span class="s1">'1000mods'</span><span class="p">,</span> <span class="s1">'Claws'</span><span class="p">)</span> <span class="go">{'Artist': '1000mods', 'SongTitle': 'Claws', 'Album': 'Vultures'}</span> <span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">i</span><span class="p">[</span><span class="s1">'SongTitle'</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">'1000mods'</span><span class="p">)]</span> <span class="go">['Claws', 'Vidage']</span> <span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">i</span><span class="p">[</span><span class="s1">'SongTitle'</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">table</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">'1000mods'</span><span class="p">,</span> <span class="n">minimum</span><span class="o">=</span><span class="s1">'Loose'</span><span class="p">)]</span> <span class="go">['Vidage']</span> </code></pre></div> <h2 id="philosophy">Philosophy<span class="headerlink">&nbsp;<a href="https://death.andgravity.com/dynamodb#philosophy" title="permalink">#</a></span></h2> <p>One can't help but feel this kind of simplicity would be severely limiting.</p> <p>A consequence of DynamoDB being this low level is that, unlike with most relational databases, <strong>query planning</strong> and sometimes <strong>index management</strong> happen at the <strong>application level</strong>, i.e. you have to do them yourself in code. In turn, this means you need to have a clear, <strong>upfront understanding</strong> of your application's <strong>access patterns</strong>, and accept that changes in access patterns will require changes to the application.</p> <p>In return, you get a <strong>fully managed</strong>, <strong>highly-available</strong> database that <strong>scales infinitely</strong>:<sup class="footnote-ref" id="fnref-2"><a href="https://death.andgravity.com/dynamodb#fn-2">2</a></sup> there are no servers to take care of, there's almost no downtime, and there are no limits on table size or the number of items in a table; where limits do exist, they are clearly documented, allowing for <strong>predictable performance</strong>.</p> <p>This highlights an intentional design decision that is essentially DynamoDB's main proposition to you as its user: <strong>data modeling complexity is always preferable to complexity coming from infrastructure maintenance, availability, and scalability</strong> (what <abbr title="Amazon Web Services">AWS</abbr> marketing calls &quot;undifferentiated heavy lifting&quot;).</p> <p>To help manage this complexity, a number of design patterns have arisen, covered extensively by the official documentation, and which we'll discuss in a future article. Even so, the toll can be heavy – by <abbr title="Amazon Web Services">AWS</abbr>'s <a class="external" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/data-modeling-foundations.html#data-modeling-foundations-single">own admission</a>, the prime disadvantage of single table design, the fundamental design pattern, is that:</p> <blockquote> <p>[the] learning curve can be steep due to paradoxical design compared to relational databases</p> </blockquote> <p>As <a class="external" href="https://www.trek10.com/blog/dynamodb-single-table-relational-modeling/">this walkthrough</a> puts it:</p> <blockquote> <p>a well-optimized single-table DynamoDB layout looks more like machine code than a simple spreadsheet</p> </blockquote> <p>...which, admittedly, sounds pretty cool, but also why would I want that? After all, most useful programming most people do is one or two abstraction levels above assembly, itself one over machine code.</p> <p class="admonition-title">See also</p> <ul> <li><a class="external" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-nosql-design.html">NoSQL design</a></li> <li><small>(unofficial)</small> <a class="external" href="https://www.alexdebrie.com/posts/dynamodb-limits/#the-dynamodb-philosophy-of-limits"># The DynamoDB philosophy of limits</a></li> </ul> <h2 id="a-bit-of-history">A bit of history<span class="headerlink">&nbsp;<a href="https://death.andgravity.com/dynamodb#a-bit-of-history" title="permalink">#</a></span></h2> <p>Perhaps it's worth having a look at where DynamoDB comes from.</p> <p>Amazon.com used Oracle databases for a long time. To cope with the increasing scale, they first adopted a database-per-service model, and then sharding, with all the architectural and operational overhead you would expect. At its 2017 peak (five years after DynamoDB was released in <abbr title="Amazon Web Services">AWS</abbr>, and over ten years after some version of it was available internally), they <a class="external" href="https://youtu.be/vPF9l9OmiXE?t=449">still had</a> 75 PB of data in nearly 7500 Oracle databases, owned by 100+ teams, with thousands of applications, <em>for <abbr title="Online Transaction Processing">OLTP</abbr> workloads alone</em>. That sounds pretty traumatic – it was definitely bad enough to <a class="external" href="https://news.ycombinator.com/item?id=42677767">allegedly</a> ban <abbr title="Online Transaction Processing">OLTP</abbr> relational databases internally, and require that teams get VP approval to use one.</p> <p>Yeah, coming from <em>that</em>, it's hard to argue DynamoDB adds complexity.</p> <p>That is not to say relational databases cannot be as scalable as DynamoDB, just that Amazon doesn't belive in them – <a class="external" href="https://en.wikipedia.org/wiki/Distributed_SQL">distributed SQL</a> databases like Google's <a class="external" href="https://en.wikipedia.org/wiki/Spanner_(database)">Spanner</a> and <a class="external" href="https://en.wikipedia.org/wiki/CockroachDB">CockroachDB</a> have existed for a while now, and even <abbr title="Amazon Web Services">AWS</abbr> seems to be <a class="external" href="https://aws.amazon.com/blogs/database/introducing-amazon-aurora-dsql/">warming up</a> to the idea.</p> <p>This might also explain why the design patterns are so slow to make their way into SDKs, or even better, into DynamoDB itself; when you have so many applications and so many experienced teams, the cost of yet another bit of code to do partition key sharding just isn't that great.</p> <p class="admonition-title">See also</p> <ul> <li><small>(paper)</small> <a class="external" href="https://www.usenix.org/system/files/atc22-elhemali.pdf">Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service</a> (2022)</li> <li><small>(paper)</small> <a class="external" href="https://assets.amazon.science/ac/1d/eb50c4064c538c8ac440ce6a1d91/dynamo-amazons-highly-available-key-value-store.pdf">Dynamo: Amazon’s Highly Available Key-value Store</a> (2007)</li> </ul> <hr /> <p>Anyway, that's it for now.</p> <p>In the next article, we'll have a closer look at the DynamoDB <strong>data model</strong> and <strong>features</strong>.</p> <p><strong>Learned something new today?</strong> Share it with others, it really helps! <span class="text-large"> <span class="share-icons"> <a class="share-icon pycoders color" href="https://pycoders.com/submissions" target="_blank">PyCoder's Weekly</a> <a class="share-icon hacker-news color" href="https://news.ycombinator.%63%6f%6d/submitlink?u=https%3A//death.andgravity.com/dynamodb&t=DynamoDB%20crash%20course%3A%20part%201%20%E2%80%93%20philosophy">HN</a> <a class="share-icon bluesky color" href="https://bsky.%61%70%70/intent/compose?text=DynamoDB%20crash%20course%3A%20part%201%20%E2%80%93%20philosophy%20https%3A//death.andgravity.com/dynamodb">Bluesky</a> <!-- <a class="share-icon reddit color" href="https://www.reddit.%63%6f%6d/%73%75%62%6d%69%74?url=https%3A//death.andgravity.com/dynamodb&amp;title=DynamoDB%20crash%20course%3A%20part%201%20%E2%80%93%20philosophy" >Reddit</a> --> <a class="share-icon linkedin color" href="https://www.linkedin.%63%6f%6d/sharing/share-offsite/?url=https%3A//death.andgravity.com/dynamodb">linkedin</a> <a class="share-icon twitter color" href="https://twitter.%63%6f%6d/%73%68%61%72%65?text=DynamoDB%20crash%20course%3A%20part%201%20%E2%80%93%20philosophy&url=https%3A//death.andgravity.com/dynamodb&via=_andgravity">Twitter</a> </span> </span></p> <p><b> Want to know when new articles come out? <a href="https://death.andgravity.com/dynamodb#embedded-subscribe-form">Subscribe here</a> to get new stuff straight to your inbox! </b></p> <ol> <li id="fn-1"><p>Or any other sorted data structure that allows fast searches, sequential access, insertions, and deletions. <a href="https://death.andgravity.com/dynamodb#fnref-1" class="footnote"><sup>[return]</sup></a></p></li> <li id="fn-2"><p>As the saying goes, the cloud is just someone else's computers. Here, &quot;infinitely&quot; means it scales horizontally, and you'll run out of money before <abbr title="Amazon Web Services">AWS</abbr> runs out of computers. <a href="https://death.andgravity.com/dynamodb#fnref-2" class="footnote"><sup>[return]</sup></a></p></li> </ol> Fri, 23 Jan 2026 08:40:00 +0000 The Python Coding Stack: The Orchestra Conductor, The Senior Programmer, and AI • [Club] https://www.thepythoncodingstack.com/p/the-orchestra-conductor-the-senior https://www.thepythoncodingstack.com/p/the-orchestra-conductor-the-senior <p>I spent a few years learning to play the piano when I was a child. It was always clear I would never be a concert pianist. Or a pianist of any description. This is to say that I don&#8217;t know much about music. I still struggle to understand why an orchestra needs a conductor&#8211;don&#8217;t the musicians all have the score that they can play nearly perfectly?</p><p>And many people who comment about programming and AI know as much about programming as I know about music&#8230;and probably even less about AI.</p><p>But the orchestra conductor analogy seems a good one. Let me explore it further.</p> <p> <a href="https://www.thepythoncodingstack.com/p/the-orchestra-conductor-the-senior"> Read more </a> </p> Thu, 22 Jan 2026 22:33:52 +0000 Reuven Lerner: Learn to code with AI — not just write prompts https://lerner.co.il/2026/01/22/learn-to-code-with-ai-not-just-write-prompts/ https://lerner.co.il/2026/01/22/learn-to-code-with-ai-not-just-write-prompts/ <div class="wp-block-image"> <a href="https://LernerPython.com"><img width="868" height="454" src="https://lerner.co.il/wp-content/uploads/2025/10/LERNER-Logo_Dark.png" alt="" class="wp-image-4545" /></a></div> <p>The AI revolution is here. Engineers at major companies are now using AI instead of writing code directly.</p> <p>But there&#8217;s a gap: Most developers know how to write code OR how to prompt AI, but not both. When working with real data, vague AI prompts produce code that might work on sample datasets but <strong>creates silent errors, performance issues, or incorrect analyses</strong> with messy, real-world data that requires careful handling.</p> <p>I&#8217;ve spent 30 years teaching Python <strong>at companies like Apple, Intel, and Cisco</strong>, plus at conferences worldwide. I&#8217;m adapting my teaching for the AI era.</p> <p>Specifically: I&#8217;m launching <strong>AI-Powered Python Practice Workshops.</strong> These are hands-on sessions where you&#8217;ll solve real problems using Claude Code, then learn to critically evaluate and improve the results.</p> <p>Here&#8217;s how it works:</p> <ol class="wp-block-list"> <li>I present a problem</li> <li>You solve it using Claude Code</li> <li>We compare prompts, discuss what worked (and what didn&#8217;t)</li> <li>I provide deep-dives on both the Python concepts AND the AI collaboration techniques</li> </ol> <p>In 3 hours, we&#8217;ll cover 3-4 exercises. That&#8217;ll give you a chance to learn two skills: Python/Pandas AND effective AI collaboration. That&#8217;ll make you more effective at coding, and at the data analysis techniques that actually work with messy, real-world datasets.</p> <p>Each workshop costs $200 for <a href="https://LernerPython.com">LernerPython</a> members. Not a member? Total cost is $700 ($500 annual membership + $200 workshop fee). Want both workshops? $900 total ($500 membership + $400 for both workshops). Plus you get 40+ courses, 500+ exercises, office hours, Discord, and personal mentorship.</p> <h2 class="wp-block-heading"><strong>AI-Powered Python Practice Workshop</strong></h2> <ul class="wp-block-list"> <li>Focus is on the Python language, standard library, and common packages</li> <li>Monday, February 2nd <ul class="wp-block-list"> <li>10 a.m. &#8211; 1 p.m. Eastern / 3 p.m. &#8211; 6 p.m. London / 5 p.m. &#8211; 8 p.m. Israel</li> <li>Sign up here: <a href="https://lernerpython.com/product/ai-python-workshop-1/">https://lernerpython.com/product/ai-python-workshop-1/</a></li> </ul> </li> </ul> <h2 class="wp-block-heading"><strong>AI-Powered Pandas Practice Workshop</strong></h2> <ul class="wp-block-list"> <li>Focus is on data analysis with Pandas</li> <li>Monday, February 9th <ul class="wp-block-list"> <li>10 a.m. &#8211; 1 p.m. Eastern / 3 p.m. &#8211; 6 p.m. London / 5 p.m. &#8211; 8 p.m. Israel</li> <li>Sign up here: <a href="https://lernerpython.com/product/ai-pandas-workshop-1/">https://lernerpython.com/product/ai-pandas-workshop-1/</a></li> </ul> </li> </ul> <p>I want to encourage lots of discussion and interactions, so I&#8217;m limiting the class to 20 total participants. Both sessions will be recorded, and will be available to all participants.</p> <p>Questions? Just e-mail me at <a href="mailto:[email protected]">[email protected]</a>.</p> <p></p> <span class="tve-leads-two-step-trigger tl-2step-trigger-0"></span><span class="tve-leads-two-step-trigger tl-2step-trigger-0"></span><p>The post <a href="https://lerner.co.il/2026/01/22/learn-to-code-with-ai-not-just-write-prompts/">Learn to code with AI — not just write prompts</a> appeared first on <a href="https://lerner.co.il">Reuven Lerner</a>.</p> Thu, 22 Jan 2026 15:53:12 +0000 Python Software Foundation: Announcing Python Software Foundation Fellow Members for Q4 2025! 🎉 https://pyfound.blogspot.com/2026/01/announcing-python-software-foundation.html https://pyfound.blogspot.com/2026/01/announcing-python-software-foundation.html <p>&nbsp;</p><p><span>The PSF is pleased to announce its fourth </span><span>batch</span><span> of PSF Fellows for </span><span>2025</span><span>! Let us welcome the new PSF Fellows for </span><span>Q4</span><span>! The following people continue to do amazing things for the Python community:</span></p><p dir="ltr"><span>Chris Brousseau</span></p><p dir="ltr"><span><a href="https://surfaceowl.com/" target="_blank">Website</a>, <a href="https://www.linkedin.com/in/chrisbrousseau/" target="_blank">LinkedIn</a>, <a href="https://github.com/surfaceowl" target="_blank">GitHub</a>, <a href="https://mastodon.social/@surfaceowl" target="_blank">Mastodon</a>, <a href="https://x.com/surfaceowl" target="_blank">X</a>, <a href="https://pybay.org/" target="_blank">PyBay,</a> <a href="https://github.com/pybay" target="_blank">PyBay GitHub</a></span></p><p dir="ltr"><span>Dave Forgac</span></p><p dir="ltr"><span><a href="https://daveops.com/" target="_blank">Website</a>, <a href="https://mastodon.social/@tylerdave" target="_blank">Mastodon</a>, <a href="https://github.com/tylerdave" target="_blank">GitHub</a>, <a href="https://www.linkedin.com/in/daveforgac/" target="_blank">LinkedIn</a></span></p><p dir="ltr"><span>Inessa Pawson</span></p><p dir="ltr"><span><a href="https://github.com/InessaPawson" target="_blank">GitHub</a>, <a href="https://linkedin.com/in/ipawson" target="_blank">LinkedIn</a></span></p><p dir="ltr"><span>James Abel</span></p><p dir="ltr"><span><a href="http://www.abel.co/" target="_blank">Website</a>, <a href="https://www.linkedin.com/in/jamesabel/" target="_blank">LinkedIn</a>, <a href="https://github.com/jamesabel" target="_blank">GitHub</a>, <a href="https://bsky.app/profile/jamesabel.bsky.social" target="_blank">Bluesky</a></span></p><p dir="ltr"><span>Karen Dalton</span></p><p dir="ltr"><span><a href="https://www.linkedin.com/in/karend" target="_blank">LinkedIn</a></span></p><p dir="ltr"><span>Mia Bajić</span></p><p dir="ltr"><span>Tatiana Andrea Delgadillo Garzofino</span></p><p dir="ltr"><span><a href="https://taicoding.com/" target="_blank">Website</a>, <a href="https://github.com/taicoding" target="_blank">GitHub</a>, <a href="https://linkedin.com/in/taicoding" target="_blank">LinkedIn</a>, <a href="https://www.instagram.com/taicoding" target="_blank">Instagram</a></span></p><p dir="ltr"><span>Thank you for your continued contributions. We have added you to our <a href="https://www.python.org/psf/fellows-roster/" target="_blank">Fellows Roster</a></span><span>.</span></p><p dir="ltr"><span>The above members help support the Python ecosystem by being phenomenal leaders, sustaining the growth of the Python scientific community, maintaining virtual Python communities, maintaining Python libraries, creating educational material, organizing Python events and conferences, starting Python communities in local regions, and overall being great mentors in our community. Each of them continues to help make Python more accessible around the world. To learn more about the new Fellow members, check out their links above.</span></p><p dir="ltr"><span>Let's continue recognizing Pythonistas all over the world for their impact on our community. The criteria for Fellow members is available on our <a href="https://www.python.org/psf/fellows" target="_blank">PSF Fellow Membership page</a></span><span>. If you would like to nominate someone to be a PSF Fellow, please send a description of their Python accomplishments and their email address to psf-fellow at python.org.</span><span> We are accepting nominations for </span><span>Quarter 1 of 2026 through February 20th, 2026</span><span>.</span></p><p dir="ltr"><span>Are you a PSF Fellow and want to help the Work Group review nominations? Contact us at psf-fellow at python.org.</span></p> Thu, 22 Jan 2026 08:13:00 +0000 Django Weblog: Djangonaut Space - Session 6 Accepting Applications https://www.djangoproject.com/weblog/2026/jan/21/djangonaut-space-session-6-accepting-applications/ https://www.djangoproject.com/weblog/2026/jan/21/djangonaut-space-session-6-accepting-applications/ <p>We are thrilled to announce that Djangonaut Space, a mentorship program for contributing to Django, is <a href="https://djangonaut.space/sessions/2026-session-6/">open for applicants for our next cohort!</a> 🚀</p> <p>Djangonaut Space is holding a sixth session! This session will start on March 2nd, 2026. We are currently accepting applications until <strong>February 2nd, 2026 Anywhere on Earth</strong>. More details can be found in the <a href="https://djangonaut.space/comms/2026/01/18/2026-opening-session-6/">website</a>.</p> <p>Djangonaut Space is a free, 8-week group mentoring program where individuals will work self-paced in a semi-structured learning environment. It seeks to help members of the community who wish to level up their current Django code contributions and potentially take on leadership roles in Django in the future.</p> <blockquote> <p>“I'm so grateful to have been a part of the Djangonaut Space program. It's a wonderfully warm, diverse, and welcoming space, and the perfect place to get started with Django contributions. The community is full of bright, talented individuals who are making time to help and guide others, which is truly a joy to experience. Before Djangonaut Space, I felt as though I wasn't the kind of person who could become a Django contributor; now I feel like I found a place where I belong.” - Eliana, Djangonaut Session 1</p> </blockquote> <p>Enthusiastic about contributing to Django but wondering what we have in store for you? No worries, we have got you covered! 🤝</p> <p>✏️ <a href="https://djangonaut.space/comms/2026/01/18/2026-opening-session-6/">Mission Briefing</a></p> <p>📷 <a href="https://youtu.be/6bjCIOCpdM4">AMA Recap</a></p> Wed, 21 Jan 2026 18:13:15 +0000 Python Software Foundation: Departing the Python Software Foundation (Staff) https://pyfound.blogspot.com/2026/01/ee-departing-the-psf-staff.html https://pyfound.blogspot.com/2026/01/ee-departing-the-psf-staff.html <p><span>This week will be my last as the Director of Infrastructure at the Python Software Foundation and my last week as a staff member. Supporting the mission of this organization with my labor has been unbelievable in retrospect and I am filled with gratitude to every member of this community, volunteer, sponsor, board member, and staff member of this organization who have worked alongside me and entrusted me with [email protected] f</span><span>or all this time.</span></p><span id="docs-internal-guid-1da6e136-7fff-37dc-9256-1924027a973e"><br /><p dir="ltr"><span>But, it is time for me to do something new. I don’t believe there would ever be a perfect time for this transition, but I do believe that now is one of the best. The PSF has built out a team that shares the responsibilities I carried across our technical infrastructure, the maintenance and support of PyPI, relationships with our in-kind sponsors, and the facilitation of PyCon US. I’m also not “burnt-out” or worse, I knew that one day I would move on “dead or alive” and it is so good to feel alive in this decision, literally and figuratively.</span></p><br /></span><blockquote><span><p><i><span>“The PSF and the Python community are very lucky to have had Ee at the helm for so many years. Ee’s approach to our technical needs has been responsive and resilient as Python, PyPI, PSF staff and the community have all grown, and their dedication to the community has been unmatched and unwavering. Ee is leaving the PSF in fantastic shape, and I know I join the rest of the staff in wishing them all the best as they move on to their next endeavor.”</span>&nbsp;</i></p></span></blockquote><blockquote><span><p><span>- Deb Nicholson, Executive Director</span></p></span></blockquote><span><br /><p dir="ltr"><span>The health and wellbeing of the PSF and the Python community is of utmost importance to me, and was paramount as I made decisions around this transition. Given that, I am grateful to be able to commit 20% of my time over the next six months to the PSF to provide support and continuity. Over the past few weeks we’ve been working internally to set things up for success, and I look forward to meeting the new staff and what they accomplish with the team at the PSF!</span></p><br /><p dir="ltr"><span>My participation in the Python community and contributions to the infrastructure began long before my role as a staff member. As I transition out of participating as PSF staff I look forward to continuing to participate in and contribute to this community as a volunteer, as long as I am lucky enough to have the chance.</span></p></span> Wed, 21 Jan 2026 15:00:02 +0000 Reuven Lerner: We’re all VCs now: The skills developers need in the AI era https://lerner.co.il/2026/01/21/were-all-vcs-now-the-skills-developers-need-in-the-ai-era/ https://lerner.co.il/2026/01/21/were-all-vcs-now-the-skills-developers-need-in-the-ai-era/ <p>Many years ago, a friend of mine described how software engineers solve problems:</p> <ul class="wp-block-list"> <li>When you&#8217;re starting off, you solve problems with code.</li> <li>When you get more experienced, you solve problems with people.</li> <li>When you get even more experienced, you solve problems with money.</li> </ul> <p>In other words: You can be the person writing the code, and solving the problem directly. Or you can manage people, specifying what they should do. Or you can invest in teams, telling them about the problems you want to solve, but letting them set specific goals and managing the day-to-day work.</p> <p>Up until recently, I was one of those people who said, &#8220;Generative AI is great, but it&#8217;s not nearly ready to write code on our behalf.&#8221; I spoke and wrote about how AI presents an amazing learning opportunity, and how I&#8217;ve integrated AI-based learning into my courses.</p> <h2 class="wp-block-heading">Things have changed&#8230; and are still changing</h2> <p>I&#8217;ve recently realized that my perspective is oh-so-last year. Because in 2026, many companies and individuals are using AI to write code on their behalf. In just the last two weeks, I&#8217;ve spoken with developers who barely touch code, having AI to develop it for them. And in case you&#8217;re wondering whether this only applies to freelancers, I&#8217;ve spoken with people from several large, well-known companies, who have said something similar.</p> <p>And it&#8217;s not just me: Gergely<a href="https://www.linkedin.com/in/gergelyorosz/overlay/about-this-profile/"> </a>Orosz, who writes the Pragmatic Engineer newsletter, recently wrote that AI-written code is &#8220;mega-trend set to hit the tech industry,&#8221; and that a growing number of companies are already relying on AI to specify, write, and test code (<a href="https://newsletter.pragmaticengineer.com/p/when-ai-writes-almost-all-code-what">https://newsletter.pragmaticengineer.com/p/when-ai-writes-almost-all-code-what</a>).</p> <p>And Simon Willison, who has been discussing and evaluating AI models in great depth for several years, has seen a sea change in model-generated code quality in just the last few months. He predicts that within six years, it&#8217;ll be as quaint for a human to type code as it is to use punch cards (<a href="https://simonwillison.net/2026/Jan/8/llm-predictions-for-2026/#6-years-typing-code-by-hand-will-go-the-way-of-punch-cards">https://simonwillison.net/2026/Jan/8/llm-predictions-for-2026/#6-years-typing-code-by-hand-will-go-the-way-of-punch-cards</a>).</p> <h2 class="wp-block-heading">An inflection point in the tech industry</h2> <p>This is mind blowing. I still remember taking an AI course during my undergraduate years at MIT, learning about cutting-edge AI research&#8230; and finding it quite lacking. I did a bit of research at MIT&#8217;s AI Lab, and saw firsthand how hard language recognition was. To think that we can now type or talk to an AI model, and get coherent, useful results, continues to astound me, in part because I&#8217;ve seen just how far this industry has gone.</p> <p>When ChatGPT first came out, it was breathtaking to see that it could code. It didn&#8217;t code that well, and often made mistakes, but that wasn&#8217;t the point. It was far better than nothing at all. In some ways, it was like the old saw about dancing bears, amazing that it could dance at all, never mind dancing well.</p> <p>Over the last few years, GenAI companies have been upping their game, slowly but surely. They still get things wrong, and still give me bad coding advice and feedback. But for the most part, they&#8217;re doing an increasingly impressive job. And from everything I&#8217;m seeing, hearing, and reading, this is just the beginning.</p> <p>Whether the current crop of AI companies survives their cash burn is another question entirely. But the technology itself is here to stay, much like how the dot-com crash of 2000 didn&#8217;t stop the Internet.</p> <p>We&#8217;re at an inflection point in the computer industry, one that is increasingly allowing one person to create a large, complex software system without writing it directly. In other words: Over the coming years, programmers will spend less and less time writing code. They&#8217;ll spend more and more time partnering with AI systems — specifying what the code should do, what is considered success, what errors will be tolerated, and how scalable the system will be.</p> <p>This is both exciting and a bit nerve-wracking. </p> <h2 class="wp-block-heading">Engineering &gt;&gt; Coding</h2> <p>The shift from &#8220;coder&#8221; to &#8220;engineer&#8221; has been going on for years. We abstracted away machine code, then assembly, then manual memory management. AI represents the biggest abstraction leap yet. Instead of abstracting away implementation details, we&#8217;re abstracting away implementation itself.</p> <p>But software engineering has long been more than just knowing how to code. It&#8217;s about problem solving, about critical thinking, and about considering not just how to build something, but how to maintain it. It&#8217;s true that coding might go away as an individual discipline, much as there&#8217;s no longer much of a need for professional scribes in a world where everyone knows how to write.</p> <p>However, it does mean that to succeed in the software world, it&#8217;ll no longer be enough to understand how computers work, and how to effectively instruct them with code. You&#8217;ll have to have many more skills, skills which are almost never taught to coders, because there were already so many fundamentals you needed to learn.</p> <p>In this new age, creating software will be increasingly similar to being an investor. You&#8217;ll need to have a sense of the market, and what consumers want. You&#8217;ll need to know what sorts of products will potentially succeed in the market. You&#8217;ll need to set up a team that can come up with a plan, and execute on it. And then you&#8217;ll need to be able to evaluate the results. If things succeed, then great! And if not, that&#8217;s OK — you&#8217;ll invest in a number of other ventures, hoping that one or more will get the 10x you need to claim success.</p> <p>If that seems like science fiction, it isn&#8217;t. I&#8217;ve seen and heard about amazing success with Claude Code from other people, and I&#8217;ve started to experience it myself, as well. You can have it set up specifications. You can have it set up tests. You can have it set up a list of tasks. You can have it work through those tasks. You can have it consult with other GenAI systems, to bring in third-party advice. And this is just the beginning.</p> <h2 class="wp-block-heading">Programming in English?</h2> <p>When ChatGPT was first released, many people quipped that the hottest programming language is now English. I laughed at that then, less because of the quality of AI coding, and more because most people, even given a long time, don&#8217;t have the experience and training to specify a programming project. I&#8217;ve been to too many meetings in which developers and project managers exchange harsh words because they interpreted vaguely specified features differently. And that&#8217;s with humans, who presumably understand the specifications better!</p> <p>As someone said to me many years ago, computers do what you tell them to do, not what you want them to do. Engineers still make plenty of mistakes, even with their training and experience. But non-technical people, attempting to specify a software system to a GenAI model, will almost certainly fail much of the time.</p> <p>So yes, technical chops will still be needed! But just as modern software engineers don&#8217;t think too much about the object code emitted by a compiler, assuming that it&#8217;ll be accurate and useful, future software engineers won&#8217;t need to check the code emitted by AI systems. (We still have some time before that happens, I expect.) The ability to break a problem into small parts, think precisely, and communicate clearly, will be more valuable than ever.</p> <p>Even when AI is writing code for us, we&#8217;ll still need developers. But the best, most successful developers won&#8217;t be the ones who have mastered Python syntax. Rather, they&#8217;ll be the best architects, the clearest communicators, and the most critical thinkers.</p> <h2 class="wp-block-heading">Preparing yourself: We&#8217;re all VCs now</h2> <p>So, how do you prepare for this new world? How can you acquire this VC mindset toward creating software?</p> <p><strong>Learn to code:</strong> You can only use these new AI systems if you have a strong understanding of the underlying technology. AI is like a chainsaw, in that it does wonders for people with experience, but is super dangerous for the untrained. So don&#8217;t believe the hype, that you don&#8217;t need to learn to program, because we&#8217;re now in an age of AI. You still need to learn it. The language doesn&#8217;t matter nearly as much as the underlying concepts. For the time being, you will also need to inspect the code that GenAI produces, and that requires coding knowledge and experience.</p> <p><strong>Communication is key:</strong> You need to learn to communicate clearly. AI uses text, which means that the better you are at articulating your plans and thoughts, the better off you&#8217;ll be. Remember &#8220;Let me Google that for you,&#8221; the snarky way that many techies responded to people who asked for help searching the Web? Well, guess what: Searching on the Internet is a skill that demands some technical understanding. People who can&#8217;t search well aren&#8217;t dumb; they just don&#8217;t have the needed skills. Similarly, working with GenAI is a skill, one that requires far more lengthy, detailed, and precise language than Google searches ever did. Improving your writing skills will make you that much more powerful as a modern developer.</p> <p><strong>High-level problem solving:</strong> An engineering education teaches you (often the hard way) how to break problems apart into small pieces, solve each piece, and then reassemble them. But how do you do that with AI agents? That&#8217;s especially where the VC mindset comes into play: Given a budget, what is the best team of AI agents you can assemble to solve a particular problem? What role will each agent play? What skills will they need? How will they communicate with one another? How do you do so efficiently, so that you don&#8217;t burn all of your tokens in one afternoon?</p> <p><strong>Push back:</strong> When I was little, people would sometimes say that something must be true, because it was in the newspaper. That mutated to: It must be true, because I read it online. Today, people believe that Gemini is AI, so it must be true. Or unbiased. Or smart. But of course, that isn&#8217;t the case; AI tools regularly make mistakes, and you need to be willing to push back, challenge them, and bring counter-examples. Sadly, people don&#8217;t do this enough. I call this &#8220;AI-mposter syndrome,&#8221; when people believe that the AI must be smarter than they are. Just today, while reading up on the Model Context Protocol, Claude gave me completely incorrect information about how it works. Only providing counter-examples got Claude to admit that actually, I was right, and it was wrong. But it would have been very easy for me to say, &#8220;Well, Claude knows better than I do.&#8221; Confidence and skepticism will go a long way in this new world.</p> <p><strong>The more checking, the better:</strong> I&#8217;ve been using Python for a long time, but I&#8217;ve spent no small amount of time with other dynamic languages, such as Ruby, Perl, and Lisp. We&#8217;ve already seen that you can only use Python in serious production environments with good testing, and even more so with type hints. When GenAI is writing your code for you, there&#8217;s zero room for compromise on these fronts. (Heck, if it&#8217;s writing the code, and the tests, then why not go all the way with test-driven development?) If you aren&#8217;t requiring a high degree of safety checks and testing, you&#8217;re asking for trouble — and potentially big trouble. Not everyone will be this serious about code safety. There <em>will</em> be disasters &#8211; code that seemed fine until it wasn&#8217;t, corners that seemed reasonable to cut until they weren&#8217;t. Don&#8217;t let that be you.</p> <p><strong>Learn how to learn:</strong> This has always been true in the computer industry; the faster you can learn new things and synthesize them into your existing knowledge, the better. But the pace has sped up considerably in the last few years. Things are changing at a dizzying pace. It&#8217;s hard to keep up. But you really have no choice but to learn about these new technologies, and how to use them effectively. It has long been common for me to learn about something one month, and then use it in a project the next month. Lately, though, I&#8217;ve been using newly learned ideas just days after coming across them.</p> <h2 class="wp-block-heading">What about juniors?</h2> <p>A big question over the last few years has been: If AI makes senior engineers 100x more productive, then why would companies hire juniors? And if juniors can&#8217;t find work, then how will they gain the experience to make them attractive, AI-powered seniors?</p> <p>This is a real problem. I attended conferences in five countries in 2025, and young engineers in all of them were worried about finding a job, or keeping their current one. There aren&#8217;t any easy answers, especially for people who were looking forward to graduating, joining a company, gradually gaining experience, and finally becoming a senior engineer or hanging out their own shingle.</p> <p>I can say that AI provides an excellent opportunity for learning, and the open-source world offers many opportunities for professional development, as well as interpersonal connections. Perhaps the age in which junior engineers gained their experience on the job are fading, and that participating in open-source projects will need to be part of the university curriculum or something people do in their spare time. And pairing with an AI tool can be extremely rewarding and empowering. Much as Waze doesn&#8217;t scold you for missing a turn, AI systems are extremely polite, and patient when you make a mistake, or need to debug a problem. Learning to work with such tools, alongside working with people, might be a good way for many to improve their skills.</p> <h2 class="wp-block-heading">Standards and licensing</h2> <p>Beyond skill development, AI-written code raises some other issues. For example: Software is one of the few aspects of our lives that has no official licensing requirements. Doctors, nurses, lawyers, and architects, among others, can&#8217;t practice without appropriate education and certification. They&#8217;re often required to take courses throughout their career, and to get re-certified along the way.</p> <p>No doubt, part of the reason for this type of certification is to maintain the power (and profits) of those inside of the system. But it also does help to ensure quality and accountability. As we transition to a world of AI-generated software, part of me wonders whether we&#8217;ll eventually need to feed the AI system a set of government- mandated codes that will ensure user safety and privacy. Or that only certified software engineers will be allowed to write the specifications fed into AI to create software.</p> <p>After all, during most of human history, you could just build a house. There weren&#8217;t any standards or codes you needed to follow. You used your best judgment — and if it fell down one day, then that kinda happened, and what can you do? Nowadays, of course, there are codes that restrict how you can build, and only someone who has been certified and licensed can try to implement those codes.</p> <p>I can easily imagine the pushback that a government would get for trying to impose such restrictions on software people. But as AI-generated code becomes ubiquitous in safety-critical systems, we&#8217;ll need <em>some</em> mechanism for accountability. Whether that&#8217;s licensing, industry standards, or something entirely new remains to be seen.</p> <h2 class="wp-block-heading">Conclusions</h2> <p>The last few weeks have been among the most head-spinning in my 30-year career. I see that my future as a Python trainer isn&#8217;t in danger, but is going to change &#8212; and potentially quite a bit &#8212; even in the coming months and years. I&#8217;m already rolling out workshops in which people solve problems not using Python and Pandas, but using Claude Code to write Python and Pandas on their behalf. It won&#8217;t be enough to learn how to use Claude Code, but it also won&#8217;t be enough to learn Python and Pandas. Both skills will be needed, at least for the time being. But the trend seems clear and unstoppable, and I&#8217;m both excited and nervous to see what comes down the pike.</p> <p>But for now? I&#8217;m doubling down on learning how to use AI systems to write code for me. I&#8217;m learning how to get them to interact, to help one another, and to critique one another. I&#8217;m thinking of myself as a VC, giving &#8220;smart money&#8221; to a bunch of AI agents that have assembled to solve a particular problem.</p> <p>And who knows? In the not-too-distant future, an updated version of my friend&#8217;s statement might look like this:</p> <ul class="wp-block-list"> <li>When you&#8217;re starting off, you solve problems with code.</li> <li>When you get more experienced, you solve problems with an AI agent.</li> <li>When you get even more experienced, you solve problems with teams of AI agents.</li> </ul> <p></p> <p></p> <span class="tve-leads-two-step-trigger tl-2step-trigger-0"></span><span class="tve-leads-two-step-trigger tl-2step-trigger-0"></span><p>The post <a href="https://lerner.co.il/2026/01/21/were-all-vcs-now-the-skills-developers-need-in-the-ai-era/">We&#8217;re all VCs now: The skills developers need in the AI era</a> appeared first on <a href="https://lerner.co.il">Reuven Lerner</a>.</p> Wed, 21 Jan 2026 14:42:24 +0000 Real Python: How to Integrate Local LLMs With Ollama and Python https://realpython.com/ollama-python/ https://realpython.com/ollama-python/ <div><p>Integrating local large language models (LLMs) into your Python projects using Ollama is a great strategy for improving privacy, reducing costs, and building offline-capable AI-powered apps.</p> <p><strong>Ollama</strong> is an open-source platform that makes it straightforward to run modern LLMs locally on your machine. Once you’ve set up Ollama and pulled the models you want to use, you can connect to them from Python using the <code>ollama</code> library.</p> <p>Here’s a quick demo:</p> <div class="embed-responsive embed-responsive-16by9 rounded mb-3 "> </div> <p>In this tutorial, you’ll integrate local LLMs into your Python projects using the Ollama platform and its Python SDK.</p> <p>You’ll first set up Ollama and pull a couple of LLMs. Then, you’ll learn how to use chat, text generation, and tool calling from your Python code. These skills will enable you to build AI-powered apps that run locally, improving privacy and cost efficiency.</p> <div class="alert alert-warning"> <p><strong>Get Your Code:</strong> <a href="https://realpython.com/bonus/ollama-python-code/" class="alert-link">Click here to download the free sample code</a> that you’ll use to integrate LLMs With Ollama and Python.</p> </div> <div class="container border rounded text-wrap-pretty my-3"> <p class="my-3"><strong><span class="icon baseline"></span> Take the Quiz:</strong> Test your knowledge with our interactive “How to Integrate Local LLMs With Ollama and Python” quiz. You’ll receive a score upon completion to help you track your learning progress:</p> <hr /> <div class="row my-3"> <div class="col-xs-12 col-sm-4 col-md-3 align-self-center"> <a href="https://realpython.com/quizzes/ollama-python/" tabindex="-1"> <div class="embed-responsive embed-responsive-16by9"> <img class="card-img-top m-0 p-0 embed-responsive-item rounded" alt="How to Integrate Local LLMs With Ollama and Python" src="https://files.realpython.com/media/How-to-Integrate-Local-LLMs-With-Ollama-and-Python_Watermarked.835ee5f2672d.jpg" width="1920" height="1080" /> <div class="card-img-overlay d-flex align-items-center"> <div class="mx-auto"> <span class="text-light"><span class="icon baseline scale2x"></span></span> </div> </div> </div> </a> </div> <div class="col"> <div class="mt-3 d-md-none"></div> <p class="small text-muted mb-0"><strong>Interactive Quiz</strong></p> <a href="https://realpython.com/quizzes/ollama-python/" class="stretched-link"><span class="my-0 h4">How to Integrate Local LLMs With Ollama and Python</span></a> <p class="text-muted mb-0 small">Check your understanding of using Ollama with Python to run local LLMs, generate text, chat, and call tools for private, offline apps.</p> </div> </div> </div> <h2 id="prerequisites">Prerequisites<a class="headerlink" href="https://realpython.com/atom.xml#prerequisites" title="Permanent link"></a></h2> <p>To work through this tutorial, you’ll need the following resources and setup:</p> <ul> <li><strong>Ollama installed and running</strong>: You’ll need <a href="https://realpython.com/ref/ai-coding-tools/ollama/" class="ref-link">Ollama</a> to use local LLMs. You’ll get to install it and set it up in the next section.</li> <li><strong>Python 3.8 or higher</strong>: You’ll be using Ollama’s Python software development kit (SDK), which requires Python 3.8 or higher. If you haven’t already, <a href="https://realpython.com/installing-python/">install Python</a> on your system to fulfill this requirement.</li> <li><strong>Models to use</strong>: You’ll use <code>llama3.2:latest</code> and <code>codellama:latest</code> in this tutorial. You’ll download them in the next section.</li> <li><strong>Capable hardware</strong>: You need relatively powerful hardware to run Ollama’s models locally, as they may require considerable resources, including memory, disk space, and CPU power. You may not need a GPU for this tutorial, but local models will run much faster if you have one.</li> </ul> <p>With these prerequisites in place, you’re ready to connect local models to your Python code using Ollama. </p> <h2 id="step-1-set-up-ollama-models-and-the-python-sdk">Step 1: Set Up Ollama, Models, and the Python SDK<a class="headerlink" href="https://realpython.com/atom.xml#step-1-set-up-ollama-models-and-the-python-sdk" title="Permanent link"></a></h2> <p>Before you can talk to a local model from Python, you need Ollama running and at least one model downloaded. In this step, you’ll install Ollama, start its background service, and pull the models you’ll use throughout the tutorial.</p> <h3 id="get-ollama-running">Get Ollama Running<a class="headerlink" href="https://realpython.com/atom.xml#get-ollama-running" title="Permanent link"></a></h3> <p>To get started, navigate to Ollama’s <a href="https://ollama.com/download">download page</a> and grab the installer for your current operating system. You’ll find installers for Windows 10 or newer and macOS 14 Sonoma or newer. Run the appropriate installer and follow the on-screen instructions. For Linux users, the installation process differs slightly, as you’ll learn soon.</p> <p>On Windows, Ollama will run in the background after installation, and the CLI will be available for you. If this doesn’t happen automatically for you, then go to the <em>Start</em> menu, search for Ollama, and run the app.</p> <p>On macOS, the app manages the CLI and setup details, so you just need to launch <em>Ollama.app</em>.</p> <p>If you’re on Linux, install Ollama with the following command:</p> <div class="codeblock__header codeblock--yellow"> <span class="mr-2 noselect">Shell</span> <div class="noselect"> <span class="codeblock__output-toggle" title="Toggle prompts and output"><span class="icon baseline js-codeblock-output-on codeblock__header--icon-lower"></span></span> </div> </div> <div class="codeblock__contents"> <div class="highlight highlight--with-header"><pre><span></span><code><span class="gp">$ </span>curl<span class="w"> </span>-fsSL<span class="w"> </span>https://ollama.com/install.sh<span class="w"> </span><span class="p">|</span><span class="w"> </span>sh </code></pre></div> <button class="codeblock__copy btn btn-outline-secondary border m-1 px-1 d-hover-only" title="Copy to clipboard"><span class="icon baseline"></span></button> </div> <p>Once the process is complete, you can verify the installation by running:</p> <div class="codeblock__header codeblock--yellow"> <span class="mr-2 noselect">Shell</span> <div class="noselect"> <span class="codeblock__output-toggle" title="Toggle prompts and output"><span class="icon baseline js-codeblock-output-on codeblock__header--icon-lower"></span></span> </div> </div> <div class="codeblock__contents"> <div class="highlight highlight--with-header"><pre><span></span><code><span class="gp">$ </span>ollama<span class="w"> </span>-v </code></pre></div> <button class="codeblock__copy btn btn-outline-secondary border m-1 px-1 d-hover-only" title="Copy to clipboard"><span class="icon baseline"></span></button> </div> <p>If this command works, then the installation was successful. Next, start Ollama’s service by running the command below:</p> <div class="codeblock__header codeblock--yellow"> <span class="mr-2 noselect">Shell</span> <div class="noselect"> <span class="codeblock__output-toggle" title="Toggle prompts and output"><span class="icon baseline js-codeblock-output-on codeblock__header--icon-lower"></span></span> </div> </div> <div class="codeblock__contents"> <div class="highlight highlight--with-header"><pre><span></span><code><span class="gp">$ </span>ollama<span class="w"> </span>serve </code></pre></div> <button class="codeblock__copy btn btn-outline-secondary border m-1 px-1 d-hover-only" title="Copy to clipboard"><span class="icon baseline"></span></button> </div> <p>That’s it! You’re now ready to start using Ollama on your local machine. In some Linux distributions, such as Ubuntu, this final command may not be necessary, as Ollama may start automatically when the installation is complete. In that case, running the command above will result in an error.</p> </div><h2><a href="https://realpython.com/ollama-python/?utm_source=realpython&utm_medium=rss">Read the full article at https://realpython.com/ollama-python/ »</a></h2> <hr /> <p><em>[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp; sweet Python Trick delivered to your inbox every couple of days. <a href="https://realpython.com/python-tricks/?utm_source=realpython&utm_medium=rss&utm_campaign=footer">&gt;&gt; Click here to learn more and see examples</a> ]</em></p> Wed, 21 Jan 2026 14:00:00 +0000 Real Python: Quiz: How to Integrate Local LLMs With Ollama and Python https://realpython.com/quizzes/ollama-python/ https://realpython.com/quizzes/ollama-python/ <p>In this quiz, you&rsquo;ll test your understanding of <a href="https://realpython.com/ollama-python/">How to Integrate Local LLMs With Ollama and Python</a>.</p> <p>By working through this quiz, you&rsquo;ll revisit how to set up Ollama, pull models, and use chat, text generation, and tool calling from Python.</p> <p>You&rsquo;ll connect to local models through the <code>ollama</code> Python library and practice sending prompts and handling responses. You&rsquo;ll also see how local inference can improve privacy and cost efficiency while keeping your apps offline-capable.</p> <hr /> <p><em>[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp; sweet Python Trick delivered to your inbox every couple of days. <a href="https://realpython.com/python-tricks/?utm_source=realpython&utm_medium=rss&utm_campaign=footer">&gt;&gt; Click here to learn more and see examples</a> ]</em></p> Wed, 21 Jan 2026 12:00:00 +0000 Reuven Lerner: Build YOUR data dashboard — join my next 8-week HOPPy studio cohort https://lerner.co.il/2026/01/21/build-your-data-dashboard-join-my-next-8-week-hoppy-studio-cohort/ https://lerner.co.il/2026/01/21/build-your-data-dashboard-join-my-next-8-week-hoppy-studio-cohort/ <div class="wp-block-image"> <img width="1024" height="1024" src="https://lerner.co.il/wp-content/uploads/2026/01/hoppy-logo-1024x1024.jpg" alt="" class="wp-image-4600" /></div> <p>Want to analyze data? Good news: Python is the leading language in the data world. Libraries like NumPy and Pandas make it easy to load, clean, analyze, and visualize your data.</p> <p>But wait: If your colleagues aren&#8217;t coders, how can they explore your data?</p> <p>The answer: A <em>data dashboard</em>, which uses UI elements (e.g., sliders, text fields, and checkboxes). Your colleagues get a custom, dynamic app, rather than static graphs, charts, and tables.</p> <p>One of the newest and hottest ways to create a data dashboard in Python is <a href="https://marimo.io" target="_blank" rel="noreferrer noopener">Marimo</a>. Among other things, Marimo offers UI widgets, real-time updating, and easy distribution. This makes it a great choice for creating a data dashboard.</p> <p>In the upcoming (4th) cohort of HOPPy (Hands-On Projects in Python), you&#8217;ll learn to create a data dashboard. You&#8217;ll make all of the important decisions, from the data set to the design. But you&#8217;ll do it all under my personal mentorship, along with a small community of other learners.</p> <p>The course starts on Sunday, February 1st, and will meet every Sunday for eight weeks. When you&#8217;re done, you&#8217;ll have a dashboard you can share with colleagues, or just add to your personal portfolio.</p> <p>If you&#8217;ve taken Python courses, but want to sink your teeth into a real-world project, then HOPPy is for you. Among other things:</p> <ul class="wp-block-list"> <li><strong>Go beyond classroom learning:</strong> You&#8217;ll learn by doing, creating your own personal product</li> <li><strong>Live instruction</strong>: Our cohort will meet, live, for two hours every Sunday to discuss problems you&#8217;ve had and provide feedback.</li> <li><strong>You decide what to do</strong>: This isn&#8217;t a class in which the instructor dictates what you&#8217;ll create. You can choose whatever data set you want. But I&#8217;ll be there to support and advise you every step of the way.</li> <li><strong>Learn about Marimo</strong>: Get experience with one of the hottest new Python technologies.</li> <li><strong>Learn about modern distribution</strong>:  Use Molab and WASM to share your dashboard with others</li> </ul> <p><strong>Want to learn more</strong>? Join me for an info session on Monday, January 26th. You can register here: <a href="https://us02web.zoom.us/webinar/register/WN_YbmUmMSgT2yuOqfg8KXF5A?__s=xxxxxxx" target="_blank" rel="noreferrer noopener">https://us02web.zoom.us/webinar/register/</a><a href="https://us02web.zoom.us/webinar/register/WN_YbmUmMSgT2yuOqfg8KXF5A" target="_blank" rel="noreferrer noopener">WN_YbmUmMSgT2yuOqfg8KXF5A</a></p> <p><strong>Ready to join right now</strong>? Get full details, and sign up, at <a href="https://lernerpython.com/hoppy-4?__s=xxxxxxx" target="_blank" rel="noreferrer noopener">https://</a><a href="https://lernerpython.com/hoppy-4" target="_blank" rel="noreferrer noopener">lernerpython</a><a href="https://lernerpython.com/hoppy-4?__s=xxxxxxx" target="_blank" rel="noreferrer noopener">.com/hoppy-4</a>. </p> <p><strong>Questions</strong>? Just reply to this e-mail. It&#8217;ll go straight to my inbox, and I&#8217;ll answer you as quickly as I can.</p> <p>I look forward to seeing you in HOPPy 4!</p> <p></p> <span class="tve-leads-two-step-trigger tl-2step-trigger-0"></span><span class="tve-leads-two-step-trigger tl-2step-trigger-0"></span><p>The post <a href="https://lerner.co.il/2026/01/21/build-your-data-dashboard-join-my-next-8-week-hoppy-studio-cohort/">Build YOUR data dashboard — join my next 8-week HOPPy studio cohort</a> appeared first on <a href="https://lerner.co.il">Reuven Lerner</a>.</p> Wed, 21 Jan 2026 06:57:22 +0000 Seth Michael Larson: mGBA → Dolphin not working? You need a GBA BIOS https://sethmlarson.dev/mgba-to-dolphin-not-working-you-need-a-gba-bios?utm_campaign=rss https://sethmlarson.dev/mgba-to-dolphin-not-working-you-need-a-gba-bios?utm_campaign=rss <p>The GBA emulator “<a href="https://mgba.io/">mGBA</a>” supports emulating the <a href="https://en.wikipedia.org/wiki/GameCube_%E2%80%93_Game_Boy_Advance_link_cable">Game Boy Advance Link Cable</a> (not to be confused with the <a href="https://en.wikipedia.org/wiki/Game_Link_Cable#Third_generation">Game Boy Advance /<em>Game</em>/ Link Cable</a>) and connecting to a running <a href="https://dolphin-emu.org">Dolphin emulator</a> instance. I am interested in this functionality for <a href="https://en.wikipedia.org/wiki/The_Legend_of_Zelda:_Four_Swords_Adventures">Legend of Zelda: Four Swords Adventures</a>, specifically the “<a href="https://en.wikipedia.org/wiki/The_Legend_of_Zelda:_Four_Swords_Adventures#Navi_Trackers">Navi Trackers</a>” game mode that was announced for all regions but was only released in Japan and Korea. In the future I want to explore the <a href="https://forums.dolphin-emu.org/Thread-tetra-s-trackers-navi-tracker-translation-02-05-2023">English</a> <a href="https://www.patreon.com/posts/zelda-four-beta-60032999">language</a> patches.</p> <!-- more --> <p>After <a href="https://dolphin-emu.org/blog/2021/04/24/mgba-and-dolphin-connectivity/">reading the documentation</a> to connect the two emulators I configured the controllers to be “GBA (TCP)” in Dolphin and ensured that Dolphin had the permissions it needed to do networking (Dolphin is installed as a Flatpak). I selected “Connect” on mGBA from the “Connect to Dolphin” popup screen and there was zero feedback... no UI changes, errors, or success messages. Hmmm...</p> <p>I found out in a random Reddit comment section that a GBA BIOS was needed to connect to Dolphin, so I set off to legally obtain the BIOSes from my hardware. I opted to use the <a href="https://github.com/mgba-emu/bios-dump">BIOS-dump ROM</a> developed by the mGBA team to dump the BIOS from my Game Boy Advance SP and DS Lite.</p> <p>Below is a guide on how to <a href="https://github.com/mgba-emu/bios-dump">build the BIOS ROM from source</a> on Ubuntu 24.04, and then dump GBA BIOSes. Please note you'll likely need a GBA flash cartridge for running homebrew on your Game Boy Advance. I used an EZ-Flash Omega flash cartridge, but I've heard Everdrive GBA is also popular.</p> <h2>Installing devKitARM on Ubuntu 24.04</h2> <p>To build this ROM from source you'll need <a href="https://devkitpro.org/wiki/Getting_Started">devKitARM</a>. If you already have devKitARM installed you can skip these steps. The devKitPro team supplies an <a href="https://apt.devkitpro.org/install-devkitpro-pacman">easy script</a> for installing devKitPro toolsets, but unfortunately the <code>apt.devkitpro.org</code> domain appears to be behind an aggressive “bot” filter right now so their instructions to use <code>wget</code> are not working as written.</p> <p>Instead, download <a href="https://apt.devkitpro.org/devkitpro-pub.gpg">their GPG key</a> with a browser and then run the commands yourself:</p> <div class="codehilite"> <pre><span></span><code>apt-get install apt-transport-https <span class="k">if</span> ! <span class="o">[</span> -f /usr/local/share/keyring/devkitpro-pub.gpg <span class="o">]</span><span class="p">;</span> <span class="k">then</span> mkdir -p /usr/local/share/keyring/ mv devkitpro-pub.gpg /usr/local/share/keyring/ <span class="k">fi</span> <span class="k">if</span> ! <span class="o">[</span> -f /etc/apt/sources.list.d/devkitpro.list <span class="o">]</span><span class="p">;</span> <span class="k">then</span> <span class="nb">echo</span> <span class="s2">&quot;deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main&quot;</span> &gt; /etc/apt/sources.list.d/devkitpro.list <span class="k">fi</span> apt-get update apt-get install devkitpro-pacman </code></pre> </div> <p>Once you've installed devKitPro pacman (for Ubuntu: <code>dkp-pacman</code>) you can install the GBA development tools package group:</p> <div class="codehilite"> <pre><span></span><code>dkp-pacman -S gba-dev </code></pre> </div> <p>After this you can set the <code>DEVKITARM</code> environment variable within your shell profile to <code>/opt/devkitpro/devkitARM</code>. Now you should be ready to build the GBA BIOS dumping ROM.</p> <h2>Building the bios-dump ROM</h2> <p>Once devKitARM toolkit is installed the next step is much easier. You basically download the source, run <code>make</code> with the <code>DEVKITARM</code> environment variable set properly, and if all the tools are installed you'll quickly have your ROM:</p> <div class="codehilite"> <pre><span></span><code>apt-get install build-essential curl unzip curl -L -o bios-dump.zip <span class="se">\</span> https://github.com/mgba-emu/bios-dump/archive/refs/heads/master.zip unzip bios-dump.zip <span class="nb">cd</span> bios-dump-master <span class="nb">export</span> <span class="nv">DEVKITARM</span><span class="o">=</span>/opt/devkitpro/devkitARM/ make </code></pre> </div> <p>You should end up with a GBA ROM file titled <code>bios-dump.gba</code>. Add this <code>.gba</code> file to your microSD card for the flash cartridge. Boot up the flash cartridge using the device you are trying to dump BIOS of and after boot-up the screen should quickly show a success message along with checksums of the BIOS file. As noted in the mGBA bios-dump README, there are two GBA BIOSes:</p> <ul> <li><code>sha256:fd2547</code>: GBA, GBA SP, GBA SP “AGS-101”, GBA Micro, and Game Boy Player.</li> <li><code>sha256:782eb3</code>: DS, DS Lite, and all 3DS variants</li> </ul> <p>I own a GBA SP, a Game Boy Player, and a DS Lite, so I was able to dump three different GBA BIOSes, two of which are identical:</p> <div class="codehilite"> <pre><span></span><code>sha256sum *.bin fd2547... gba_sp_bios.bin fd2547... gba_gbp_bios.bin 782eb3... gba_ds_bios.bin </code></pre> </div> <p>From here I was able to configure mGBA with a GBA BIOS file (Tools→Settings→BIOS) and successfully connect to Dolphin running four instances of mGBA; one for each of the Links!</p> <div class="row"> <div class="col-8"> <p><img src="https://storage.googleapis.com/sethmlarson-dev-static-assets/G4SE01_2026-01-17_17-11-00.png" /></p> </div> <div class="col-4"> <p><img src="https://storage.googleapis.com/sethmlarson-dev-static-assets/gba_bios-0.png" /></p> <p>💚❤️💙💜</p> <p>mGBA probably could have shown an error message when the “connecting” phase requires a BIOS. Looks like this behavior been known <a href="https://github.com/mgba-emu/mgba/issues/2210">since 2021</a>.</p> </div> </div> <br /><hr /><p>Thanks for keeping RSS alive! ♥</p> Wed, 21 Jan 2026 00:00:00 +0000 PyCoder’s Weekly: Issue #718: pandas 3.0, deque, tprof, and More (Jan. 20, 2026) https://pycoders.com/issues/718 https://pycoders.com/issues/718 <p> <span>#718 – JANUARY 20, 2026</span><br /> <span><a href="https://pycoders.com/issues/718/feed">View in Browser »</a></span> </p> <p><a href="https://pycoders.com"><img alt="The PyCoder&rsquo;s Weekly Logo" src="https://cdn.pycoders.com/37bdf31dc645f968ffb90196e5d38ff5" /></a></p> <hr /> <div> <h3><a href="https://pycoders.com/link/15879/feed" target="_blank">What&rsquo;s New in pandas 3.0</a></h3> <p> Learn what&rsquo;s new in pandas 3.0: <code>pd.col</code> expressions for cleaner code, Copy-on-Write for predictable behavior, and PyArrow-backed strings for 5-10x faster operations.<br /> <span><a href="https://pycoders.com/link/15879/feed" target="_blank">CODECUT.AI</a> • Shared by <a href="https://pycoders.com/link/15875/feed" target="_blank">Khuyen Tran</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15863/feed" target="_blank">Python&rsquo;s <code>deque</code>: Implement Efficient Queues and Stacks</a></h3> <p> Use a Python <code>deque</code> to efficiently append and pop elements from both ends of a sequence, build queues and stacks, and set <code>maxlen</code> for history buffers.<br /> <span><a href="https://pycoders.com/link/15863/feed" target="_blank">REAL PYTHON</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15848/feed" target="_blank">B2B Authentication for any Situation - Fully Managed or BYO</a></h3> <a href="https://pycoders.com/link/15848/feed" target="_blank"><img src="https://cdn.pycoders.com/ba733fdaad1bc21b72eb28c2bc6d79f6" alt="alt" /></a> <p> What your sales team needs to close deals: multi-tenancy, SAML, SSO, SCIM provisioning, passkeys…What you’d rather be doing: almost anything else. <a href="https://pycoders.com/link/15848/feed" target="_blank">PropelAuth does it all for you, at every stage. →</a><br /> <span><a href="https://pycoders.com/link/15848/feed" target="_blank">PROPELAUTH</a></span> <span>sponsor</span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15868/feed" target="_blank">Introducing <code>tprof</code>, a Targeting Profiler</a></h3> <p> Adam has written <code>tprof</code> a targeting profiler for Python 3.12+. This article introduces you to the tool and why he wrote it.<br /> <span><a href="https://pycoders.com/link/15868/feed" target="_blank">ADAM JOHNSON</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15866/feed" target="_blank">Python 3.15.0 Alpha 4 Released</a></h3> <p> <span><a href="https://pycoders.com/link/15866/feed" target="_blank">CPYTHON DEV BLOG</a></span> </p> </div> <h2>Articles &amp; Tutorials</h2> <div> <h3><a href="https://pycoders.com/link/15869/feed" target="_blank">Anthropic Invests $1.5M in the PSF</a></h3> <p> Anthropic has entered a two-year partnership with the PSF, contributing $1.5 million. The investment will focus on Python ecosystem security including advances to CPython and PyPI.<br /> <span><a href="https://pycoders.com/link/15869/feed" target="_blank">PYTHON SOFTWARE FOUNDATION</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15874/feed" target="_blank">The Coolest Feature in Python 3.14</a></h3> <p> Svaannah has written a debugging tool called <code>debugwand</code> that help access Python applications running in Kubernetes and Docker containers using Python 3.14&rsquo;s <code>sys.remote_exec()</code> function.<br /> <span><a href="https://pycoders.com/link/15874/feed" target="_blank">SAVANNAH OSTROWSKI</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15847/feed" target="_blank">AI Code Review with Comments You&rsquo;ll Actually Implement</a></h3> <a href="https://pycoders.com/link/15847/feed" target="_blank"><img src="https://cdn.pycoders.com/3a1b5af9b49ad7e71c6d87a0658b1b04" alt="alt" /></a> <p> Unblocked is the AI code review that surfaces real issues and meaningful feedback instead of flooding your PRs with stylistic nitpicks and low-value comments. <a href="https://pycoders.com/link/15847/feed" target="_blank">“Finally, a tool that surfaces context only someone with a full view of the codebase could provide.” - Senior developer, Clio →</a><br /> <span><a href="https://pycoders.com/link/15847/feed" target="_blank">UNBLOCKED</a></span> <span>sponsor</span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15859/feed" target="_blank">Avoiding Duplicate Objects in Django Querysets</a></h3> <p> When filtering Django querysets across relationships, you can easily end up with duplicate objects in your results. Learn why this happens and the best ways to avoid it.<br /> <span><a href="https://pycoders.com/link/15859/feed" target="_blank">JOHNNY METZ</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15854/feed" target="_blank"><code>diskcache</code>: Your Secret Python Perf Weapon</a></h3> <p> Talk Python interviews Vincent Warmerdam and they discuss DiskCache, an SQLite-based caching mechanism that doesn&rsquo;t require you to spin up extra services like Redis.<br /> <span><a href="https://pycoders.com/link/15854/feed" target="_blank">TALK PYTHON</a></span> <span>podcast</span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15853/feed" target="_blank">How to Create a Django Project</a></h3> <p> Learn how to create a Django project and app in clear, guided steps. Use it as a reference for any future Django project and tutorial you&rsquo;ll work on.<br /> <span><a href="https://pycoders.com/link/15853/feed" target="_blank">REAL PYTHON</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15882/feed" target="_blank">Get Job-Ready With Live Python Training</a></h3> <p> Real Python&rsquo;s 2026 cohorts are open. <a href="https://pycoders.com/link/15881/feed" target="_blank">Python for Beginners</a> teaches fundamentals the way professional developers actually use them. <a href="https://pycoders.com/link/15880/feed" target="_blank">Intermediate Python Deep Dive</a> goes deeper into decorators, clean OOP, and Python&rsquo;s object model. Live instruction, real projects, expert feedback. Learn more at <a href="https://pycoders.com/link/15882/feed" target="_blank">realpython.com/live →</a><br /> <span><a href="https://pycoders.com/link/15882/feed" target="_blank">REAL PYTHON</a></span> <span>sponsor</span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15873/feed" target="_blank">Quiz: How to Create a Django Project</a></h3> <p> <span><a href="https://pycoders.com/link/15873/feed" target="_blank">REAL PYTHON</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15855/feed" target="_blank">Intro to Object-Oriented Programming (OOP) in Python</a></h3> <p> Learn Python OOP fundamentals fast: master classes, objects, and constructors with hands-on lessons in this beginner-friendly video course.<br /> <span><a href="https://pycoders.com/link/15855/feed" target="_blank">REAL PYTHON</a></span> <span>course</span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15867/feed" target="_blank">Fun With Mypy: Reifying Runtime Relations on Types</a></h3> <p> This post describes how to implement a safer version of <code>typing.cast</code> which guarantees a cast type is also an appropriate sub-type.<br /> <span><a href="https://pycoders.com/link/15867/feed" target="_blank">LANGSTON BARRETT</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15861/feed" target="_blank">How to Type Hint a Decorator in Python</a></h3> <p> Writing a decorator itself can be a little tricky, but adding type hints makes it a little harder. This article shows you how.<br /> <span><a href="https://pycoders.com/link/15861/feed" target="_blank">MIKE DRISCOLL</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15851/feed" target="_blank">How to Integrate ChatGPT&rsquo;s API With Python Projects</a></h3> <p> Learn how to use the ChatGPT Python API with the openai library to build AI-powered features in your Python applications.<br /> <span><a href="https://pycoders.com/link/15851/feed" target="_blank">REAL PYTHON</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15877/feed" target="_blank">Quiz: How to Integrate ChatGPT&rsquo;s API With Python Projects</a></h3> <p> <span><a href="https://pycoders.com/link/15877/feed" target="_blank">REAL PYTHON</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15849/feed" target="_blank">Raw String Literals in Python</a></h3> <p> Exploring the pitfalls of raw string literals in Python and why backslash can still escape some things in raw mode.<br /> <span><a href="https://pycoders.com/link/15849/feed" target="_blank">SUBSTACK.COM</a> • Shared by <a href="https://pycoders.com/link/15850/feed" target="_blank">Vivis Dev</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15856/feed" target="_blank">Need a Constant in Python? Enums Can Come in Useful</a></h3> <p> Python doesn’t have constants, but it does have <code>enums</code>. Learn when you might want to use them in your code.<br /> <span><a href="https://pycoders.com/link/15856/feed" target="_blank">STEPHEN GRUPPETTA</a></span> </p> </div> <h2>Projects &amp; Code</h2> <div> <h3><a href="https://pycoders.com/link/15872/feed" target="_blank">usqlite: μSQLite Library Module for MicroPython</a></h3> <p> <span><a href="https://pycoders.com/link/15872/feed" target="_blank">GITHUB.COM/SPATIALDUDE</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15876/feed" target="_blank">transtractor-lib: PDF Bank Statement Extraction</a></h3> <p> <span><a href="https://pycoders.com/link/15876/feed" target="_blank">GITHUB.COM/TRANSTRACTOR</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15857/feed" target="_blank">sharepoint-to-text: Sharepoint to Text</a></h3> <p> <span><a href="https://pycoders.com/link/15857/feed" target="_blank">GITHUB.COM/HORSMANN</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15865/feed" target="_blank">graphqlite: Graph Database SQLite Extension</a></h3> <p> <span><a href="https://pycoders.com/link/15865/feed" target="_blank">GITHUB.COM/COLLIERY-IO</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15864/feed" target="_blank">chanx: WebSocket Framework for Django Channels, FastAPI, and ASGI-based Applications</a></h3> <p> <span><a href="https://pycoders.com/link/15864/feed" target="_blank">GITHUB.COM/HUYNGUYENGL99</a></span> </p> </div> <h2>Events</h2> <div> <h3><a href="https://pycoders.com/link/15862/feed" target="_blank">Weekly Real Python Office Hours Q&amp;A (Virtual)</a></h3> <p> January 21, 2026<br /> <span><a href="https://pycoders.com/link/15862/feed" target="_blank">REALPYTHON.COM</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15858/feed" target="_blank">Python Leiden User Group</a></h3> <p> January 22, 2026<br /> <span><a href="https://pycoders.com/link/15858/feed" target="_blank">PYTHONLEIDEN.NL</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15870/feed" target="_blank">PyDelhi User Group Meetup</a></h3> <p> January 24, 2026<br /> <span><a href="https://pycoders.com/link/15870/feed" target="_blank">MEETUP.COM</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15878/feed" target="_blank">PyLadies Amsterdam: Robotics Beginner Class With MicroPython</a></h3> <p> January 27, 2026<br /> <span><a href="https://pycoders.com/link/15878/feed" target="_blank">MEETUP.COM</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15860/feed" target="_blank">Python Sheffield</a></h3> <p> January 27, 2026<br /> <span><a href="https://pycoders.com/link/15860/feed" target="_blank">GOOGLE.COM</a></span> </p> </div> <div> <h3><a href="https://pycoders.com/link/15871/feed" target="_blank">Python Southwest Florida (PySWFL)</a></h3> <p> January 28, 2026<br /> <span><a href="https://pycoders.com/link/15871/feed" target="_blank">MEETUP.COM</a></span> </p> </div> <hr /> <p>Happy Pythoning!<br />This was PyCoder&rsquo;s Weekly Issue #718.<br /><a href="https://pycoders.com/issues/718/feed">View in Browser »</a></p> <img src="https://pycoders.com/issues/718/open/feed" width="1" height="1" alt="alt" /> <hr /> <p><em>[ Subscribe to 🐍 PyCoder&rsquo;s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week <a href="https://pycoders.com/?utm_source=pycoders&utm_medium=feed&utm_campaign=footer">&gt;&gt; Click here to learn more</a> ]</em></p> Tue, 20 Jan 2026 19:30:00 +0000 Real Python: uv vs pip: Python Packaging and Dependency Management https://realpython.com/courses/uv-vs-pip-packaging-dependency-management/ https://realpython.com/courses/uv-vs-pip-packaging-dependency-management/ <p>When it comes to Python package managers, the choice often comes down to <code>uv</code> vs <code>pip</code>. You may choose <code>pip</code> for out-of-the-box availability, broad compatibility, and reliable ecosystem support. In contrast, <code>uv</code> is worth considering if you prioritize fast installs, reproducible environments, and clean uninstall behavior, or if you want to streamline workflows for new projects.</p> <p>In this video course, you&rsquo;ll compare both tools. To keep this comparison meaningful, you&rsquo;ll focus on the overlapping features, primarily <em>package installation</em> and <em>dependency management</em>.</p> <hr /> <p><em>[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp; sweet Python Trick delivered to your inbox every couple of days. <a href="https://realpython.com/python-tricks/?utm_source=realpython&utm_medium=rss&utm_campaign=footer">&gt;&gt; Click here to learn more and see examples</a> ]</em></p> Tue, 20 Jan 2026 14:00:00 +0000 PyCharm <img src="https://blog.jetbrains.com/wp-content/uploads/2025/09/PC-social-BlogFeatured-1280x720-2x-8.png" alt="Why Is Python So Popular in 2025?" class="wp-image-644404" /> <p>While other programming languages come and go, Python has stood the test of time and firmly established itself as a top choice for developers of all levels, from beginners to seasoned professionals.</p> <p>Whether you’re working on intelligent systems or data-driven workflows, Python has a pivotal role to play in how your software is built, scaled, and optimized.</p> <p>Many surveys, including our <a href="https://devecosystem-2025.jetbrains.com/" target="_blank" rel="noopener">Developer Ecosystem Survey 2025</a>, confirm Python’s continued popularity. The real question is why developers keep choosing it, and that’s what we’ll explore. </p> <p>Whether you’re choosing your first language or building production-scale services, this post will walk you through why Python remains a top choice for developers.</p> <h2 class="wp-block-heading">How popular is Python in 2025?</h2> <p>In our <a href="https://devecosystem-2025.jetbrains.com/" target="_blank" rel="noopener">Developer Ecosystem Survey 2025</a>, Python ranks as the second most-used programming language in the last 12 months, with 57% of developers reporting that they use it.</p> <p>More than a third (34%) said Python is their primary programming language. This places it ahead of JavaScript, Java, and TypeScript in terms of primary use. It’s also performing well despite fierce competition from newer systems and niche domain tools.</p> <p>These stats tell a story of sustained relevance across diverse developer segments, from seasoned backend engineers to first-time data analysts.</p> <p>This continued success is down to Python&#8217;s ability to grow with you. It doesn’t just serve as a first step; it continues adding value in advanced environments as you gain skills and experience throughout your career.</p> <p>Let’s explore why Python remains a popular choice in 2025.</p> <h2 class="wp-block-heading">1. Dominance in AI and machine learning</h2> <p>Our recently released report, <a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/"><em>The State of Python 2025</em></a>, shows that 41% of Python developers use the language specifically for machine learning.</p> <p>This is because Python drives innovation in areas like natural language processing, computer vision, and recommendation systems.</p> <p>Python’s strength in this area comes from the fact that it offers support at every stage of the process, from prototyping to production. It also integrates into machine learning operations (MLOps) pipelines with minimal friction and high flexibility.</p> <p>One of the most significant reasons for Python’s popularity is its syntax, which is expressive, readable, and dynamic. This allows developers to write training loops, manipulate tensors, and orchestrate workflows without boilerplate friction.&nbsp;</p> <p>However, it’s Python’s ecosystem that makes it indispensable.</p> <p>Core frameworks include:</p> <ul> <li>PyTorch – for research-oriented deep learning</li> </ul> <ul> <li>TensorFlow – for production deployment and scalability</li> <li>Keras – for rapid prototyping</li> <li>scikit-learn – for classical machine learning</li> <li><a href="https://blog.jetbrains.com/pycharm/2024/11/hugging-face-integration/">Hugging Face</a> Transformers – for natural language processing and generative models</li> </ul> <p>These frameworks are mature, well-documented, and interoperable, benefitting from rapid open-source development and extensive community contributions. They support everything from GPU acceleration and distributed training to model export and quantization.</p> <p>Python also integrates cleanly across the machine learning (ML) pipeline, from data preprocessing with <a href="https://blog.jetbrains.com/pycharm/2024/10/data-exploration-with-pandas/">pandas</a> and NumPy to model serving via <a href="https://blog.jetbrains.com/pycharm/2024/09/how-to-use-fastapi-for-machine-learning/">FastAPI</a> or <a href="https://blog.jetbrains.com/pycharm/2022/08/flask-tutorial/">Flask</a> to inference serving for LLMs with <a href="https://github.com/vllm-project/vllm" target="_blank" rel="noopener">vLLM</a>.</p> <p>It all comes together to provide a solution that allows you to deliver a working AI solution without ever really having to work outside Python.</p> <h2 class="wp-block-heading">2. Strength in data science and analytics</h2> <p>From analytics dashboards to ETL scripts, Python’s flexibility drives fast, interpretable insights across industries. It&#8217;s particularly adept at handling complex data, such as time-series analyses.&nbsp;</p> <p><a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/"><em>The State of Python 2025</em></a> reveals that 51% of respondents are involved in data exploration and processing. This includes tasks like:</p> <ul> <li>Data extraction, transformation, and loading (ETL)</li> <li>Exploratory data analysis (EDA)</li> <li>Statistical and predictive modeling</li> <li>Visualization and reporting</li> <li>Real-time data analysis</li> <li>Communication of insights</li> </ul> <p>Core libraries such as pandas, NumPy, Matplotlib, Plotly, and Jupyter Notebook form a mature ecosystem that’s supported by strong documentation and active community development.</p> <p>Python offers a unique balance. It’s accessible enough for non-engineers, but powerful enough for production-grade pipelines. It also integrates with cloud platforms, supports multiple data formats, and works seamlessly with SQL and NoSQL data stores.</p> <h2 class="wp-block-heading">3. Syntax that’s simple and scalable</h2> <p>Python’s most visible strength remains its readability. Developers routinely cite Python’s low barrier to entry and clean syntax as reasons for initial adoption and longer-term loyalty. In Python, even model training syntax reads like plain English:</p> <pre class="EnlighterJSRAW">def train(model): for item in model.data: model.learn(item)</pre> <p>Code snippets like this require no special decoding. That clarity isn’t just beginner-friendly; it also lowers maintenance costs, shortens onboarding time, and improves communication across mixed-skill teams.</p> <p>This readability brings practical advantages. Teams spend less time deciphering logic and more time improving functionality. Bugs surface faster. Reviews run more smoothly. And non-developers can often read Python scripts without assistance.</p> <p><a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/"><em>The State of Python 2025</em></a> revealed that 50% of respondents had less than two years of total coding experience. Over a third (39%) had been coding in Python for two years or less, even in hobbyist or educational settings.</p> <p>This is where Python really stands out. Though its simple syntax makes it an ideal entry point for new coders, it scales with users, which means retention rates remain high. As projects grow in complexity, Python’s simplicity becomes a strength, not a limitation.</p> <p>Add to this the fact that Python supports multiple programming paradigms (procedural, object-oriented, and functional), and it becomes clear why readability is important. It’s what enables developers to move between approaches without friction.</p> <h2 class="wp-block-heading">4. A mature and versatile ecosystem</h2> <p>Python’s power lies in its vast network of libraries that span nearly every domain of modern software development.</p> <p>Our survey shows that developers rely on Python for everything from web applications and API integration to data science, automation, and testing.&nbsp;</p> <p>Its deep, actively maintained toolset means you can use Python at all stages of production.</p> <p>Here’s a snapshot of Python’s core domains and the main libraries developers reach for:</p> <table><tbody><tr><td><strong>Domain</strong></td><td><strong>Popular Libraries</strong></td></tr><tr><td>Web development</td><td>Django, Flask, FastAPI</td></tr><tr><td>AI and ML</td><td>TensorFlow, PyTorch, scikit-learn, Keras</td></tr><tr><td>Testing</td><td>pytest, unittest, Hypothesis</td></tr><tr><td>Automation</td><td>Click, APScheduler, Rich</td></tr><tr><td>Data science</td><td>pandas, NumPy, Plotly, Matplotlib</td></tr></tbody></table> <p>This breadth translates to real-world agility. Developers can move between back-end APIs and machine learning pipelines without changing language or tooling. They can prototype with high-level wrappers and drop to lower-level control when needed.</p> <p>Critically, Python’s packaging and dependency management systems like pip, conda, and poetry support modular development and reproducible environments. Combined with frameworks like FastAPI for APIs, pytest for testing, and pandas for data handling, Python offers unrivaled scalability.</p> <h2 class="wp-block-heading">5. Community support and shared knowledge</h2> <p>Python’s enduring popularity owes much to its global, engaged developer community.</p> <p>From individual learners to enterprise teams, Python users benefit from open forums, high-quality tutorials, and a strong culture of mentorship. The community isn&#8217;t just helpful, it’s fast-moving and inclusive, fostering a welcoming environment for developers of all levels.</p> <p>Key pillars include:</p> <ul> <li>The <a href="https://www.python.org/psf-landing/" target="_blank" rel="noopener">Python Software Foundation</a>, which supports education, events, and outreach.</li> <li>High activity on <a href="https://stackoverflow.com/questions/tagged/python" target="_blank" rel="noopener">Stack Overflow</a>, ensuring quick answers to real-world problems, and active participation in open-source projects and local user groups.</li> <li>A rich landscape of resources (<a href="https://realpython.com/" target="_blank" rel="noopener"><em>Real Python</em></a>, <a href="https://talkpython.fm/" target="_blank" rel="noopener"><em>Talk Python</em></a>, and <a href="https://pycon.org/" target="_blank" rel="noopener">PyCon</a>), serving both beginners and professionals.</li> </ul> <p>This network doesn’t just solve problems; it also shapes the language’s evolution. Python’s ecosystem is sustained by collaboration, continual refinement, and shared best practices.</p> <p>When you choose Python, you tap into a knowledge base that grows with the language and with you over time.</p> <h2 class="wp-block-heading">6. Cross-domain versatility</h2> <p>Python’s reach is not limited to AI and ML or data science and analytics. It’s equally at home in automation, scripting, web APIs, data workflows, and systems engineering. Its ability to move seamlessly across platforms, domains, and deployment targets makes it the default language for multipurpose development.</p> <p><a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/"><em>The State of Python 2025</em></a> shows just how broadly developers rely on Python:</p> <table><tbody><tr><td><strong>Functionality</strong></td><td><strong>Percentage of Python users</strong></td></tr><tr><td>Data analysis</td><td>48%</td></tr><tr><td>Web development</td><td>46%</td></tr><tr><td>Machine learning</td><td>41%</td></tr><tr><td>Data engineering</td><td>31%</td></tr><tr><td>Academic research</td><td>27%</td></tr><tr><td>DevOps and systems administration</td><td>26%</td></tr></tbody></table> <p>That spread illustrates Python’s domain elasticity. The same language that powers model training can also automate payroll tasks, control scientific instruments, or serve REST endpoints. Developers can consolidate tools, reduce context-switching, and streamline team workflows.</p> <p>Python’s platform independence (Windows, Linux, macOS, cloud, and browser) reinforces this versatility. Add in a robust packaging ecosystem and consistent cross-library standards, and the result is a language equally suited to both rapid prototyping and enterprise production.</p> <p>Few languages match Python’s reach, and fewer still offer such seamless continuity. From frontend interfaces to backend logic, Python gives developers one cohesive environment to build and ship full solutions.</p> <p>That completeness is part of the reason people stick with it. Once you&#8217;re in, you rarely need to reach for anything else.</p> <h2 class="wp-block-heading">Python in the age of intelligent development</h2> <p>As software becomes more adaptive, predictive, and intelligent, Python is strongly positioned to retain its popularity.&nbsp;</p> <p>Its abilities in areas like AI, ML, and data handling, as well as its mature libraries, make it a strong choice for systems that evolve over time.</p> <p>Python’s popularity comes from its ability to easily scale across your projects and platforms. It continues to be a great choice for developers of all experience levels and across projects of all sizes, from casual automation scripts to enterprise AI platforms.</p> <p>And when working with PyCharm, Python is an intelligent, fast, and clean option.</p> <p>For a deeper dive, check out <a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/"><em>The State of Python 2025</em></a> by Michael Kennedy, Python expert and host of the <a href="https://talkpython.fm/" target="_blank" rel="noopener"><em>Talk Python to Me</em></a> podcast.&nbsp;</p> <p>Michael analyzed over 30,000 responses from our <a href="https://lp.jetbrains.com/python-developers-survey-2024/" target="_blank" rel="noopener">Python Developers Survey 2024</a>, uncovering fascinating insights and identifying the latest trends.</p> <p>Whether you’re a beginner or seasoned developer,<strong> </strong><a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/"><em>The State of Python 2025</em></a> will give you the inside track on where the language is now and where it’s headed.&nbsp;</p> <p>As tools like <a href="https://github.com/vllm-project/vllm" target="_blank" rel="noopener">Astral’s uv</a> show, Python’s evolution is far from over, despite its relative maturity. With a growing ecosystem and proven staying power, it’s well-positioned to remain a popular choice for developers for years to come.</p> Tue, 20 Jan 2026 13:40:46 +0000 PyCharm <p>Whether you&#8217;re building APIs, dashboards, or <a href="https://blog.jetbrains.com/pycharm/tag/machine-learning/">machine learning</a> pipelines, choosing the right framework can make or break your project.</p> <p>Every year, we survey thousands of Python developers to help you understand how the ecosystem is evolving, from tooling and languages to frameworks and libraries. Our insights from the <a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/">State of Python 2025</a> offer a snapshot of what frameworks developers are using in 2025.</p> <p>In this article, we’ll look at the most popular Python frameworks and libraries. While some long-standing favorites like <a href="https://www.jetbrains.com/pycharm/web-development/django/" target="_blank" rel="noopener">Django</a> and <a href="https://blog.jetbrains.com/pycharm/tag/flask/">Flask</a> remain strong, newer contenders like <a href="https://blog.jetbrains.com/pycharm/tag/fastapi/">FastAPI</a> are rapidly gaining ground in areas like AI, ML, and data science.</p> <h2 class="wp-block-heading">1. FastAPI</h2> <p><strong>2024 usage: 38% (+9% from 2023)</strong></p> <p>Top of the table is <a href="https://fastapi.tiangolo.com/" target="_blank" rel="noopener">FastAPI</a>, a modern, high-performance web framework for building APIs with Python 3.8+. It was designed to combine Python’s type hinting, asynchronous programming, and OpenAPI standards into a single, developer-friendly package.&nbsp;</p> <p>Built on top of <a href="https://www.starlette.io/" target="_blank" rel="noopener">Starlette</a> (for the web layer) and <a href="https://docs.pydantic.dev/latest/" target="_blank" rel="noopener">Pydantic</a> (for data validation), FastAPI offers automatic request validation, serialization, and interactive documentation, all with minimal boilerplate.</p> <p>FastAPI is ideal for teams prioritizing speed, simplicity, and standards. It’s especially popular among both web developers and data scientists.</p> <h3 class="wp-block-heading">FastAPI advantages</h3> <ul> <li><strong>Great for AI/ML: </strong>FastAPI is widely used to deploy <a href="https://blog.jetbrains.com/pycharm/2024/09/how-to-use-fastapi-for-machine-learning/">machine learning</a> models in production. It integrates well with libraries like <a href="https://www.tensorflow.org/" target="_blank" rel="noopener">TensorFlow</a>, <a href="https://pytorch.org/" target="_blank" rel="noopener">PyTorch</a>, and <a href="https://blog.jetbrains.com/pycharm/2024/11/hugging-face-integration/">Hugging Face</a>, and supports async model inference pipelines for maximum throughput.</li> <li><strong>Asynchronous by default:</strong> Built on <a href="https://asgi.readthedocs.io/en/latest/" target="_blank" rel="noopener">ASGI,</a> FastAPI supports native async/await, making it ideal for real-time apps, streaming endpoints, and low-latency ML services.</li> <li><strong>Type-safe and modern</strong>: FastAPI uses Python’s type hints to auto-validate requests and generate clean, editor-friendly code, reducing runtime errors and boosting team productivity.</li> <li><strong>Auto-generated docs</strong>: FastAPI creates interactive documentation via <a href="https://swagger.io/tools/swagger-ui/" target="_blank" rel="noopener">Swagger UI</a> and <a href="https://github.com/Redocly/redoc" target="_blank" rel="noopener">ReDoc</a>, making it easy for teams to explore and test endpoints without writing any extra docs.</li> <li><strong>Strong community momentum:</strong> Though it&#8217;s relatively young, FastAPI has built a large and active community and has a growing ecosystem of extensions, tutorials, and integrations.</li> </ul> <h3 class="wp-block-heading">FastAPI disadvantages</h3> <ul> <li><strong>Steeper learning curve for asynchronous work</strong>: async/await unlocks performance, but debugging, testing, and concurrency management can challenge developers new to asynchronous programming.</li> <li><strong>Batteries not included</strong>: FastAPI lacks built-in tools for authentication, admin, and database management. You’ll need to choose and integrate these manually.</li> <li><strong>Smaller ecosystem</strong>: FastAPI’s growing plugin landscape still trails Django’s, with fewer ready-made tools for tasks like CMS integration or role-based access control.</li> </ul> <h2 class="wp-block-heading">2. Django</h2> <p><strong>2024 usage: 35% (+2% from 2023)</strong></p> <p><a href="https://www.djangoproject.com/" target="_blank" rel="noopener">Django</a> once again ranks among the most popular Python frameworks for developers.</p> <p>Originally built for rapid development with built-in security and structure, Django has since evolved into a full-stack toolkit. It’s trusted for everything from content-heavy websites to data science dashboards and ML-powered services.</p> <p>It follows the <a href="https://blog.jetbrains.com/pycharm/2025/01/django-views/">model-template-view (MTV)</a> pattern and comes with built-in tools for routing, data access, and user management. This allows teams to move from idea to deployment with minimal setup.</p> <h3 class="wp-block-heading">Django advantages</h3> <ul> <li><strong>Batteries included:</strong> Django has a comprehensive set of built-in tools, including an ORM, a user authenticator, an admin panel, and a <a href="https://blog.jetbrains.com/pycharm/2025/02/the-ultimate-guide-to-django-templates/">templating engine</a>. This makes it ideal for teams that want to move quickly without assembling their own stack.</li> <li><strong>Secure by default:</strong> It includes built-in protections against CSRF, SQL injection, XSS, and other common vulnerabilities. Django’s security-first approach is one reason it’s trusted by banks, governments, and large enterprises.</li> <li><strong>Scalable and production-ready:</strong> Django supports horizontal scaling, caching, and asynchronous views. It’s been used to power high-traffic platforms like Instagram, Pinterest, and Disqus.</li> <li><strong>Excellent documentation:</strong> <a href="https://docs.djangoproject.com/" target="_blank" rel="noopener">Django’s official docs</a> are widely praised for their clarity and completeness, making it accessible to developers at all levels.</li> <li><strong>Mature ecosystem:</strong> Thousands of third-party packages are available for everything from CMS platforms and REST APIs to payments and search.</li> <li><strong>Long-term support:</strong> Backed by the <a href="https://www.djangoproject.com/foundation/" target="_blank" rel="noopener">Django Software Foundation</a>, Django receives regular updates, security patches, and LTS releases, making it a safe choice for long-term projects.</li> </ul> <h3 class="wp-block-heading">Django disadvantages</h3> <ul> <li><strong>Heavyweight for small apps:</strong> For simple APIs or microservices, Django’s full-stack approach can feel excessive and slow to configure.</li> <li><strong>Tightly coupled components:</strong> Swapping out parts of the stack, such as the ORM or templating engine, often requires workarounds or deep customization.</li> <li><strong>Steeper learning curve:</strong> Django’s conventions and depth can be intimidating for beginners or teams used to more minimal frameworks.</li> </ul> <h2 class="wp-block-heading">3. Flask</h2> <p><strong>2024 usage: 34% (+1% from 2023)</strong></p> <p><a href="https://flask.palletsprojects.com/" target="_blank" rel="noopener">Flask</a> is one of the most popular Python frameworks for small apps, APIs, and data science dashboards.&nbsp;</p> <p>It is a lightweight, unopinionated web framework that gives you full control over application architecture. Flask is classified as a “microframework” because it doesn’t enforce any particular project structure or include built-in tools like ORM or form validation.</p> <p>Instead, it provides a simple core and lets you add only what you need. Flask is built on top of <a href="https://werkzeug.palletsprojects.com/" target="_blank" rel="noopener">Werkzeug</a> (a WSGI utility library) and <a href="https://jinja.palletsprojects.com/" target="_blank" rel="noopener">Jinja2</a> (a templating engine). It’s known for its clean syntax, intuitive routing, and flexibility.</p> <p>It scales well when paired with extensions like <a href="https://www.sqlalchemy.org/" target="_blank" rel="noopener">SQLAlchemy</a>, <a href="https://flask-login.readthedocs.io/" target="_blank" rel="noopener">Flask-Login</a>, or Flask-RESTful.&nbsp;</p> <h3 class="wp-block-heading">Flask advantages</h3> <ul> <li><strong>Lightweight and flexible:</strong> Flask doesn’t impose structure or dependencies, making it ideal for microservices, APIs, and teams that want to build a stack from the ground up.</li> <li><strong>Popular for data science and ML workflows</strong>: Flask is frequently used for experimentation like building dashboards, serving models, or turning notebooks into lightweight web apps.</li> <li><strong>Beginner-friendly:</strong> With minimal setup and a gentle learning curve, Flask is often recommended as a first web framework for Python developers.</li> <li><strong>Extensible:</strong> A rich ecosystem of extensions allows you to add features like database integration, form validation, and authentication only when needed.</li> <li><strong>Modular architecture:</strong> Flask’s design makes it easy to break your app into blueprints or integrate with other services, which is perfect for teams working on distributed systems.</li> <li><strong>Readable codebase:</strong> Flask’s source code is compact and approachable, making it easier to debug, customize, or fork for internal tooling.</li> </ul> <h3 class="wp-block-heading">Flask disadvantages</h3> <ul> <li><strong>Bring-your-own everything:</strong> Unlike Django, Flask doesn’t include an ORM, admin panel, or user management. You’ll need to choose and integrate these yourself.</li> <li><strong>DIY security:</strong> Flask provides minimal built-in protections, so you implement CSRF protection, input validation, and other best practices manually.</li> <li><strong>Potential to become messy:</strong> Without conventions or structure, large Flask apps can become difficult to maintain unless you enforce your own architecture and patterns.</li> </ul> <h2 class="wp-block-heading">4. Requests</h2> <p><strong>2024 usage: 33% (+3% from 2023)</strong></p> <p><a href="https://requests.readthedocs.io/en/latest/" target="_blank" rel="noopener">Requests</a> isn’t a web framework, it’s a Python library for making HTTP requests, but its influence on the Python ecosystem is hard to overstate. It’s one of the most downloaded packages on PyPI and is used in everything from web scraping scripts to production-grade microservices.</p> <p>Requests is often paired with frameworks like Flask or FastAPI to handle outbound HTTP calls. It abstracts away the complexity of raw sockets and urllib, offering a clean, Pythonic interface for sending and receiving data over the web.</p> <h3 class="wp-block-heading">Requests advantages</h3> <ul> <li><strong>Simple and intuitive:</strong> Requests makes HTTP feel like a native part of Python. Its syntax is clean and readable – requests.get(url) is all it takes to fetch a resource.</li> <li><strong>Mature and stable:</strong> With over a decade of development, Requests is battle-tested and widely trusted. It’s used by millions of developers and is a default dependency in many Python projects.</li> <li><strong>Great for REST clients:</strong> Requests is ideal for consuming APIs, integrating with SaaS platforms, or building internal tools that rely on external data sources.</li> <li><strong>Excellent documentation and community:</strong> The official docs are clear and concise, and the library is well-supported by tutorials, Stack Overflow answers, and GitHub issues.</li> <li><strong>Broad compatibility:</strong> Requests works seamlessly across Python versions and platforms, with built-in support for sessions, cookies, headers, and timeouts.</li> </ul> <h3 class="wp-block-heading">Requests disadvantages</h3> <ul> <li><strong>Not async:</strong> Requests is synchronous and blocking by design. For high-concurrency workloads or async-native frameworks, alternatives like HTTPX or AIOHTTP are better.</li> <li><strong>No built-in retry logic:</strong> While it supports connection pooling and timeouts, retry behavior must be implemented manually or via third-party wrappers like urllib3.</li> <li><strong>Limited low-level control</strong>: Requests simplifies HTTP calls but abstracts networking details, making advanced tuning (e.g. sockets, DNS, and connection reuse) difficult.</li> </ul> <h2 class="wp-block-heading">5. Asyncio</h2> <p><strong>2024 usage: 23% (+3% from 2023)</strong></p> <p><a href="https://docs.python.org/3/library/asyncio.html" target="_blank" rel="noopener">Asyncio</a> is Python’s native library for asynchronous programming. It underpins many modern async frameworks and enables developers to write non-blocking code using coroutines, event loops, and async/await syntax.</p> <p>While not a web framework itself, Asyncio excels at handling I/O-bound tasks such as network requests and subprocesses. It’s often used behind the scenes, but remains a powerful tool for building custom async workflows or integrating with low-level protocols.</p> <h3 class="wp-block-heading">Asyncio advantages</h3> <ul> <li><strong>Native async support:</strong> Asyncio is part of the Python standard library and provides first-class support for asynchronous I/O using async/await syntax.</li> <li><strong>Foundation for modern frameworks:</strong> It powers many of today’s most popular async web frameworks, including FastAPI, Starlette, and AIOHTTP.</li> <li><strong>Fine-grained control:</strong> Developers can manage event loops, schedule coroutines, and coordinate concurrent tasks with precision, which is ideal for building custom async systems.</li> <li><strong>Efficient for I/O-bound workloads:</strong> Asyncio excels at handling large volumes of concurrent I/O operations, such as API calls, socket connections, or file reads.</li> </ul> <h3 class="wp-block-heading">Asyncio disadvantages</h3> <ul> <li><strong>Steep learning curve:</strong> Concepts like coroutines, event loops, and task scheduling can be difficult for developers new to asynchronous programming.</li> <li><strong>Not a full framework:</strong> Asyncio doesn’t provide routing, templating, or request handling. It’s a low-level tool that requires additional libraries for web development.</li> <li><strong>Debugging complexity:</strong> Async code can be harder to trace and debug, especially when dealing with race conditions or nested coroutines.</li> </ul> <h2 class="wp-block-heading">6. Django REST Framework</h2> <p><strong>2024 usage: 20% (+2% from 2023)</strong></p> <p><a href="https://www.django-rest-framework.org/" target="_blank" rel="noopener">Django REST Framework</a> (DRF) is the most widely used extension for building APIs on top of Django. It provides a powerful, flexible toolkit for serializing data, managing permissions, and exposing RESTful endpoints – all while staying tightly integrated with Django’s core components.</p> <p>DRF is especially popular in enterprise and backend-heavy applications where teams are already using Django and want to expose a clean, scalable API without switching stacks. It’s also known for its browsable API interface, which makes testing and debugging endpoints much easier during development.</p> <h3 class="wp-block-heading">Django REST Framework advantages</h3> <ul> <li><strong>Deep Django integration:</strong> DRF builds directly on Django’s models, views, and authentication system, making it a natural fit for teams already using Django.</li> <li><strong>Browsable API interface:</strong> One of DRF’s key features is its interactive web-based API explorer, which helps developers and testers inspect endpoints without needing external tools.</li> <li><strong>Flexible serialization:</strong> DRF’s serializers can handle everything from simple fields to deeply nested relationships, and they support both ORM and non-ORM data sources.</li> <li><strong>Robust permissions system:</strong> DRF includes built-in support for role-based access control, object-level permissions, and custom authorization logic.</li> <li><strong>Extensive documentation:</strong> DRF is well-documented and widely taught, with a large community and plenty of tutorials, examples, and third-party packages.</li> </ul> <h3 class="wp-block-heading">Django REST Framework disadvantages</h3> <ul> <li><strong>Django-dependent with heavier setup</strong>: DRF is tightly tied to Django and requires more configuration than lightweight frameworks like FastAPI, especially when customizing behavior.</li> <li><strong>Less flexible serialization</strong>: DRF’s serializers work well for common cases, but customizing them for complex or non-standard data often demands verbose overrides.</li> </ul> <h2 class="wp-block-heading">Best of the rest: Frameworks 7–10</h2> <p>While the most popular Python frameworks dominate usage across the ecosystem, several others continue to thrive in more specialized domains. These tools may not rank as high overall, but they play important roles in backend services, data pipelines, and async systems.</p> <table><tbody><tr><td><strong>Framework</strong></td><td><strong>Overview</strong></td><td><strong>Advantages</strong></td><td><strong>Disadvantages</strong></td></tr><tr><td><a href="https://www.python-httpx.org/" target="_blank" rel="noopener"><strong>httpx</strong></a><br />2024 usage: 15% (+3% from 2023)</td><td>Modern HTTP client for sync and async workflows</td><td>Async support, HTTP/2, retries, and type hints</td><td>Not a web framework, no routing or server-side features</td></tr><tr><td><a href="https://docs.aiohttp.org/en/stable/" target="_blank" rel="noopener"><strong>aiohttp</strong></a><br />2024 usage: 13% (+1% from 2023)</td><td>Async toolkit for HTTP servers and clients</td><td>ASGI-ready, native WebSocket handling, and flexible middleware</td><td>Lower-level than FastAPI, less structured for large apps.</td></tr><tr><td><a href="https://streamlit.io/" target="_blank" rel="noopener"><strong>Streamlit</strong></a><br />2024 usage: 12% (+4% from 2023)</td><td>Dashboard and data app builder for data workflows</td><td>Fast UI prototyping, with zero front-end knowledge required</td><td>Limited control over layout, less suited for complex UIs.</td></tr><tr><td><a href="https://www.starlette.io/" target="_blank" rel="noopener"><strong>Starlette</strong></a><br />2024 usage: 8% (+2% from 2023)</td><td>Lightweight ASGI framework used by FastAPI</td><td>Exceptional performance, composable design, fine-grained routing</td><td>Requires manual integration, fewer built-in conveniences</td></tr></tbody></table> <h2 class="wp-block-heading">Choosing the right framework and tools</h2> <p>Whether you’re building a blazing-fast API with FastAPI, a full-stack CMS with Django, or a lightweight dashboard with Flask, the most popular Python web frameworks offer solutions for every use case and developer style.</p> <p>Insights from the <a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/">State of Python 2025</a> show that while Django and Flask remain strong, FastAPI is leading a new wave of async-native, type-safe development. Meanwhile, tools like Requests, Asyncio, and Django REST Framework continue to shape how Python developers build and scale modern web services.</p> <p>But frameworks are only part of the equation. The right development environment can make all the difference, from faster debugging to <a href="https://www.jetbrains.com/pycharm/features/coding_assistance.html" target="_blank" rel="noopener">smarter code completion</a> and seamless framework integration.</p> <p>That’s where <a href="https://www.jetbrains.com/pycharm/" target="_blank" rel="noopener">PyCharm</a> comes in. Whether you’re working with Django, FastAPI, Flask, or all three, PyCharm offers deep support for Python web development. This includes async debugging, REST client tools, and rich integration with popular libraries and frameworks.</p> <p>Ready to build something great? Try PyCharm and see how much faster and smoother Python web development can be.</p> <div class="buttons"> <div class="buttons__row"> <a href="https://www.jetbrains.com/pycharm/web-development" class="btn" target="_blank" rel="noopener">Try PyCharm for free</a> </div> </div> Tue, 20 Jan 2026 13:40:46 +0000 PyCharm <p>Hugging Face is currently a household name for machine learning researchers and enthusiasts. One of their biggest successes is <a href="https://huggingface.co/docs/transformers/en/index" target="_blank" rel="noopener">Transformers</a>, a model-definition framework for machine learning models in text, computer vision, audio, and video. Because of the vast repository of state-of-the-art machine learning models available on the <a href="https://huggingface.co/models" target="_blank" rel="noopener">Hugging Face Hub</a> and the compatibility of Transformers with the majority of training frameworks, it is widely used for inference and model training.</p> <h2 class="wp-block-heading">Why do we want to fine-tune an AI model?</h2> <p>Fine-tuning AI models is crucial for tailoring their performance to specific tasks and datasets, enabling them to achieve higher accuracy and efficiency compared to using a general-purpose model. By adapting a pre-trained model, fine-tuning reduces the need for training from scratch, saving time and resources. It also allows for better handling of specific formats, nuances, and edge cases within a particular domain, leading to more reliable and tailored outputs.<br /><br />In this blog post, we will fine-tune a GPT model with mathematical reasoning so it better handles math questions.</p> <h2 class="wp-block-heading">Using models from Hugging Face</h2> <p>After <a href="https://www.jetbrains.com/pycharm/download/" target="_blank" rel="noopener">downloading PyCharm</a>, we can easily browse and add any models from Hugging Face. In a new Python file, from the <em>Code</em> menu at the top, select <em>Insert HF Model</em>.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-40.png" alt="Using models from Hugging Face" class="wp-image-594074" /> <p>In the menu that opens, you can browse models by category or start typing in the search bar at the top. When you select a model, you can see its description on the right.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-41.png" alt="Explore models from Hugging Face" class="wp-image-594085" /> <p>When you click<em> Use Model, </em>you will see a code snippet added to your file. And that&#8217;s it – You&#8217;re ready to start using your Hugging Face model.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-42.png" alt="Use Hugging Face models in PyCharm" class="wp-image-594096" /> <h2 class="wp-block-heading">GPT (Generative Pre-Trained Transformer) models</h2> <p>GPT models are very popular on the <a href="https://huggingface.co/models" target="_blank" rel="noopener">Hugging Face Hub</a>, but what are they? GPTs are trained models that understand natural language and generate high-quality text. They are mainly used in tasks related to textual entailment, question answering, semantic similarity, and document classification. The most famous example is <a href="https://openai.com/index/chatgpt/" target="_blank" rel="noopener">ChatGPT, created by OpenAI</a>.</p> <p>A lot of OpenAI GPT models are available on the <a href="https://huggingface.co/models" target="_blank" rel="noopener">Hugging Face Hub</a>, and we will learn how to use these models with Transformers<em>, </em>fine-tune them with our own data, and deploy them in an application<em>.</em></p> <h2 class="wp-block-heading">Benefits of using Transformers</h2> <p>Transformers, together with other tools provided by Hugging Face, provides high-level tools for fine-tuning any sophisticated deep learning model. Instead of requiring you to fully understand a given model’s architecture and tokenization method, these tools help make models “plug and play” with any compatible training data, while also providing a large amount of customization in tokenization and training.</p> <h2 class="wp-block-heading">Transformers in action</h2> <p>To get a closer look at<em> </em>Transformers in action, let’s see how we can use it to interact with a GPT model.</p> <h3 class="wp-block-heading">Inference using a pretrained model with a pipeline</h3> <p>After selecting and adding the OpenAI GPT-2 model to the code, this is what we’ve got:</p> <pre class="EnlighterJSRAW">from transformers import pipeline pipe = pipeline("text-generation", model="openai-community/gpt2")</pre> <p>Before we can use it, we need to make a few preparations. First, we need to install a machine learning framework. In this example, we chose <a href="https://pytorch.org/get-started/locally/" target="_blank" rel="noopener">PyTorch</a>. You can install it easily via the <em>Python Packages</em> window in PyCharm.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-43.png" alt="Install PyTorch in PyCharm" class="wp-image-594107" /> <p>Then we need to install Transformers<em> </em>using the `torch` option. You can do that by using the terminal – open it using the button on the left or use the <em>⌥ F12 </em>(macOS) or <em>Alt + F12</em> (Windows) hotkey.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-44.png" alt="Install Transformers in PyCharm's terminal" class="wp-image-594118" /> <p>In the terminal, since we are using uv, we use the following commands to add it as a dependency and install it:</p> <pre class="EnlighterJSRAW">uv add “transformers[torch]” uv sync</pre> <p>If you are using pip:</p> <pre class="EnlighterJSRAW">pip install “transformers[torch]”</pre> <p>We will also install a couple more libraries that we will need later, including python-dotenv, datasets<em>, </em>notebook,<em> </em>and<em> </em>ipywidgets<em>. </em>You can use either of the methods above to install them.<br />After that, it may be best to add a GPU device to speed up the model. Depending on what you have on your machine, you can add it by setting the device parameter in pipeline<em>. </em>Since I am using a Mac M2 machine, I can set<code class="EnlighterJSRAW"> device="mps"</code> like this:</p> <pre class="EnlighterJSRAW">pipe = pipeline("text-generation", model="openai-community/gpt2", device="mps")</pre> <p>If you have CUDA GPUs you can also set <code class="EnlighterJSRAW">device="cuda"</code>.</p> <p>Now that we’ve set up our pipeline, let’s try it out with a simple prompt:</p> <pre class="EnlighterJSRAW">from transformers import pipeline pipe = pipeline("text-generation", model="openai-community/gpt2", device="mps") print(pipe("A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?", max_new_tokens=200))</pre> <p>Run the script with the <em>Run</em> button (<img src="https://blog.jetbrains.com/wp-content/uploads/2025/09/AD_4nXf6ZDm7vSGyFlO0DzXegK6WP9JxsStUiJA-bkRZ0mwPsUsmn8M70emV5Sr8f17-fEK6z9V1EQKWEm3RPHdT8n8uqG18faVmQn5y09psVInQLU0CZQKXAEg2q7m7AOsh4hPU7G8gcQ.png" />) at the top:</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-45.png" alt="Run the script in PyCharm" class="wp-image-594129" /> <p>The result will look something like this:</p> <pre class="EnlighterJSRAW">[{'generated_text': 'A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?nnA rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width?nnA rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width?nnA rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter'}]</pre> <p>There isn’t much reasoning in this at all, only a bunch of nonsense.&nbsp;</p> <p>You may also see this warning:</p> <pre class="EnlighterJSRAW">Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.</pre> <p>This is the default setting. You can also manually add it as below, so this warning disappears, but we don’t have to worry about it too much at this stage.</p> <pre class="EnlighterJSRAW">print(pipe("A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?", max_new_tokens=200, pad_token_id=pipe.tokenizer.eos_token_id))</pre> <p>Now that we’ve seen how GPT-2 behaves out of the box, let’s see if we can make it better at math reasoning with some fine-tuning.</p> <h3 class="wp-block-heading">Load and prepare a dataset from the Hugging Face Hub</h3> <p>Before we work on the GPT model, we first need training data. Let’s see how to get a dataset from the Hugging Face Hub.</p> <p>If you haven&#8217;t already, sign up for a Hugging Face account and <a href="https://huggingface.co/docs/hub/security-tokens#user-access-tokens" target="_blank" rel="noopener">create an access token</a>. We only need a `read` token for now. Store your token in a `.env` file, like so:</p> <pre class="EnlighterJSRAW">HF_TOKEN=your-hugging-face-access-token</pre> <p>We will use this <a href="https://huggingface.co/datasets/Cheukting/math-meta-reasoning-cleaned" target="_blank" rel="noopener">Math Reasoning Dataset</a>, which has text describing some math reasoning. We will fine-tune our GPT model with this dataset so it can solve math problems more effectively.</p> <p>Let’s create a new Jupyter notebook, which we’ll use for fine-tuning because it lets us run different code snippets one by one and monitor the progress.</p> <p>In the first cell, we use this script to load the dataset from the Hugging Face Hub:</p> <pre class="EnlighterJSRAW">from datasets import load_dataset from dotenv import load_dotenv import os load_dotenv() dataset = load_dataset("Cheukting/math-meta-reasoning-cleaned", token=os.getenv("HF_TOKEN")) dataset</pre> <p>Run this cell (it may take a while, depending on your internet speed), which will download the dataset. When it’s done, we can have a look at the result:</p> <pre class="EnlighterJSRAW">DatasetDict({ train: Dataset({ features: ['id', 'text', 'token_count'], num_rows: 987485 }) }) </pre> <p>If you are curious and want to have a peek at the data, you can do so in PyCharm. Open the <em>Jupyter Variables</em> window using the button on the right:</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-46.png" alt="Open Jupyter Variables in PyCharm" class="wp-image-594140" /> <p>Expand <em>dataset</em> and you will see the <em>View as DataFrame</em> option next to <em>dataset[‘train’]</em>:</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-47.png" alt="Jupyter Variables in PyCharm" class="wp-image-594152" /> <p>Click on it to take a look at the data in the <em>Data View</em> tool window:</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-48.png" alt="Data View tool in PyCharm" class="wp-image-594163" /> <p>Next, we will tokenize the text in the dataset:</p> <pre class="EnlighterJSRAW">from transformers import GPT2Tokenizer tokenizer = GPT2Tokenizer.from_pretrained("openai-community/gpt2") tokenizer.pad_token = tokenizer.eos_token def tokenize_function(examples): return tokenizer(examples['text'], truncation=True, padding='max_length', max_length=512) tokenized_datasets = dataset.map(tokenize_function, batched=True)</pre> <p>Here we use the GPT-2 tokenizer and set the <code>pad_token</code> to be the <code>eos_token</code>, which is the token indicating the end of line. After that, we will tokenize the text with a function. It may take a while the first time you run it, but after that it will be cached and will be faster if you have to run the cell again.</p> <p>The dataset has almost 1 million rows for training. If you have enough computing power to process all of them, you can use them all. However, in this demonstration we’re training locally on a laptop, so I&#8217;d better only use a small portion!</p> <pre class="EnlighterJSRAW">tokenized_datasets_split = tokenized_datasets["train"].shard(num_shards=100, index=0).train_test_split(test_size=0.2, shuffle=True) tokenized_datasets_split</pre> <p>Here I take only 1% of the data, and then perform <code>train_test_split</code><em> </em>to split the dataset into two:</p> <pre class="EnlighterJSRAW">DatasetDict({ train: Dataset({ features: ['id', 'text', 'token_count', 'input_ids', 'attention_mask'], num_rows: 7900 }) test: Dataset({ features: ['id', 'text', 'token_count', 'input_ids', 'attention_mask'], num_rows: 1975 }) }) </pre> <p>Now we are ready to fine-tune the GPT-2 model.</p> <h3 class="wp-block-heading">Fine-tune a GPT model</h3> <p>In the next empty cell, we will set our training arguments:</p> <pre class="EnlighterJSRAW">from transformers import TrainingArguments training_args = TrainingArguments( output_dir='./results', num_train_epochs=5, per_device_train_batch_size=8, per_device_eval_batch_size=8, warmup_steps=100, weight_decay=0.01, save_steps = 500, logging_steps=100, dataloader_pin_memory=False )</pre> <p>Most of them are pretty standard for fine-tuning a model. However, depending on your computer setup, you may want to tweak a few things:</p> <ul> <li>Batch size – Finding the optimal batch size is important, since the larger the batch size is, the faster the training goes. However, there is a limit to how much memory is available for your CPU or GPU, so you may find there’s an upper threshold.</li> <li>Epochs – Having more epochs causes the training to take longer. You can decide how many epochs you need.</li> <li>Save steps – Save steps determine how often a checkpoint will be saved to disk. If the training is slow and there is a chance that it will stop unexpectedly, then you may want to save more often ( set this value lower).</li> </ul> <p>&nbsp;After we’ve configured our settings, we will put the trainer together in the next cell:</p> <pre class="EnlighterJSRAW">from transformers import Trainer, DataCollatorForLanguageModeling model = GPT2LMHeadModel.from_pretrained("openai-community/gpt2") data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False) trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_datasets_split['train'], eval_dataset=tokenized_datasets_split['test'], data_collator=data_collator, ) trainer.train(resume_from_checkpoint=False)</pre> <p>We set `resume_from_checkpoint=False`, but you can set it to `True` to continue from the last checkpoint if the training is interrupted.</p> <p>After the training finishes, we will evaluate and save the model:</p> <pre class="EnlighterJSRAW">trainer.evaluate(tokenized_datasets_split['test']) trainer.save_model("./trained_model")</pre> <p>We can now use the trained model in the pipeline. Let’s switch back to `model.py`, where we have used a pipeline with a pretrained model:</p> <pre class="EnlighterJSRAW">from transformers import pipeline pipe = pipeline("text-generation", model="openai-community/gpt2", device="mps") print(pipe("A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?", max_new_tokens=200, pad_token_id=pipe.tokenizer.eos_token_id))</pre> <p>Now let’s change `model=&#8221;openai-community/gpt2&#8243;` to `model=&#8221;./trained_model&#8221;` and see what we get:</p> <pre class="EnlighterJSRAW">[{'generated_text': "A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?nAlright, let me try to solve this problem as a student, and I'll let my thinking naturally fall into the common pitfall as described.nn---nn**Step 1: Attempting the Problem (falling into the pitfall)**nnWe have a rectangle with perimeter 20 cm. The length is 6 cm. We want the width.nnFirst, I need to find the area under the rectangle.nnLet’s set \( A = 20 - 12 \), where \( A \) is the perimeter.nn**Area under a rectangle:** n\[nA = (20-12)^2 + ((-12)^2)^2 = 20^2 + 12^2 = 24n\]nnSo, \( 24 = (20-12)^2 = 27 \).nnNow, I’ll just divide both sides by 6 to find the area under the rectangle.n"}]</pre> <p>Unfortunately, it still does not solve the problem. However, it did come up with some mathematical formulas and reasoning that it didn’t use before. If you want, you can try fine-tuning the model a bit more with the data we didn’t use.</p> <p>In the next section, we will see how we can deploy a fine-tuned model to API endpoints using both the tools provided by Hugging Face and FastAPI.</p> <h2 class="wp-block-heading">Deploying a fine-tuned model</h2> <p>The easiest way to deploy a model in a server backend is to use FastAPI. Previously, I wrote a <a href="https://blog.jetbrains.com/pycharm/2024/09/how-to-use-fastapi-for-machine-learning/">blog post</a> about deploying a machine learning model with FastAPI. While we won’t go into the same level of detail here, we will go over how to deploy our fine-tuned model.</p> <p>With the help of <a href="https://www.jetbrains.com/junie/" target="_blank" rel="noopener">Junie</a>, we’ve created some scripts which you can see <a href="https://github.com/Cheukting/fine-tune-gpt2/tree/main/app" target="_blank" rel="noopener">here</a>. These scripts let us deploy a server backend with FastAPI endpoints.&nbsp;</p> <p>There are some new dependencies that we need to add:</p> <pre class="EnlighterJSRAW">uv add fastapi pydantic uvicorn uv sync</pre> <p>Let’s have a look at some interesting points in the scripts, in `main.py`:</p> <pre class="EnlighterJSRAW"># Initialize FastAPI app app = FastAPI( title="Text Generation API", description="API for generating text using a fine-tuned model", version="1.0.0" ) # Initialize the model pipeline try: pipe = pipeline("text-generation", model="../trained_model", device="mps") except Exception as e: # Fallback to CPU if MPS is not available try: pipe = pipeline("text-generation", model="../trained_model", device="cpu") except Exception as e: print(f"Error loading model: {e}") pipe = None</pre> <p>After initializing the app, the script will try to load the model into a pipeline. If a Metal GPU is not available, it will fall back to using the CPU. If you have a CUDA GPU instead of a Metal GPU, you can change `mps` to `cuda`.</p> <pre class="EnlighterJSRAW"># Request model class TextGenerationRequest(BaseModel): prompt: str max_new_tokens: int = 200 # Response model class TextGenerationResponse(BaseModel): generated_text: str</pre> <p>Two new classes are created, inheriting from Pydantic’s<em> </em>`BaseModel`<em>.</em></p> <p>We can also inspect our endpoints with the <em>Endpoints </em>tool window<em>. </em>Click on the globe next to `app = FastAPI` on line 11 and select <em>Show All Endpoints</em>.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-49.png" alt="Show all endpoints in PyCharm" class="wp-image-594174" /> <p>We have three endpoints. Since the root endpoint is just a welcome message, we will look at the other two.</p> <pre class="EnlighterJSRAW">@app.post("/generate", response_model=TextGenerationResponse) async def generate_text(request: TextGenerationRequest): """ Generate text based on the provided prompt. Args: request: TextGenerationRequest containing the prompt and generation parameters Returns: TextGenerationResponse with the generated text """ if pipe is None: raise HTTPException(status_code=500, detail="Model not loaded properly") try: result = pipe( request.prompt, max_new_tokens=request.max_new_tokens, pad_token_id=pipe.tokenizer.eos_token_id ) # Extract the generated text from the result generated_text = result[0]['generated_text'] return TextGenerationResponse(generated_text=generated_text) except Exception as e: raise HTTPException(status_code=500, detail=f"Error generating text: {str(e)}") </pre> <p>The `/generate` endpoint collects the request prompt and generates the response text with the model.</p> <pre class="EnlighterJSRAW">@app.get("/health") async def health_check(): """Check if the API and model are working properly.""" if pipe is None: raise HTTPException(status_code=500, detail="Model not loaded") return {"status": "healthy", "model_loaded": True}</pre> <p>The `/health` endpoint checks whether the model is loaded correctly. This can be useful if the client-side application needs to check before making the other endpoint available in its UI.</p> <p>In `run.py`, we use <a href="https://www.uvicorn.org/" target="_blank" rel="noopener">uvicorn</a> to run the server:</p> <pre class="EnlighterJSRAW">import uvicorn if __name__ == "__main__": uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)</pre> <p>When we run this script, the server will be started at <a href="http://0.0.0.0:8000/" target="_blank">http://0.0.0.0:8000/</a>.</p> <p>After we start running the server, we can go to <a href="http://0.0.0.0:8000/docs" target="_blank">http://0.0.0.0:8000/docs</a> to test out the endpoints.&nbsp;</p> <h2 class="wp-block-heading"><img src="https://blog.jetbrains.com/wp-content/uploads/2025/09/AD_4nXf6PXwz_Vz7VEQoyZs20NJ9TsO36oWJPf0w4iMjwHZ_EBP1Pk9c_8aWR2ybGE-wsmArM1zAQl1s8jHEr09I0g1A3boGD1Kt4i4CemufHZTHnATjIWrJ8x2ZUYg4Q7E4b3tc2XDmmg.png" /></h2> <p>We can try this with the `/generate` endpoint:</p> <pre class="EnlighterJSRAW">{ "prompt": "5 people give each other a present. How many presents are given altogether?", "max_new_tokens": 300 }</pre> <p>This is the response we get:</p> <pre class="EnlighterJSRAW">{ "generated_text": "5 people give each other a present. How many presents are given altogether?nAlright, let's try to solve the problem:nn**Problem** n1. Each person gives each other a present. How many presents are given altogether?n2. How many "gift" are given altogether?nn**Common pitfall** nAssuming that each present is a "gift" without considering the implications of the original condition.nn---nn### Step 1: Attempting the problem (falling into the pitfall)nnOkay, so I have two people giving each other a present, and I want to know how many are present. I remember that there are three types of gifts—gifts, gins, and ginses.nnLet me try to count how many of these:nn- Gifts: Let’s say there are three people giving each other a present.n- Gins: Let’s say there are three people giving each other a present.n- Ginses: Let’s say there are three people giving each other a present.nnSo, total gins and ginses would be:nn- Gins: \( 2 \times 3 = 1 \), \( 2 \times 1 = 2 \), \( 1 \times 1 = 1 \), \( 1 \times 2 = 2 \), so \( 2 \times 3 = 4 \).n- Ginses: \( 2 \times 3 = 6 \), \(" } </pre> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-50.png" alt="" class="wp-image-594185" /> <p>Feel free to experiment with other requests.</p> <h2 class="wp-block-heading">Conclusion and next steps</h2> <p>Now that you have successfully fine-tuned an LLM model like GPT-2 with a math reasoning dataset and deployed it with FastAPI, you can fine-tune a lot more of the open-source LLMs available on the Hugging Face Hub. You can experiment with fine-tuning other LLM models with either the open-source data there or your own datasets. If you want to (and the license of the original model allows), you can also upload your fine-tuned model on the Hugging Face Hub. Check out their <a href="https://huggingface.co/docs/transformers/v4.53.3/en/main_classes/trainer#transformers.Trainer.push_to_hub" target="_blank" rel="noopener">documentation</a> for how to do that.</p> <p>One last remark regarding using or fine-tuning models with resources on the Hugging Face Hub – make sure to read the licenses of any model or dataset that you use to understand the conditions for working with those resources. Is it allowed to be used commercially? Do you need to credit the resources used?</p> <p>In future blog posts, we will keep exploring more code examples involving Python, AI, machine learning, and data visualization.</p> <p>In my opinion, <a href="https://www.jetbrains.com/pycharm/" target="_blank" rel="noopener">PyCharm</a> provides best-in-class Python support that ensures both speed and accuracy. Benefit from the smartest code completion, PEP 8 compliance checks, intelligent refactorings, and a variety of inspections to meet all your coding needs. As demonstrated in this blog post, PyCharm provides integration with the Hugging Face Hub, allowing you to browse and use models without leaving the IDE. This makes it suitable for a wide range of AI and LLM fine-tuning projects.</p> <div class="buttons"> <div class="buttons__row"> <a href="https://www.jetbrains.com/pycharm/" class="btn" target="" rel="noopener">Download PyCharm Now</a> </div> </div> Tue, 20 Jan 2026 13:40:46 +0000 PyCharm <p><em>This is a guest post from <a href="https://blog.jetbrains.com/pycharm/2025/08/the-state-of-python-2025/#author">Michael Kennedy</a>, the founder of Talk Python and a PSF Fellow.</em></p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/Blog-Featured-1280x720-1-2.png" alt="State of Python 2025" class="wp-image-591576" /> <p>Welcome to the highlights, trends, and key actions from the <a href="https://lp.jetbrains.com/python-developers-survey-2024/" target="_blank" rel="noopener">eighth annual Python Developers Survey</a>. This survey is conducted as a collaborative effort between the Python Software Foundation and JetBrains’ PyCharm team. The survey results provide a comprehensive look at Python usage statistics and popularity trends in 2025.</p> <p>My name is Michael Kennedy, and I&#8217;ve analyzed the more than 30,000 responses to the survey and pulled out the most significant trends and predictions, and identified various actions that you can take to improve your Python career.</p> <p>I am in a unique position as the host of the <em>Talk Python to Me</em> podcast. Every week for the past 10 years, I&#8217;ve interviewed the people behind some of the most important libraries and language trends in the Python ecosystem. In this article, my goal is to use that larger community experience to understand the results of this important yearly survey.</p> <p>If your job or products and services depend on Python, or developers more broadly, you&#8217;ll want to read this article. It provides a lot of insight that is difficult to gain from other sources.</p> <h2 class="wp-block-heading">Key Python trends in 2025</h2> <p>Let’s dive into the most important trends based on the Python survey results.&nbsp;</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-14.png" alt="Infographic showing key Python trends in 2025" class="wp-image-591587" /> <p>As you explore these insights, having the right tools for your projects can make all the difference. Try PyCharm for free and stay equipped with everything you need for data science, ML/AI workflows, and web development in one powerful Python IDE.</p> <div class="buttons"> <div class="buttons__row"> <a href="https://www.jetbrains.com/pycharm/download/" class="btn" target="" rel="noopener">Try PyCharm for free</a> </div> </div> <h3 class="wp-block-heading">Python people use Python</h3> <p>Let&#8217;s begin by talking about how central Python is for people who use it. Python people use Python primarily. That might sound like an obvious tautology. However, developers use many languages that are not their primary language. For example, web developers might use Python, C#, or Java primarily, but they also use CSS, HTML, and even JavaScript.</p> <p>On the other hand, developers who work primarily with Node.js or Deno also use JavaScript, but not as their primary language.</p> <p>The survey shows that <strong>86% of respondents use Python as their main language</strong> for writing computer programs, building applications, creating APIs, and more.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-15.png" alt="Donut chart of Python usage in 2025: 86% use Python as main language, 14% as secondary." class="wp-image-591599" /> <h3 class="wp-block-heading">We are mostly brand-new programmers</h3> <p>For those of us who have been programming for a long time – I include myself in this category, having written code for almost 30 years now – it&#8217;s easy to imagine that most people in the industry have a decent amount of experience. It&#8217;s a perfectly reasonable assumption. You go to conferences and talk with folks who have been doing programming for 10 or 20 years. You look at your colleagues, and many of them have been using Python and programming for a long time.</p> <p>But that is not how the broader Python ecosystem looks.</p> <p>Exactly 50% of respondents have less than two years of professional coding experience! And 39% have less than two years of experience with Python (even in hobbyist or educational settings).</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-16.png" alt="Bar chart of developers’ coding experience: 31% less than 1 year, 19% with 1–2 years, 20% with 3–5 years, 13% with 6–10 years, 17% with 11+ years." class="wp-image-591612" /> <p>This result reaffirms that Python is a great language for those early in their career. The simple (but not simplistic) syntax and approachability really speak to newer programmers as well as seasoned ones. Many of us love programming and Python and are happy to share it with our newer community members.</p> <p>However, it suggests that we consider these demographics when we create content for the community. If you create a tutorial or video demonstration, don&#8217;t skimp on the steps to help people get started. For example, don&#8217;t just tell them to install the package. Tell them that they need to <a href="https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html" target="_blank" rel="noopener">create a virtual environment</a>, and show them how to do so and how to activate it. Guide them on installing the package into that virtual environment.</p> <p>If you&#8217;re a tool vendor such as JetBrains, you&#8217;ll certainly want to keep in mind that many of your users will be quite new to programming and to Python itself. That doesn&#8217;t mean you should ignore advanced features or dumb down your products, but don&#8217;t make it hard for beginners to adopt them either.</p> <h3 class="wp-block-heading">Data science is now over half of all Python</h3> <p>This year, 51% of all surveyed Python developers are involved in <a href="https://www.jetbrains.com/pycharm/data-science/" target="_blank" rel="noopener">data exploration and processing</a>, with pandas and NumPy being the tools most commonly used for this.</p> <p>Many of us in the Python pundit space have talked about Python as being divided into thirds: One-third web development, one-third <a href="https://www.jetbrains.com/pycharm/data-science/" target="_blank" rel="noopener">Python for data science</a> and pure science, and one-third as a catch-all bin.</p> <p>We need to rethink that positioning now that one of those thirds is overwhelmingly the most significant portion of Python.</p> <p>This is also in the context of not only a massive boom in the interest in data and AI right now, but a corresponding explosion in the development of tools to work with in this space. There are data processing tools like Polars, new ways of working with notebooks like Marimo, and a huge number of user friendly packages for working with LLMs, vision models, and agents, such as Transformers (the Hugging Face library for LLMs), Diffusers (for diffusion models), smolagents, LangChain/LangGraph (frameworks for LLM agents) and LlamaIndex (for indexing knowledge for LLMs).</p> <p><strong>Python&#8217;s center of gravity has indeed tilted further toward data/AI</strong>.</p> <h3 class="wp-block-heading"><strong>Most still use older Python versions despite benefits of newer releases</strong>&nbsp;</h3> <p>The survey shows a distribution across the latest and older versions of the Python runtime. Many of us (15%) are running on the very latest released version of Python, but <strong>more likely than not, we&#8217;re using a version a year old or older (83%)</strong>.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-17.png" alt="Bar chart of Python version usage in 2025: 35% on Python 3.12, 21% on 3.11, 15% on 3.13, smaller shares on older versions." class="wp-image-591623" /> <p>The survey also indicates that many of us are using Docker and containers to execute our code, which makes this 83% or higher number even more surprising. With containers, just pick the latest version of Python in the container. Since everything is isolated, you don&#8217;t need to worry about its interactions with the rest of the system, for example, Linux&#8217;s system Python. We should expect containerization to provide more flexibility and ease our transition towards the latest version of Python.</p> <p>So why haven&#8217;t people updated to the latest version of Python? The survey results give two primary reasons.</p> <ol> <li>The version I&#8217;m using meets all my needs (53%)</li> <li>I haven&#8217;t had the time to update (25%)</li> </ol> <p>The 83% of developers running on older versions of Python may be missing out on much more than they realize. It&#8217;s not just that they are missing some language features, such as the <code>except</code> keyword, or a minor improvement to the standard library, such as <code>tomllib</code>. <strong>Python 3.11, 3.12, and 3.13 all include major performance benefits</strong>, and the upcoming 3.14 will include even more.</p> <p>What&#8217;s amazing is you get these benefits without changing your code. You simply choose a newer runtime, and your code runs faster. CPython has been extremely good at backward compatibility. There&#8217;s rarely significant effort involved in upgrading. Let&#8217;s look at some numbers.</p> <p><strong>48% of people are currently using Python 3.11. </strong>Upgrading to 3.13 will make their code run ~<strong>11% faster</strong> end to end while using ~<strong>10-15% less memory</strong>.</p> <p>If they are one of the 27% still on <strong>3.10 or older</strong>, their code gets <strong>a whopping ~42% speed increase</strong> (with no code changes), and <strong>memory use can drop by ~20-30%</strong>!</p> <p>So maybe they&#8217;ll still come back to &#8220;Well, it&#8217;s fast enough for us. We don&#8217;t have that much traffic, etc.&#8221;. But if they are like most medium to large businesses, this is an incredible waste of cloud compute expense (which also maps to environmental harm via spent energy).</p> <p>Research shows some estimates for cloud compute (specifically computationally based):</p> <ul> <li><strong>Mid-market / &#8220;medium&#8221; business</strong> <ul> <li>Total annual AWS bill (median): ~ $2.3 million per year (<a href="https://www.vendr.com/marketplace/aws" target="_blank" rel="noopener">vendr.com</a>)</li> <li>EC2 (compute-instance) share (~ 50–70 % of that bill): $1.15–1.6 million per year (<a href="https://www.cloudlaya.com/blog/the-real-cost-of-ec2-instance/" target="_blank" rel="noopener">cloudlaya.com</a>)</li> </ul> </li> <li><strong>Large enterprise</strong> <ul> <li>Total annual AWS bill: ~ $24–36 million per year (i.e. $2–3 million per month) (<a href="https://www.reddit.com/r/aws/comments/1b6r50v/ballpark_how_much_is_your_total_spend_on_aws/" target="_blank" rel="noopener">reddit.com</a>)</li> <li>EC2 share (~ 50–70 %): $12–25 million per year (<a href="https://www.cloudlaya.com/blog/the-real-cost-of-ec2-instance/" target="_blank" rel="noopener">cloudlaya.com</a>)</li> </ul> </li> </ul> <p>If we assume they&#8217;re running Python 3.10, that&#8217;s potentially <strong>$420,000</strong> and <strong>$5.6M in savings</strong>, respectively (computed as 30% of the EC2 cost).</p> <p>If your company realizes you are burning an extra $0.4M-$5M a year because you haven’t gotten around to spending the day it takes to upgrade, that&#8217;ll be a tough conversation.</p> <p>Finances and environment aside, it&#8217;s really great to be able to embrace the latest language features and be in lock-step with the core devs&#8217; significant work. <strong>Make upgrading a priority</strong>,<strong> </strong>folks.</p> <h3 class="wp-block-heading">Python web devs resurgence</h3> <p>For the past few years, we&#8217;ve heard that the significance of web development within the Python space is decreasing. Two powerful forces could be at play here: 1) As more data science and AI-focused people come to Python, the relatively static number of web devs represents a lower percentage, and 2) The web continues to be frontend-focused, and until Python in the browser becomes a working reality, web developers are likely to prefer JavaScript.</p> <p>Looking at the numbers from 2021–2023, the trend is clearly downward 45% → 43% → 42%. <strong>But this year, the web is back</strong>! Respondents reported that 46% of them are using Python for web development in 2024. To bolster this hypothesis further, we saw web &#8220;secondary&#8221; languages jump correspondingly, with HTML/CSS usage up 15%, JavaScript usage up 14%, and SQL&#8217;s usage up 16%.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-18.png" alt="Line chart of Python use cases 2021–2024: data analysis at 48%, web development at 46%, machine learning at 41% in 2024." class="wp-image-591634" /> <p>The biggest winner of the Python web frameworks was FastAPI, which jumped from 29% to 38% (a 30% increase). While all of the major frameworks grew year over year, FastAPI&#8217;s nearly 30% jump is impressive. I can only speculate why this is. To me, I think this jump in Python for web is likely partially due to a large number of newcomers to the Python space. Many of these are on the ML/AI/data science side of things, and those folks often don&#8217;t have years of baked-in experience and history with Flask or Django. They are likely choosing the hottest of the Python web frameworks, which today looks like it’s FastAPI. There are many examples of people hosting their ML models behind FastAPI APIs.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-19.png" alt="Line chart of Python web frameworks 2021–2024: FastAPI rose to 38%, Django declined to 35%, Flask declined to 34%." class="wp-image-591645" /> <p>The trend towards async-friendly Python web frameworks has been continuing as well. Over at <em>Talk Python</em>, I<a href="https://talkpython.fm/blog/posts/talk-python-rewritten-in-quart-async-flask/" target="_blank" rel="noopener"> rewrote our Python web app in async Flask</a> (roughly 10,000 lines of Python). Django has been steadily adding async features, and its async support is nearly complete. Though today, at version 5.2, its DB layer needs a bit more work, as the team says: &#8220;We&#8217;re still working on async support for the ORM and other parts of Django.&#8221;</p> <h3 class="wp-block-heading">Python web servers shift toward async and Rust-based tools</h3> <p>It&#8217;s worth a brief mention that the production app servers hosting Python web apps and APIs are changing too. Anecdotally, I see two forces at play here: 1) The move to async frameworks necessitates app servers that support <a href="https://asgi.readthedocs.io/en/latest/specs/main.html" target="_blank" rel="noopener">ASGI</a>, not just <a href="https://peps.python.org/pep-3333/" target="_blank" rel="noopener">WSGI</a> and 2) Rust is becoming more and more central to the fast execution of Python code (we’ll dive into that shortly).</p> <p>The biggest loss in this space last year was the complete demise of uWSGI. We even did a <em>Python Bytes</em> podcast entitled <em>We Must Replace uWSGI With Something Else</em> examining this situation in detail.&nbsp;</p> <p>We also saw Gunicorn handling less of the async workload with async-native servers such as<a href="https://www.uvicorn.org" target="_blank" rel="noopener"> uvicorn</a> and<a href="https://github.com/pgjones/hypercorn" target="_blank" rel="noopener"> Hypercorn</a>, which are able to<a href="https://github.com/encode/uvicorn/pull/2183" target="_blank" rel="noopener"> operate independently</a>. Newcomer servers, based on Rust, such as <a href="https://github.com/emmett-framework/granian" target="_blank" rel="noopener">Granian</a>, have gained a solid following as well.</p> <h3 class="wp-block-heading">Rust is how we speed up Python now</h3> <p>Over the past couple of years, Rust has become Python&#8217;s performance co-pilot. The Python Language Summit of 2025 <a href="https://pyfound.blogspot.com/2025/06/python-language-summit-2025-what-do-core-developers-want-from-rust.html" target="_blank" rel="noopener">revealed</a> that &#8220;Somewhere between one-quarter and one-third of all native code being uploaded to PyPI for new projects uses Rust&#8221;, indicating that &#8220;people are choosing to start new projects using Rust&#8221;.</p> <p>Looking into the survey results, we see that Rust usage grew from 27% to 33% for binary extensions to Python packages. This reflects a growing trend toward using Rust for systems-level programming and for native extensions that accelerate Python code. </p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-20.png" alt="Bar chart comparing 2023 vs 2024: 55% use C++, 45% use C, 33% use Rust for Python binary modules." class="wp-image-591657" /> <p>We see this in the ecosystem with the success of Polars for data science and Pydantic for pretty much all disciplines. We are even seeing that for Python app servers such as the newer Granian.</p> <h3 class="wp-block-heading">Typed Python is getting better tooling</h3> <p>Another key trend this year is static type checking in Python. You&#8217;ve probably seen Python type information in function definitions such as: </p> <p><code>def add(x: int, y: int) -&gt; int: ...&nbsp;</code></p> <p>These have been in Python for a while now. Yet, there is a renewed effort to make typed Python more common and more forgiving. We&#8217;ve had tools such as mypy since typing&#8217;s early days, but the goal there was more along the lines of whole program consistency. In just the past few months, we have seen two new high-performance typing tools released:</p> <ul> <li><a href="https://github.com/astral-sh/ty" target="_blank" rel="noopener">ty</a> from Astral – an extremely fast Python type checker and language server written in Rust.</li> <li><a href="https://pyrefly.org" target="_blank" rel="noopener">Pyrefly</a> from Meta – a faster Python type checker written in Rust.</li> </ul> <p>ty and Pyrefly provide extremely fast static type checking and language server protocols (LSPs). These next‑generation type checkers make it easier for developers to adopt type hints and enforce code quality.</p> <p>Notice anything similar? They are both written in Rust, backing up the previous claim that &#8220;Rust has become Python&#8217;s performance co-pilot&#8221;.</p> <p>By the way, <a href="https://talkpython.fm/episodes/show/506/ty-astrals-new-type-checker-formerly-red-knot" target="_blank" rel="noopener">I interviewed the team</a> behind ty when it was announced a few weeks ago if you want to dive deeper into that project.</p> <h3 class="wp-block-heading">Code and docs make up most open-source contributions</h3> <p>There are many different and unique ways to contribute to open source. Probably the first thing that comes to most people&#8217;s minds when they think of a contributor is someone who writes code and adds a new feature to that project. However, there are less visible but important ways to make a contribution, such as triaging issues and reviewing pull requests.</p> <p>So, what portion of the community has contributed to open source, and in which ways have they done so?</p> <p>The survey tells us that one-third of devs contributed to open source. This manifests primarily as code and documentation/tutorial additions.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-21.png" alt="Bar chart of open-source contributions in 2025: 78% code, 40% documentation, 35% governance, 33% tests." class="wp-image-591670" /> <h3 class="wp-block-heading">Python documentation is the top resource for developers</h3> <p>Where do you typically learn as a developer or data scientist? Respondents said that docs are #1. There are many ways to learn languages and libraries, but people like docs best. This is good news for open-source maintainers. This means that the effort put into documentation (and embedded tutorials) is well spent. It&#8217;s a clear and straightforward way to improve users&#8217; experience with your project.</p> <p>Moreover, this lines up with <a href="https://talkpython.fm/episodes/show/504/developer-trends-in-2025" target="_blank" rel="noopener"><em>Developer Trends in 2025</em></a>, a podcast panel episode I did with experienced Python developers, including JetBrains&#8217; own Paul Everitt. The panelists all agree that docs are #1, though the survey ranked YouTube much higher than the panelists, at 51%. Remember, our community has an average of 1–2 years of experience, and 45% of them are younger than 30 years old.</p> <p>Respondents said that documentation and embedded tutorials are the top learning resources. Other sources, such as YouTube tutorials, online courses, and AI-based code generation tools, are also gaining popularity. In fact, the survey shows that AI tools as a learning source increased from 19 % to 27 % (up 42% year over year)!</p> <h3 class="wp-block-heading">Postgres reigns as the database king for Pythonistas</h3> <p>When asked which database (if any) respondents chose, they overwhelmingly said PostgreSQL. This relational database management system (RDBMS) grew from 43 % to 49 %. That&#8217;s +14% year over year, which is remarkable for a 28-year-old open-source project.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-22.png" alt="Bar chart of databases used in 2023 vs 2024: PostgreSQL grew to 49%, SQLite 37%, MySQL 31%." class="wp-image-591682" /> <p>One interesting detail here, beyond Postgres being used a lot, is that every single database in the top six, including MySQL and SQLite, grew in usage year over year. This is likely another indicator that web development itself is growing again, as discussed above.</p> <h2 class="wp-block-heading">Forward-looking trends</h2> <h3 class="wp-block-heading">Agentic AI will be wild</h3> <p>My first forward-looking trend is that agentic AI will be a game-changer for coding. Agentic AI is often cited as a tool of the much maligned and loved<a href="https://www.youtube.com/watch?v=_2C2CNmK7dQ" target="_blank" rel="noopener"> vibe coding</a>. However, <strong>vibe coding obscures the fact that agentic AI tools are remarkably productive when used alongside a talented engineer or data scientist</strong>.</p> <p>Surveys outside the PSF survey indicate that about 70% of developers were using or planning to use AI coding tools in 2023, and by 2024, around 44% of professional developers use them daily.</p> <p>JetBrains’ <em>State of Developer Ecosystem 2023</em> report noted that within a couple of years, &#8220;AI-based code generation tools went from interesting research to an important part of many developers&#8217; toolboxes&#8221;. Jump ahead to 2025, according to the <em>State of Developer Ecosystem 2025</em> survey, <strong>nearly half of the respondents (49%) plan to try AI coding agents in the coming year</strong>.</p> <img src="https://blog.jetbrains.com/wp-content/uploads/2025/08/image-23.png" alt="Bar chart showing adoption of AI coding agents in 2025: 49% very likely, 20% somewhat likely, 11% already using." class="wp-image-591695" /> <p>Program managers at major tech companies have stated that they almost cannot hire developers who don&#8217;t embrace agentic AI. The productive delta between those using it and those who avoid it is simply too great (estimated at about 30% greater productivity with AI).</p> <h3 class="wp-block-heading"><code>Async</code>, <code>await</code>, and threading are becoming core to Python</h3> <p>The future will be abuzz with concurrency and Python. We&#8217;ve already discussed how the Python web frameworks and app servers are all moving towards asynchronous execution, but this only represents one part of a powerful trend.</p> <p>Python 3.14 will be the first version of Python to completely support free-threaded Python. Free-threaded Python, which is a version of the Python runtime that does not use the GIL, the global interpreter lock, was first added as an experiment to CPython 3.13.</p> <p>Just last week, the steering council and core developers officially accepted this as a permanent part of the language and runtime. This will have far-reaching effects. Developers and data scientists will have to think more carefully about threaded code with locks, race conditions, and the performance benefits that come with it. Package maintainers, especially those with native code extensions, may have to rewrite some of their code to support free-threaded Python so they themselves do not enter race conditions and deadlocks.</p> <p>There is a massive upside to this as well. I&#8217;m currently writing this on the cheapest Apple Mac Mini M4. This computer comes with 10 CPU cores. That means until this change manifests in Python, the maximum performance I can get out of a single Python process is 10% of what my machine is actually capable of. Once free-threaded Python is fully part of the ecosystem, I should get much closer to maximum capacity with a standard Python program using threading and the async and await keywords.</p> <p><code>Async</code> and <code>await</code> keywords are not just tools for web developers who want to write more concurrent code.&nbsp; It&#8217;s appearing in more and more locations. One such tool that I recently came across is <a href="https://temporal.io" target="_blank" rel="noopener">Temporal</a>. This program leverages the asyncio event loop but replaces the standard clever threading tricks with durable machine-spanning execution. You might simply await some action, and behind the scenes, you get durable execution that survives machine restarts. So understanding <code>async</code> and <code>await</code> is going to be increasingly important as more tools make interesting use of it, as Temporal did.</p> <p>I see parallels here of how Pydantic made a lot of people more interested in Python typing than they otherwise would have been.</p> <h3 class="wp-block-heading">Python GUIs and mobile are rising</h3> <p>My last forward-looking trend is that Python GUIs and Python on mobile are rising. When we think of native apps on iOS and Android, we can only dream of using Python to build them someday soon.</p> <p>At the 2025 Python Language Summit, Russell Keith-Magee presented his work on making iOS and Android Tier 3-supported platforms for CPython. This has been laid out in PEP 730 and PEP 738. This is a necessary but not sufficient condition for allowing us to write true native apps that ship to the app stores using Python.</p> <p>More generally, there have been some interesting ideas and new takes on UIs for Python. We had Jeremy Howard from fast.ai introduce <a href="https://www.fastht.ml" target="_blank" rel="noopener">FastHTML</a>, which allows us to write modern web applications in pure Python. <a href="https://nicegui.io" target="_blank" rel="noopener">NiceGUI</a> has been coming on strong as an excellent way to write web apps and PWAs in pure Python.</p> <p>I expect these changes, especially the mobile ones, to unlock powerful use cases that we&#8217;ll be talking about for years to come.</p> <h2 class="wp-block-heading">Actionable ideas</h2> <p>You&#8217;ve seen the results, my interpretations, and predictions. So what should you do about them? Of course, nothing is required of you, but I am closing out this article with some actionable ideas to help you take advantage of these technological and open-source waves.</p> <p>Here are six actionable ideas you can put into practice after reading this article. Pick your favorite one that you&#8217;re not yet leveraging and see if it can help you thrive further in the Python space.</p> <h3 class="wp-block-heading">Action 1: Learn uv</h3> <p><a href="https://astral.sh/uv/" target="_blank" rel="noopener">uv</a>, the incredible package and Python management tool jumped incredibly from 0% to 11% the year it was introduced (and that growth has demonstrably continued to surge in 2025). This Rust-based tool unifies capabilities from many of the most important ones you may have previously heard of and does so with performance and incredible features.</p> <p>Do you need Python on the machine? Simply <code>RUN uv venv .venv</code>, and you have both installed the latest stable release and created a virtual environment. That&#8217;s just the beginning. If you want the full story, I did <a href="https://talkpython.fm/episodes/show/453/uv-the-next-evolution-in-python-packages" target="_blank" rel="noopener">an interview with Charlie Marsh</a> about the second generation of uv over on <em>Talk Python</em>.</p> <p>If you decide to install uv, be sure to <a href="https://github.com/astral-sh/uv?tab=readme-ov-file#installation" target="_blank" rel="noopener">use their standalone installers</a>. It allows uv to manage itself and get better over time.</p> <h3 class="wp-block-heading">Action 2: Use the latest Python</h3> <p>We saw that 83% of respondents are not using the latest version of Python. Don&#8217;t be one of them. Use a virtual environment or use a container and install the latest version of Python. The quickest and easiest way these days is to use uv, as it won&#8217;t affect system Python and other configurations (see action 1!).</p> <p>If you deploy or develop in Docker containers, all you need to do is set up the latest version of Python 3.13 and run these two lines:</p> <pre class="EnlighterJSRAW">RUN curl -LsSf https://astral.sh/uv/install.sh | sh RUN uv venv --python 3.13 /venv</pre> <p>If you develop locally in virtual environments (as I do), just remove the <code>RUN</code> keyword and use uv to create that environment. Of course, update the version number as new major versions of Python are released.</p> <p>By taking this action, you will be able to take advantage of the full potential of modern Python, from the performance benefits to the language features.</p> <h3 class="wp-block-heading">Action 3: Learn agentic AI</h3> <p>If you&#8217;re one of the people who have not yet tried agentic AI, you owe it to yourself to give it a look. Agentic AI uses large language models (LLMs) such as GPT‑4, ChatGPT, or models available via Hugging Face to perform tasks autonomously.</p> <p>I understand why people avoid using AI and LLMs. For one thing, there&#8217;s dubious legality around copyrights. The environmental harms can be real, and the threat to developers&#8217; jobs and autonomy is not to be overlooked. But using top-tier models for <em>agentic</em> AI, not just chatbots, allows you to be tremendously productive.</p> <p>I&#8217;m not recommending vibe coding. But have you ever wished for a library or package to exist, or maybe a CLI tool to automate some simple part of your job? Give that task to an agentic AI, and you won&#8217;t be taking on technical debt to your main application and some part of your day. Your productivity just got way better.</p> <p>The other mistake people make here is to give it a try using the cheapest or free models. When they don&#8217;t work that great, people hold that up as evidence and say, “See, it&#8217;s not that helpful. It just makes up stuff and gets things wrong.” Make sure you choose the best possible model that you can, and if you want to give it a genuine look, spend $10 or $20 for a month to see what&#8217;s actually possible.</p> <p>JetBrains recently released <a href="https://www.jetbrains.com/junie/" target="_blank" rel="noopener">Junie, an agentic coding assistant for their IDEs</a>. If you&#8217;re using one of them, definitely give it a look.</p> <h3 class="wp-block-heading">Action 4: Learn to read basic Rust</h3> <p>Python developers should consider learning the basics of Rust, not to replace Python, but to complement it. As I discussed in our analysis, Rust is becoming increasingly important in the most significant portions of the Python ecosystem. I definitely don&#8217;t recommend that you become a Rust developer instead of a Pythonista, but being able to read basic Rust so that you understand what the libraries you&#8217;re consuming are doing will be a good skill to have.</p> <h3 class="wp-block-heading">Action 5: Invest in understanding threading</h3> <p>Python developers have worked mainly outside the realm of threading and parallel programming. In Python 3.6, the amazing async and await keywords were added to the language. However, they only applied to I/O bound concurrency. For example, if I&#8217;m calling a web service, I might use the HTTPX library and await that call. This type of concurrency mostly avoids race conditions and that sort of thing.</p> <p>Now, true parallel threading is coming for Python. With PEP 703 officially and fully accepted as part of Python in 3.14, we&#8217;ll need to understand how true threading works. This will involve understanding locks, semaphores, and mutexes.</p> <p>It&#8217;s going to be a challenge, but it is also a great opportunity to dramatically increase Python&#8217;s performance.</p> <p>At the 2025 Python Language Summit, almost one-third of the talks dealt with concurrency and threading in one form or another. This is certainly a forward-looking indicator of what&#8217;s to come.</p> <p>Not every program you write will involve concurrency or threading, but they will be omnipresent enough that having a working understanding will be important. I have <a href="https://training.talkpython.fm/courses/python-concurrency-deep-dive" target="_blank" rel="noopener">a course I wrote about async in Python</a> if you&#8217;re interested in learning more about it. Plus, JetBrains&#8217; own Cheuk Ting Ho wrote an excellent article entitled <a href="https://blog.jetbrains.com/pycharm/2025/06/concurrency-in-async-await-and-threading/"><em>Faster Python: Concurrency in async/await and threading</em></a>, which is worth a read.</p> <h3 class="wp-block-heading">Action 6: Remember the newbies</h3> <p>My final action to you is to keep things accessible for beginners – every time you build or share. Half of the Python developer base has been using Python for less than two years, and most of them have been programming in any format for less than two years. That is still remarkable to me.</p> <p>So, as you go out into the world to speak, write, or create packages, libraries, and tools, remember that you should not assume years of communal knowledge about working with multiple Python files, virtual environments, pinning dependencies, and much more.</p> <p>Interested in learning more? <a href="https://lp.jetbrains.com/python-developers-survey-2024/" target="_blank" rel="noopener">Check out the full <em>Python Developers Survey</em> <em>Results</em> here</a>.</p> <h2 class="wp-block-heading">Start developing with PyCharm</h2> <p>PyCharm provides everything you need for data science, ML/AI workflows, and web development right out of the box – all in one powerful IDE.</p> <div class="buttons"> <div class="buttons__row"> <a href="https://www.jetbrains.com/pycharm/download/" class="btn" target="" rel="noopener">Try PyCharm for free</a> </div> </div> <h2 class="wp-block-heading" id="author">About the author</h2> <div class="about-author "> <div class="about-author__box"> <div class="row"> <div class="about-author__box-img"> <img src="https://blog.jetbrains.com/wp-content/uploads/2024/11/michael-kennedy.jpg" alt="Michael Kennedy" /> </div> <div class="about-author__box-text"> <h4>Michael Kennedy</h4> <p><span>Michael is the founder of Talk Python and a PSF Fellow. Talk Python is a podcast and course platform that has been exploring the Python ecosystem for over 10 years. At his core, Michael is a web and API developer.</span></p> </div> </div> </div> </div> Tue, 20 Jan 2026 13:40:46 +0000 PyBites: “I’m worried about layoffs” https://pybit.es/articles/dont-get-comfortable/ https://pybit.es/articles/dont-get-comfortable/ <p class="">I’ve had some challenging conversations this week.</p> <p class="">Lately, my calendar has been filled with calls from developers reaching out for advice because layoffs were just announced at their company.</p> <p class="">Having been in their shoes myself, I could really empathise with their anxiety.</p> <p class="">The thing is though, when we&#8217;d dig into&nbsp;<em>why</em>&nbsp;there was such anxiety, a common confession surfaced. It often boiled down to something like this:</p> <p class=""><em>&#8220;I got comfortable. I stopped learning. I haven&#8217;t touched a new framework or built anything serious in two years because things were okay.&#8221;</em></p> <p class="">They were enjoying &#8220;Peace Time.&#8221;</p> <p class="">I like to think of life in two modes: <strong>Crisis Mode</strong> and <strong>Calm Mode</strong>.</p> <ul class="wp-block-list"> <li class=""><strong>Crisis Mode</strong>: Life is chaotic. The house is on fire. You just lost your job, or your project was cancelled. Stress is high, money is tight, and uncertainty is the only certainty.</li> <li class=""><strong>Calm Mode</strong>: Life is stable. The pay cheque hits every few weeks. The boss is happy. The weekends are free.</li> </ul> <p class="">The deadly mistake most developers make is waiting for War Mode before they start training.</p> <p class="">They wait until the severance package arrives to finally decide,&nbsp;<em>&#8220;Okay, time to really learn Python/FastAPI/Cloud.&#8221;</em></p> <p class="">It&#8217;s a recipe for disaster. Trying to learn complex engineering skills when you&#8217;re terrified about paying the mortgage is almost impossible. You&#8217;re just too stressed. You can’t focus which means you can&#8217;t dive into the deep building necessary to learn.</p> <p class=""><strong>You absolutely have to train and skill up during Peace Time.</strong></p> <p class="">When things are boring and stable, that&#8217;s the exact moment you should be aggressive about your growth.</p> <p class="">That&#8217;s when you have the mental bandwidth to struggle through a hard coding problem without the threat of redundancy hanging over your head. It&#8217;s the perfect time to sharpen the saw.</p> <p class="">If you&#8217;re currently in a stable job, you&#8217;re in Calm Mode. Don&#8217;t waste it.</p> <p class=""><strong>Here&#8217;s what you need to do:</strong>&nbsp;</p> <ul class="wp-block-list"> <li class="">Look at your schedule this week. Identify the &#8220;comfort blocks&#8221; (the times you&#8217;re coasting because you aren&#8217;t currently threatened).</li> <li class="">Take 5 hours of that time this week and dedicate it to <strong>growth</strong>. This is your Crisis Mode preparation. Build something that pushes you outside of your comfort zone. Go and learn the tool that intimidates you the most!</li> <li class="">If crisis hits six months from now, you won’t be the one panicking. You’ll be the one who is ready.</li> </ul> <p class="">Does this resonate with you? Are you guilty of coasting during Peace Time?</p> <p class="">I know I&#8217;ve been there! (I often think back and wonder where I&#8217;d be now had I not spent so much time coasting through my life&#8217;s peaceful periods!)</p> <p class="">Let&#8217;s get you back on track. Fill out this <strong>Portfolio Assessment</strong> form we&#8217;ve created to help you formulate your goals and ideas. We read every submission, <a href="https://form.jotform.com/233191638982062" target="_blank" rel="noopener">Pybites Portfolio Assessment Tool</a>.</p> <p class="">Julian</p> <p class=""></p> <p class=""><em>This note was originally sent to our email list. Join here: <a href="https://pybit.es/newsletter">https://pybit.es/newsletter</a></em></p> <p class=""><em>Edit: Softened language from &#8220;War&#8221; and &#8220;Peace&#8221; mode to &#8220;Crisis&#8221; and &#8220;Calm&#8221; mode. Special thanks to our community member, Dean, for the suggestion.</em></p> Tue, 20 Jan 2026 00:15:39 +0000 Seth Michael Larson: “urllib3 in 2025” available on Illia Volochii’s new blog https://sethmlarson.dev/urllib3-in-2025-available-on-illia-volochiis-blog?utm_campaign=rss https://sethmlarson.dev/urllib3-in-2025-available-on-illia-volochiis-blog?utm_campaign=rss <p><a href="https://volochii.dev/blog/urllib3-in-2025/">2025 was a big year for urllib3</a> and I want you to read about it! In case you missed it, this year I <a href="https://github.com/urllib3/urllib3/issues/3629">passed the baton of “lead maintainer”</a> to <a href="https://volochii.dev">Illia Volochii</a> who has a <a href="https://volochii.dev">new website and blog</a>. <a href="https://quentin.pradet.me/">Quentin Pradet</a> and I continue to be maintainers to the project.</p> <!-- more --> <p>If you are reading my blog to keep up-to-date on the latest in urllib3 I highly recommend following both <a href="https://volochii.dev/blog/">Illia</a> and <a href="https://quentin.pradet.me/blog/">Quentin's</a> blogs, as I will likely publish less and less about urllib3 here going forward. The leadership change was a part of <a href="https://sethmlarson.dev/observing-volunteer-amnesty-day">my observation</a> of <a href="https://www.volunteeramnestyday.net/">Volunteer Responsibility Amnesty Day</a> in the spring of last year.</p> <p>This isn't goodbye, but I would like to take a moment to be reflective. Being a contributor to urllib3 from 2016 to now has had an incredibly positive impact on my life and livelihood. I am forever grateful for my early open source mentors: <a href="https://lukasa.co.uk/">Cory Benfield</a> and <a href="https://blog.thea.codes/">Thea "Stargirl" Flowers</a>, who were urllib3 leads before me. I've also met <em>so many new friends</em> from my deep involvement with Python open source, it really is an amazing network of people! 💜</p> <p>urllib3 was <a href="https://sethmlarson.dev/review-of-2019-for-urllib3#grants-and-sponsorships">my first opportunity to work on open source full-time</a> for a few weeks on a grant about improving security. urllib3 became an early partner with <a href="https://tidelift.com">Tidelift</a>, leading me to investigate and write about open source security practices and policies for Python projects. My positions at Elastic and the Python Software Foundation were likely influenced by my involvement with urllib3 and other open source Python projects.</p> <p>In short: contributing to open source is an amazing and potentially life-changing opportunity.</p> <br /><hr /><p>Thanks for keeping RSS alive! ♥</p> Tue, 20 Jan 2026 00:00:00 +0000 Kevin Renskers: Django 6.0 Tasks: a framework without a worker https://www.loopwerk.io/articles/2026/django-tasks-review/ https://www.loopwerk.io/articles/2026/django-tasks-review/ <p>Background tasks have always existed in Django projects. They just never existed in Django itself.</p> <p>For a long time, Django focused almost exclusively on the request/response cycle. Anything that happened outside that flow, such as sending emails, running cleanups, or processing uploads, was treated as an external concern. The community filled that gap with tools like Celery, RQ, and cron-based setups.</p> <p>That approach worked but it was never ideal. Background tasks are not an edge case. They are a fundamental part of almost every non-trivial web application. Leaving this unavoidable slice entirely to third-party tooling meant that every serious Django project had to make its own choices, each with its own trade-offs, infrastructure requirements, and failure modes. It’s one more thing that makes Django complex to deploy.</p> <p>Django 6.0 is the first release that acknowledges this problem at the framework level by introducing a built-in tasks framework. That alone makes it a significant release. But my question is whether it actually went far enough.</p> <h2><a name="what-django-6-0-adds"></a>What Django 6.0 adds</h2> <p>Django 6.0 introduces a brand new tasks framework. It’s not a queue, not a worker system, and not a scheduler. It only defines background work in a first-party, Django-native way, and provides hooks for someone else to execute that work.</p> <p>As an abstraction, this is clean and sensible. It gives Django a shared language for background execution and removes a long-standing blind spot in the framework. But it also stops there.</p> <p>Django’s task system only supports one-off execution. There is no notion of scheduling, recurrence, retries, persistence, or guarantees. There is no worker process and no production-ready backend. That limitation would be easier to accept if one-off tasks were the primary use case for background work, but they are not. In real applications, background work is usually time-based, repeatable, and failure-prone. Tasks need to run later, run again, or keep retrying until they succeed.</p> <h2><a name="a-missed-opportunity"></a>A missed opportunity</h2> <p>What makes this particularly frustrating is that Django had a clear opportunity to do more.</p> <p><a href="https://github.com/django/deps/blob/main/accepted/0014-background-workers.rst" target="_blank" rel="nofollow">DEP 14</a> explicitly talks about a database backend, deferring tasks to run at a specific time in the future, and a new email backend that offloads work to the background. None of that has made it into Django itself yet. Why wasn’t the database worker from <a href="https://github.com/RealOrangeOne/django-tasks" target="_blank" rel="nofollow">django-tasks</a> at least added to Django, or something equivalent? This would have covered a large percentage of real-world use cases with minimal operational complexity.</p> <p>Instead, we got an abstraction without an implementation.</p> <p>I understand that building features takes time. What I struggle to understand is why shipping such a limited framework was preferred over waiting longer and delivering a more complete story. You only get to introduce a feature once, and in its current form the tasks framework feels more confusing than helpful for newcomers. The <a href="https://docs.djangoproject.com/en/6.0/topics/tasks/" target="_blank" rel="nofollow">official documentation</a> even acknowledges this incompleteness, yet offers little guidance beyond a link to the <a href="https://www.djangoproject.com/community/ecosystem/" target="_blank" rel="nofollow">Community Ecosystem</a> page. Developers are left guessing whether they are missing an intended setup or whether the feature is simply unfinished.</p> <h2><a name="what-django-should-focus-on-next"></a>What Django should focus on next</h2> <p>Currently, with Django 6.0, serious background processing still requires third-party tools for scheduling, retries, delayed execution, monitoring, and scaling workers. That was true before, and it remains true now. Even if one-off fire-and-forget tasks are all you need, you still need to install a third party package to get a database backend and worker.</p> <p>DEP 14 also explicitly states that the intention is <em>not</em> to build a replacement for Celery or RQ, because “that is a complex and nuanced undertaking”. I think this is a mistake. The vast majority of Django applications need a robust task framework. A database-backed worker that handles delays, retries, and basic scheduling would cover most real-world needs without any of Celery’s operational complexity. Django positions itself as a batteries-included framework, and background tasks are not an advanced feature. They are basic application infrastructure.</p> <p>Otherwise, what is the point of Django’s Task framework? Let’s assume that it’ll get a production-ready backend and worker soon. What then? It can still only run one-off tasks. As soon as you need to schedule tasks, you still need to reach for a third-party solution. I think it should have a first-party answer for the most common cases, even if it’s complex.</p> <h2><a name="conclusion"></a>Conclusion</h2> <p>Django 6.0’s task system is an important acknowledgement of a long-standing gap in the framework. It introduces a clean abstraction and finally gives background work a place in Django itself. This is good! But by limiting that abstraction to one-off tasks and leaving execution entirely undefined, Django delivers the least interesting part of the solution.</p> <p>If I sound disappointed, it’s because I am. I just don’t understand the point of adding such a bare-bones Task framework when the reality is that most real-world projects still need to use third-party packages. But the foundation is there now. I hope that Django builds something on top that can replace <a href="https://github.com/jcass77/django-apscheduler" target="_blank" rel="nofollow">django-apscheduler</a>, <a href="https://github.com/rq/django-rq" target="_blank" rel="nofollow">django-rq</a>, and <a href="https://github.com/celery/django-celery" target="_blank" rel="nofollow">django-celery</a>. I believe that it can, and that it should.</p> Mon, 19 Jan 2026 20:00:01 +0000 Talk Python Blog: Announcing Talk Python AI Integrations https://talkpython.fm/blog/posts/announcing-talk-python-ai-integrations/ https://talkpython.fm/blog/posts/announcing-talk-python-ai-integrations/ <p>We&rsquo;ve just added two new and exciting features to the Talk Python To Me website to allow deeper and richer integration with AI and LLMs.</p> <ol> <li>A full MCP server at <a href="https://talkpython.fm/api/mcp/docs">talkpython.fm/api/mcp/docs</a></li> <li>A LLMs summary to guide non-MCP use-cases: <a href="https://talkpython.fm/llms.txt">talkpython.fm/llms.txt</a></li> </ol> <h2 id="the-mcp-server">The MCP Server</h2> <p>New to the idea of an MCP server? MCP (Model Context Protocol) servers are lightweight services that expose data and functionality to AI assistants through a standardized interface, allowing models like Claude to query external systems and access real-time information beyond their training data. <strong>The Talk Python To Me MCP server acts as a bridge between AI conversations and the podcast&rsquo;s extensive catalog</strong>. This enables you to search episodes, look up guest appearances, retrieve transcripts, and explore course content directly within your AI workflow, making research and content discovery seamless.</p> Mon, 19 Jan 2026 17:49:43 +0000 Mike Driscoll: New Book: Vibe Coding Video Games with Python https://www.blog.pythonlibrary.org/2026/01/19/new-book-vibe-coding-video-games-with-python/ https://www.blog.pythonlibrary.org/2026/01/19/new-book-vibe-coding-video-games-with-python/ <p>My latest book, <strong>Vibe Coding Video Games with Python,</strong> is now available as an eBook. The paperback will be coming soon, hopefully by mid-February at the latest. The book is around 183 pages in length and is 6&#215;9” in size.</p> <p><img class="aligncenter size-medium wp-image-12744" src="https://www.blog.pythonlibrary.org/wp-content/uploads/2026/01/Vibe_coding_video_games600-188x300.jpg" alt="Vibe Coding Video Games with Python" width="188" height="300" /></p> <p>In this book, you will learn how to use artificial intelligence to create mini-games. You will attempt to recreate the look and feel of various classic video games. The intention is not to violate copyright or anything of the sort, but instead to learn the limitations and the power of AI.</p> <p>Instead, you will simply be learning about whether or not you can use AI to help you know how to create video games. Can you do it with no previous knowledge, as the AI proponents say? Is it really possible to create something just by writing out questions to the ether?</p> <p>You will use various large language models (LLMs), such as Google Gemini, Grok, Mistral, and CoPilot, to create these games. You will discover the differences and similarities between these tools. You may be surprised to find that some tools give much more context than others.</p> <p>AI is certainly not a cure-all and is far from perfect. You will quickly discover AI’s limitations and learn some strategies for solving those kinds of issues.</p> <h3 class="header-anchor-post"><strong>What You’ll Learn</strong></h3> <p>You’ll be creating “clones” of some popular games. However, these games will only be the first level and may or may not be fully functional.</p> <ul> <li>Chapter 1 – The Snake Game</li> <li>Chapter 2 – Pong Clone</li> <li>Chapter 3 – Frogger Clone</li> <li>Chapter 4 – Space Invaders Clone</li> <li>Chapter 5 – Minesweeper Clone</li> <li>Chapter 6 – Luna Lander Clone</li> <li>Chapter 7 – Asteroids Clone</li> <li>Chapter 8 – Tic-Tac-Toe</li> <li>Chapter 9 – Pole Position Clone</li> <li>Chapter 10 – Connect Four</li> <li>Chapter 11 – Adding Sprites</li> </ul> <h3 class="header-anchor-post">Where to Purchase</h3> <div class="pencraft pc-display-flex pc-alignItems-center pc-position-absolute pc-reset header-anchor-parent"> <div class="pencraft pc-display-contents pc-reset pubTheme-yiXxQA"><span>You can get </span><strong>Vibe Coding Video Games with Python</strong><span> at the following websites:</span></div> </div> <ul> <li><a href="https://leanpub.com/vibegames" rel="">Leanpub</a></li> <li><a href="https://driscollis.gumroad.com/l/vibegames" rel="">Gumroad</a></li> <li><a href="https://amzn.to/4byWKaf" rel="">Amazon Kindle</a></li> </ul> <p>The post <a href="https://www.blog.pythonlibrary.org/2026/01/19/new-book-vibe-coding-video-games-with-python/">New Book: Vibe Coding Video Games with Python</a> appeared first on <a href="https://www.blog.pythonlibrary.org">Mouse Vs Python</a>.</p> Mon, 19 Jan 2026 14:25:39 +0000