<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: gil</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/gil.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2025-10-08T18:36:33+00:00</updated><author><name>Simon Willison</name></author><entry><title>Python 3.14 Is Here. How Fast Is It?</title><link href="https://simonwillison.net/2025/Oct/8/python-314-is-here-how-fast-is-it/#atom-tag" rel="alternate"/><published>2025-10-08T18:36:33+00:00</published><updated>2025-10-08T18:36:33+00:00</updated><id>https://simonwillison.net/2025/Oct/8/python-314-is-here-how-fast-is-it/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.miguelgrinberg.com/post/python-3-14-is-here-how-fast-is-it"&gt;Python 3.14 Is Here. How Fast Is It?&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Miguel Grinberg uses some basic benchmarks (like &lt;code&gt;fib(40)&lt;/code&gt;) to test the new Python 3.14 on Linux and macOS and finds some substantial speedups over Python 3.13 - around 27% faster.&lt;/p&gt;
&lt;p&gt;The optional JIT didn't make a meaningful difference to his benchmarks. On a threaded benchmark he got 3.09x speedup with 4 threads using the free threading build - for Python 3.13 the free threading build only provided a 2.2x improvement.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/p0iw9e/python_3_14_is_here_how_fast_is_it"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/performance"&gt;performance&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="performance"/><category term="python"/></entry><entry><title>Python 3.14</title><link href="https://simonwillison.net/2025/Oct/8/python-314/#atom-tag" rel="alternate"/><published>2025-10-08T04:10:06+00:00</published><updated>2025-10-08T04:10:06+00:00</updated><id>https://simonwillison.net/2025/Oct/8/python-314/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.python.org/downloads/release/python-3140/"&gt;Python 3.14&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
This year's major Python version, Python 3.14, just made its first stable release!&lt;/p&gt;
&lt;p&gt;As usual the &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html"&gt;what's new in Python 3.14&lt;/a&gt; document is the best place to get familiar with the new release:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The biggest changes include &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-template-string-literals"&gt;template string literals&lt;/a&gt;, &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-deferred-annotations"&gt;deferred evaluation of annotations&lt;/a&gt;, and support for &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-multiple-interpreters"&gt;subinterpreters&lt;/a&gt; in the standard library.&lt;/p&gt;
&lt;p&gt;The library changes include significantly improved capabilities for &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-asyncio-introspection"&gt;introspection in asyncio&lt;/a&gt;, &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-zstandard"&gt;support for Zstandard&lt;/a&gt; via a new &lt;a href="https://docs.python.org/3.14/library/compression.zstd.html#module-compression.zstd"&gt;compression.zstd&lt;/a&gt; module, syntax highlighting in the REPL, as well as the usual deprecations and removals, and improvements in user-friendliness and correctness.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Subinterpreters look particularly interesting as a way to use multiple CPU cores to run Python code despite the continued existence of the GIL. If you're feeling brave and &lt;a href="https://hugovk.github.io/free-threaded-wheels/"&gt;your dependencies cooperate&lt;/a&gt; you can also use the free-threaded build of Python 3.14 - &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-free-threaded-now-supported"&gt;now officially supported&lt;/a&gt; - to skip the GIL entirely.&lt;/p&gt;
&lt;p&gt;A new major Python release means an older release hits the &lt;a href="https://devguide.python.org/versions/"&gt;end of its support lifecycle&lt;/a&gt; - in this case that's Python 3.9. If you maintain open source libraries that target every supported Python versions (as I do) this means features introduced in Python 3.10 can now be depended on! &lt;a href="https://docs.python.org/3.14/whatsnew/3.10.html"&gt;What's new in Python 3.10&lt;/a&gt; lists those - I'm most excited by &lt;a href="https://docs.python.org/3.14/whatsnew/3.10.html#pep-634-structural-pattern-matching"&gt;structured pattern matching&lt;/a&gt; (the &lt;code&gt;match/case&lt;/code&gt; statement) and the &lt;a href="https://docs.python.org/3.14/whatsnew/3.10.html#pep-604-new-type-union-operator"&gt;union type operator&lt;/a&gt;, allowing &lt;code&gt;int | float | None&lt;/code&gt; as a type annotation in place of &lt;code&gt;Optional[Union[int, float]]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you use &lt;code&gt;uv&lt;/code&gt; you can grab a copy of 3.14 using:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uv self update
uv python upgrade 3.14
uvx python@3.14
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or for free-threaded Python 3.1;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uvx python@3.14t
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;uv&lt;/code&gt; team wrote &lt;a href="https://astral.sh/blog/python-3.14"&gt;about their Python 3.14 highlights&lt;/a&gt; in their announcement of Python 3.14's availability via &lt;code&gt;uv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The GitHub Actions &lt;a href="https://github.com/actions/setup-python"&gt;setup-python action&lt;/a&gt; includes Python 3.14 now too, so the following YAML snippet in will run tests on all currently supported versions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;strategy:
  matrix:
    python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/setup-python@v6
  with:
    python-version: ${{ matrix.python-version }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://github.com/simonw/datasette-pretty-traces/blob/3edddecab850d6ac47ed128a400b6a0ff8b0c012/.github/workflows/test.yml"&gt;Full example here&lt;/a&gt; for one of my many Datasette plugin repos.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/open-source"&gt;open-source&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/github-actions"&gt;github-actions&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/psf"&gt;psf&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/uv"&gt;uv&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="open-source"/><category term="python"/><category term="github-actions"/><category term="psf"/><category term="uv"/></entry><entry><title>Quoting Kumar Aditya</title><link href="https://simonwillison.net/2025/Sep/11/kumar-aditya/#atom-tag" rel="alternate"/><published>2025-09-11T03:07:16+00:00</published><updated>2025-09-11T03:07:16+00:00</updated><id>https://simonwillison.net/2025/Sep/11/kumar-aditya/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://labs.quansight.org/blog/scaling-asyncio-on-free-threaded-python"&gt;&lt;p&gt;In Python 3.14, I have implemented several changes to fix thread safety of &lt;code&gt;asyncio&lt;/code&gt; and enable it to scale effectively on the free-threaded build of CPython. It is now implemented using lock-free data structures and per-thread state, allowing for highly efficient task management and execution across multiple threads. In the general case of multiple event loops running in parallel, there is no lock contention and performance scales linearly with the number of threads. [...]&lt;/p&gt;
&lt;p&gt;For a deeper dive into the implementation, check out the &lt;a href="https://github.com/python/cpython/blob/main/InternalDocs/asyncio.md#python-314-implementation"&gt;internal docs for asyncio&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://labs.quansight.org/blog/scaling-asyncio-on-free-threaded-python"&gt;Kumar Aditya&lt;/a&gt;, Scaling asyncio on Free-Threaded Python&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/async"&gt;async&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/scaling"&gt;scaling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/threads"&gt;threads&lt;/a&gt;&lt;/p&gt;



</summary><category term="async"/><category term="gil"/><category term="python"/><category term="scaling"/><category term="threads"/></entry><entry><title>Hypothesis is now thread-safe</title><link href="https://simonwillison.net/2025/Aug/8/hypothesis/#atom-tag" rel="alternate"/><published>2025-08-08T22:08:55+00:00</published><updated>2025-08-08T22:08:55+00:00</updated><id>https://simonwillison.net/2025/Aug/8/hypothesis/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://hypothesis.works/articles/thread-safe/"&gt;Hypothesis is now thread-safe&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Hypothesis is a property-based testing library for Python. It lets you write tests like this one:&lt;/p&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s1"&gt;hypothesis&lt;/span&gt; &lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;given&lt;/span&gt;, &lt;span class="pl-s1"&gt;strategies&lt;/span&gt; &lt;span class="pl-k"&gt;as&lt;/span&gt; &lt;span class="pl-s1"&gt;st&lt;/span&gt;

&lt;span class="pl-en"&gt;@&lt;span class="pl-en"&gt;given&lt;/span&gt;(&lt;span class="pl-s1"&gt;st&lt;/span&gt;.&lt;span class="pl-c1"&gt;lists&lt;/span&gt;(&lt;span class="pl-s1"&gt;st&lt;/span&gt;.&lt;span class="pl-c1"&gt;integers&lt;/span&gt;()))&lt;/span&gt;
&lt;span class="pl-k"&gt;def&lt;/span&gt; &lt;span class="pl-en"&gt;test_matches_builtin&lt;/span&gt;(&lt;span class="pl-s1"&gt;ls&lt;/span&gt;):
    &lt;span class="pl-k"&gt;assert&lt;/span&gt; &lt;span class="pl-en"&gt;sorted&lt;/span&gt;(&lt;span class="pl-s1"&gt;ls&lt;/span&gt;) &lt;span class="pl-c1"&gt;==&lt;/span&gt; &lt;span class="pl-en"&gt;my_sort&lt;/span&gt;(&lt;span class="pl-s1"&gt;ls&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;This will automatically create a collection of test fixtures that exercise a large array of expected list and integer shapes. Here's &lt;a href="https://gist.github.com/simonw/74014071af1553921e0307efd2280168"&gt;a Gist&lt;/a&gt; demonstrating the tests the above code will run, which include things like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[]
[0]
[-62, 13194]
[44, -19562, 44, -12803, -24012]
[-7531692443171623764, -109369043848442345045856489093298649615]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hypothesis contributor Liam DeVoe was recently sponsored by Quansight to add thread safety to Hypothesis, which has become important recently due to Python free threading:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While we of course would always have loved for Hypothesis to be thread-safe, thread-safety has historically not been a priority, because running Hypothesis tests under multiple threads is not something we see often.&lt;/p&gt;
&lt;p&gt;That changed recently. Python---as both a language, and a community---is gearing up to &lt;a href="https://peps.python.org/pep-0703/"&gt;remove the global interpreter lock (GIL)&lt;/a&gt;, in a build called &lt;a href="https://docs.python.org/3/howto/free-threading-python.html"&gt;free threading&lt;/a&gt;. Python packages, especially those that interact with the C API, will need to test that their code still works under the free threaded build. A great way to do this is to run each test in the suite in two or more threads simultaneously. [...]&lt;/p&gt;
&lt;p&gt;Nathan mentioned that because Hypothesis is not thread-safe, Hypothesis tests in community packages have to be skipped when testing free threaded compatibility, which removes a substantial battery of coverage.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now that Hypothesis is thread-safe another blocker to increased Python ecosystem support for free threading has been removed!

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/zrbpds/hypothesis_is_now_thread_safe"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/testing"&gt;testing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/threads"&gt;threads&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="python"/><category term="testing"/><category term="threads"/></entry><entry><title>From Async/Await to Virtual Threads</title><link href="https://simonwillison.net/2025/Aug/3/virtual-threads/#atom-tag" rel="alternate"/><published>2025-08-03T18:57:56+00:00</published><updated>2025-08-03T18:57:56+00:00</updated><id>https://simonwillison.net/2025/Aug/3/virtual-threads/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://lucumr.pocoo.org/2025/7/26/virtual-threads/"&gt;From Async/Await to Virtual Threads&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Armin Ronacher has long been critical of async/await in Python, both for necessitating &lt;a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/"&gt;colored functions&lt;/a&gt; and because of the more subtle challenges they introduce like &lt;a href="https://lucumr.pocoo.org/2020/1/1/async-pressure/"&gt;managing back pressure&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Armin &lt;a href="https://lucumr.pocoo.org/2024/11/18/threads-beat-async-await/"&gt;argued convincingly&lt;/a&gt; for the threaded programming model back in December. Now he's expanded upon that with a description of how virtual threads might make sense in Python.&lt;/p&gt;
&lt;p&gt;Virtual threads behave like real system threads but can vastly outnumber them, since they can be paused and scheduled to run on a real thread when needed. Go uses this trick to implement goroutines which can then support millions of virtual threads on a single system.&lt;/p&gt;
&lt;p&gt;Python core developer Mark Shannon &lt;a href="https://discuss.python.org/t/add-virtual-threads-to-python/91403"&gt;started a conversation&lt;/a&gt; about the potential for seeing virtual threads to Python back in May.&lt;/p&gt;
&lt;p&gt;Assuming this proposal turns into something concrete I don't expect we will see it in a production Python release for a few more years. In the meantime there are some exciting improvements to the Python concurrency story - most notably &lt;a href="https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-pep734"&gt;around sub-interpreters&lt;/a&gt; - coming up this year in Python 3.14.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/armin-ronacher"&gt;armin-ronacher&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/concurrency"&gt;concurrency&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/go"&gt;go&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/threads"&gt;threads&lt;/a&gt;&lt;/p&gt;



</summary><category term="armin-ronacher"/><category term="concurrency"/><category term="gil"/><category term="go"/><category term="python"/><category term="threads"/></entry><entry><title>Quoting Donghee Na</title><link href="https://simonwillison.net/2025/Jun/17/donghee-na/#atom-tag" rel="alternate"/><published>2025-06-17T13:44:09+00:00</published><updated>2025-06-17T13:44:09+00:00</updated><id>https://simonwillison.net/2025/Jun/17/donghee-na/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://discuss.python.org/t/pep-779-criteria-for-supported-status-for-free-threaded-python/84319/123"&gt;&lt;p&gt;The Steering Council (SC) approves &lt;a href="https://peps.python.org/pep-0779/"&gt;PEP 779&lt;/a&gt; [Criteria for supported status for free-threaded Python], with the effect of removing the “experimental” tag from the free-threaded build of Python 3.14 [...]&lt;/p&gt;
&lt;p&gt;With these recommendations and the acceptance of this PEP, we as the Python developer community should broadly advertise that free-threading is a supported Python build option now and into the future, and that it will not be removed without following a proper deprecation schedule. [...]&lt;/p&gt;
&lt;p&gt;Keep in mind that any decision to transition to Phase III, with free-threading as the default or sole build of Python is still undecided, and dependent on many factors both within CPython itself and the community. We leave that decision for the future.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://discuss.python.org/t/pep-779-criteria-for-supported-status-for-free-threaded-python/84319/123"&gt;Donghee Na&lt;/a&gt;, discuss.python.org&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="python"/></entry><entry><title>Supercharge the One Person Framework with SQLite: Rails World 2024</title><link href="https://simonwillison.net/2024/Oct/16/sqlite-rails/#atom-tag" rel="alternate"/><published>2024-10-16T22:24:45+00:00</published><updated>2024-10-16T22:24:45+00:00</updated><id>https://simonwillison.net/2024/Oct/16/sqlite-rails/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://fractaledmind.github.io/2024/10/16/sqlite-supercharges-rails/"&gt;Supercharge the One Person Framework with SQLite: Rails World 2024&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Stephen Margheim shares an annotated transcript of the &lt;a href="https://www.youtube.com/watch?v=l56IBad-5aQ"&gt;YouTube video&lt;/a&gt; of his recent talk at this year's Rails World conference in Toronto.&lt;/p&gt;
&lt;p&gt;The Rails community is leaning &lt;em&gt;hard&lt;/em&gt; into SQLite right now. Stephen's talk is some of the most effective evangelism I've seen anywhere for SQLite as a production database for web applications, highlighting several new changes &lt;a href="https://simonwillison.net/2024/Oct/7/whats-new-in-ruby-on-rails-8/"&gt;in Rails 8&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;... there are two additions coming with Rails 8 that merit closer consideration. Because these changes make Rails 8 the first version of Rails (and, as far as I know, the first version of any web framework) that provides a fully production-ready SQLite experience out-of-the-box. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those changes: &lt;a href="https://github.com/rails/rails/pull/50371"&gt;Ensure SQLite transaction default to IMMEDIATE mode&lt;/a&gt; to avoid "database is locked" errors when a deferred transaction attempts to upgrade itself with a write lock (discussed here &lt;a href="https://simonwillison.net/2024/Mar/31/optimizing-sqlite-for-servers/"&gt;previously&lt;/a&gt;, and added to Datasette 1.0a14 &lt;a href="https://simonwillison.net/2024/Aug/5/datasette-1a14/#sqlite-isolation-level-immediate-"&gt;in August&lt;/a&gt;) and &lt;a href="https://github.com/rails/rails/pull/51958"&gt;SQLite non-GVL-blocking, fair retry interval busy handler&lt;/a&gt; - a lower-level change that ensures SQLite's busy handler doesn't hold Ruby's Global VM Lock (the Ruby version of Python's GIL) while a thread is waiting on a SQLite lock.&lt;/p&gt;
&lt;p&gt;The rest of the talk makes a passionate and convincing case for SQLite as an option for production deployments, in line with the Rails goal of being a &lt;a href="https://world.hey.com/dhh/the-one-person-framework-711e6318"&gt;One Person Framework&lt;/a&gt; - "a toolkit so powerful that it allows a single individual to create modern applications upon which they might build a competitive business".&lt;/p&gt;
&lt;p&gt;&lt;img alt="Animated slide. The text Single-machine SQLite-only deployments can't serve production workloads is stamped with a big red Myth stamp" src="https://static.simonwillison.net/static/2024/sqlite-myth-smaller.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Back in April Stephen published &lt;a href="https://fractaledmind.github.io/2024/04/15/sqlite-on-rails-the-how-and-why-of-optimal-performance/"&gt;SQLite on Rails: The how and why of optimal performance&lt;/a&gt; describing some of these challenges in more detail (including the best explanation I've seen anywhere of &lt;code&gt;BEGIN IMMEDIATE TRANSACTION&lt;/code&gt;) and promising:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unfortunately, running SQLite on Rails out-of-the-box isn’t viable today. But, with a bit of tweaking and fine-tuning, you can ship a very performant, resilient Rails application with SQLite. And my personal goal for Rails 8 is to make the out-of-the-box experience fully production-ready.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It looks like he achieved that goal!

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=41858018"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/rails"&gt;rails&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ruby"&gt;ruby&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/scaling"&gt;scaling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite"&gt;sqlite&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/sqlite-busy"&gt;sqlite-busy&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="rails"/><category term="ruby"/><category term="scaling"/><category term="sqlite"/><category term="sqlite-busy"/></entry><entry><title>Free Threaded Python With Asyncio</title><link href="https://simonwillison.net/2024/Oct/9/free-threaded-python-with-asyncio/#atom-tag" rel="alternate"/><published>2024-10-09T20:38:19+00:00</published><updated>2024-10-09T20:38:19+00:00</updated><id>https://simonwillison.net/2024/Oct/9/free-threaded-python-with-asyncio/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.changs.co.uk/free-threaded-python-with-asyncio.html"&gt;Free Threaded Python With Asyncio&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Jamie Chang expanded &lt;a href="https://til.simonwillison.net/python/trying-free-threaded-python"&gt;my free-threaded Python experiment&lt;/a&gt; from a few months ago to explore the interaction between Python's &lt;code&gt;asyncio&lt;/code&gt; and the new GIL-free build of Python 3.13.&lt;/p&gt;
&lt;p&gt;The results look really promising. Jamie says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Generally when it comes to Asyncio, the discussion around it is always about the performance or lack there of. Whilst peroformance is certain important, the ability to reason about concurrency is the biggest benefit. [...]&lt;/p&gt;
&lt;p&gt;Depending on your familiarity with AsyncIO, it might actually be the simplest way to start a thread.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This code for running a Python function in a thread really is very pleasant to look at:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;result = await asyncio.to_thread(some_function, *args, **kwargs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jamie also demonstrates &lt;a href="https://docs.python.org/3/library/asyncio-task.html#task-groups"&gt;asyncio.TaskGroup&lt;/a&gt;, which makes it easy to execute a whole bunch of threads and wait for them all to finish:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async with TaskGroup() as tg:
    for _ in range(args.tasks):
        tg.create_task(to_thread(cpu_bound_task, args.size))
&lt;/code&gt;&lt;/pre&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/async"&gt;async&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="async"/><category term="gil"/><category term="python"/></entry><entry><title>Free-threaded CPython is ready to experiment with!</title><link href="https://simonwillison.net/2024/Jul/12/free-threaded-cpython/#atom-tag" rel="alternate"/><published>2024-07-12T23:42:46+00:00</published><updated>2024-07-12T23:42:46+00:00</updated><id>https://simonwillison.net/2024/Jul/12/free-threaded-cpython/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://labs.quansight.org/blog/free-threaded-python-rollout"&gt;Free-threaded CPython is ready to experiment with!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The Python 3.13 beta releases that include a "free-threaded" version that removes the GIL are now available to test! A team from Quansight Labs, home of the PyData core team, just launched &lt;a href="https://py-free-threading.github.io/"&gt;py-free-threading.github.io&lt;/a&gt; to help document the new builds and track compatibility with Python's larger ecosystem.&lt;/p&gt;
&lt;p&gt;Free-threading mode will not be enabled in Python installations by default. You can install special builds that have the option enabled today - I used the macOS installer and, after enabling the new build in the "Customize" panel in the installer, ended up with a &lt;code&gt;/usr/local/bin/python3.13t&lt;/code&gt; binary which shows "Python 3.13.0b3 experimental free-threading build" when I run it.&lt;/p&gt;
&lt;p&gt;Here's &lt;a href="https://til.simonwillison.net/python/trying-free-threaded-python"&gt;my TIL describing my experiments so far&lt;/a&gt; installing and running the 3.13 beta on macOS, which also includes a correction to an embarrassing bug that Claude introduced but I failed to catch!


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/concurrency"&gt;concurrency&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/threads"&gt;threads&lt;/a&gt;&lt;/p&gt;



</summary><category term="concurrency"/><category term="gil"/><category term="python"/><category term="threads"/></entry><entry><title>gh-116167: Allow disabling the GIL with PYTHON_GIL=0 or -X gil=0</title><link href="https://simonwillison.net/2024/Mar/12/allow-disabling-the-gil/#atom-tag" rel="alternate"/><published>2024-03-12T05:40:41+00:00</published><updated>2024-03-12T05:40:41+00:00</updated><id>https://simonwillison.net/2024/Mar/12/allow-disabling-the-gil/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/python/cpython/pull/116338"&gt;gh-116167: Allow disabling the GIL with PYTHON_GIL=0 or -X gil=0&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Merged into python:main 14 hours ago. Looks like the first phase of Sam Gross’s phenomenal effort to provide a GIL free Python (here via an explicit opt-in) will ship in Python 3.13.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="python"/></entry><entry><title>A Steering Council notice about PEP 703 (Making the Global Interpreter Lock Optional in CPython)</title><link href="https://simonwillison.net/2023/Jul/29/a-steering-council-notice-about-pep-703/#atom-tag" rel="alternate"/><published>2023-07-29T21:23:21+00:00</published><updated>2023-07-29T21:23:21+00:00</updated><id>https://simonwillison.net/2023/Jul/29/a-steering-council-notice-about-pep-703/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://discuss.python.org/t/a-steering-council-notice-about-pep-703-making-the-global-interpreter-lock-optional-in-cpython/30474"&gt;A Steering Council notice about PEP 703 (Making the Global Interpreter Lock Optional in CPython)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Huge news concerning the nogil research fork of Python: “It’s clear that the overall sentiment is positive, both for the general idea and for PEP 703 specifically. The Steering Council is also largely positive on both. We intend to accept PEP 703, although we’re still working on the acceptance details.”

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/charliermarsh/status/1685068890424967168"&gt;@charliermarsh&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="python"/></entry><entry><title>The Python Language Summit 2023: Making the Global Interpreter Lock Optional</title><link href="https://simonwillison.net/2023/May/31/nogil/#atom-tag" rel="alternate"/><published>2023-05-31T00:04:41+00:00</published><updated>2023-05-31T00:04:41+00:00</updated><id>https://simonwillison.net/2023/May/31/nogil/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://pyfound.blogspot.com/2023/05/the-python-language-summit-2023-making.html"&gt;The Python Language Summit 2023: Making the Global Interpreter Lock Optional&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Extremely informative update covering Sam Gross’s python-nogil proposal from this year’s language summit at PyCon.&lt;/p&gt;

&lt;p&gt;Sam has been working hard on his fork for the past year, and now has it rebased for Python 3.12. If his PEP is accepted it could end up as an optional compile-time build in time for Python 3.13.&lt;/p&gt;

&lt;p&gt;“The plan for nogil remains that it would be enabled via a compile-time flag, named --disable-gil. Third-party C extensions would need to provide separate wheels for GIL-disabled Python.”


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="python"/></entry><entry><title>Real Multithreading is Coming to Python - Learn How You Can Use It Now</title><link href="https://simonwillison.net/2023/May/15/per-interpreter-gils/#atom-tag" rel="alternate"/><published>2023-05-15T19:42:39+00:00</published><updated>2023-05-15T19:42:39+00:00</updated><id>https://simonwillison.net/2023/May/15/per-interpreter-gils/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://martinheinz.dev/blog/97"&gt;Real Multithreading is Coming to Python - Learn How You Can Use It Now&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Martin Heinz provides a detailed tutorial on trying out the new Per-Interpreter GIL feature that’s landing in Python 3.12, which allows Python code to run concurrently in multiple threads by spawning separate sub-interpreters, each with their own dedicated GIL.&lt;/p&gt;

&lt;p&gt;It’s not an easy feature to play with yet! First you need to compile Python yourself, and then use APIs that are generally only available to C code (but should hopefully become available to Python code itself in Python 3.13).&lt;/p&gt;

&lt;p&gt;Martin’s workaround for this is ingenious: it turns out the Python test.support package provides utility functions to help write tests against interpreters, and Martin shows how to abuse this module to launch, run and cleanup interpreters using regular Python code.&lt;/p&gt;

&lt;p&gt;He also demonstrates test.support.interpreters.create_channel(), which can be used to create channels with receiver and sender ends, somewhat similar to Go.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/i9wbjm/real_multithreading_is_coming_python"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/concurrency"&gt;concurrency&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/go"&gt;go&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="concurrency"/><category term="gil"/><category term="go"/><category term="python"/></entry><entry><title>Quoting Armin Ronacher</title><link href="https://simonwillison.net/2023/Apr/11/armin-ronacher/#atom-tag" rel="alternate"/><published>2023-04-11T16:47:40+00:00</published><updated>2023-04-11T16:47:40+00:00</updated><id>https://simonwillison.net/2023/Apr/11/armin-ronacher/#atom-tag</id><summary type="html">
    &lt;blockquote cite="https://twitter.com/mitsuhiko/status/1645747519782092806"&gt;&lt;p&gt;My strong hunch is that the GIL does not need removing, if a) subinterpreters have their own GILs and b) an efficient way is provided to pass (some) data between subinterpreters lock free and c) we find good patterns to make working with subinterpreters work.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class="cite"&gt;&amp;mdash; &lt;a href="https://twitter.com/mitsuhiko/status/1645747519782092806"&gt;Armin Ronacher&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/armin-ronacher"&gt;armin-ronacher&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="armin-ronacher"/><category term="gil"/><category term="python"/></entry><entry><title>Weeknotes: Datasette Lite, nogil Python, HYTRADBOI</title><link href="https://simonwillison.net/2022/May/6/weeknotes/#atom-tag" rel="alternate"/><published>2022-05-06T22:56:39+00:00</published><updated>2022-05-06T22:56:39+00:00</updated><id>https://simonwillison.net/2022/May/6/weeknotes/#atom-tag</id><summary type="html">
    &lt;p&gt;My big project this week was &lt;a href="https://simonwillison.net/2022/May/4/datasette-lite/"&gt;Datasette Lite&lt;/a&gt;, a new way to run Datasette directly in a browser, powered by WebAssembly and &lt;a href="https://pyodide.org/"&gt;Pyodide&lt;/a&gt;. I also continued my research into running SQL queries in parallel, described &lt;a href="https://simonwillison.net/2022/Apr/27/parallel-queries/"&gt;last week&lt;/a&gt;. Plus I spoke at &lt;a href="https://www.hytradboi.com/"&gt;HYTRADBOI&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Datasette Lite&lt;/h4&gt;
&lt;p&gt;This started out as a research project, inspired by the excitement around Python in the browser from PyCon US last week (which I didn't attend, but observed with some jealousy on Twitter).&lt;/p&gt;
&lt;p&gt;I've been wanting to explore this possibility for a while. &lt;a href="https://jupyterlite.readthedocs.io/en/latest/"&gt;JupyterLite&lt;/a&gt; had convinced me that it would be feasible to run Datasette using Pyodide, especially after I found out that the &lt;code&gt;sqlite3&lt;/code&gt; module from the Python standard library works there already.&lt;/p&gt;
&lt;p&gt;I have a private "notes" GitHub repository which I use to keep notes in GitHub issues. I started a thread there researching the possibility of running an ASGI application in Pyodide, thinking that might be a good starting point to getting Datasette to work.&lt;/p&gt;
&lt;p&gt;The proof of concept moved remarkably quickly, especially once I realized that Service Workers weren't going to work but Web Workers might.&lt;/p&gt;
&lt;p&gt;Once I had comitted to Datasette Lite as a full project I started &lt;a href="https://github.com/simonw/datasette-lite"&gt;a new repository&lt;/a&gt; for it and transferred across my initial prototype issue thread. You can read that full thread for a blow-by-blow account of how my research pulled together in &lt;a href="https://github.com/simonw/datasette-lite/issues/1"&gt;datasette-lite issue #1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the project is documented in detail in &lt;a href="https://simonwillison.net/2022/May/4/datasette-lite/"&gt;my blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since launching it the biggest change I've made was a change of URL: since it's clearly going to be a core component of the Datasette project going forward I promoted it from &lt;code&gt;simonw.github.io/datasette-lite/&lt;/code&gt; to its new permanent home at &lt;a href="https://lite.datasette.io"&gt;lite.datasette.io&lt;/a&gt;. It's still hosted by GitHub Pages - here's &lt;a href="https://til.simonwillison.net/github/custom-subdomain-github-pages"&gt;my TIL&lt;/a&gt; about setting up the new domain.&lt;/p&gt;
&lt;p&gt;It may have started as a proof of concept tech demo, but the response to it so far has convinced me that I should really take it seriously. Being able to host Datasette without needing to run any server-side code at all is an incredibly compelling experience.&lt;/p&gt;
&lt;p&gt;It doesn't matter how hard I work on getting the Datasette &lt;a href="https://docs.datasette.io/en/stable/publish.html"&gt;deployment experience&lt;/a&gt; as easy as possible, static file hosting will always be an order of magnitude more accessible. And even at this early stage Datasette Lite is already proving to be a genuinely useful way to run the software.&lt;/p&gt;
&lt;p&gt;As part of this research I also shipped &lt;a href="https://sqlite-utils.datasette.io/en/stable/changelog.html#v3-26-1"&gt;sqlite-utils 3.26.1&lt;/a&gt; with a minor dependency fix that means it works in Pyodide now. You can try that out by running the following in the &lt;a href="https://pyodide.org/en/stable/console.html"&gt;Pyodide REPL&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-text-python-console"&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span class="pl-k"&gt;import&lt;/span&gt; micropip
&amp;gt;&amp;gt;&amp;gt; &lt;span class="pl-k"&gt;await&lt;/span&gt; micropip.install(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;sqlite-utils&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;)
&amp;gt;&amp;gt;&amp;gt; &lt;span class="pl-k"&gt;import&lt;/span&gt; sqlite_utils
&amp;gt;&amp;gt;&amp;gt; db &lt;span class="pl-k"&gt;=&lt;/span&gt; sqlite_utils.Database(&lt;span class="pl-v"&gt;memory&lt;/span&gt;&lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;span class="pl-c1"&gt;True&lt;/span&gt;)
&amp;gt;&amp;gt;&amp;gt; &lt;span class="pl-c1"&gt;list&lt;/span&gt;(db.query(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;select 3 * 5&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;))
[{'3 * 5': 15}]&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="nogil"&gt;Parallel SQL queries work... if you can get rid of the GIL&lt;/h4&gt;
&lt;p&gt;Last week I described my effort to implement &lt;a href="https://simonwillison.net/2022/Apr/27/parallel-queries/"&gt;Parallel SQL queries for Datasette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea there was that many Datasette pages execute multiple SQL queries - a &lt;code&gt;count(*)&lt;/code&gt; and a &lt;code&gt;select ... limit 101&lt;/code&gt; for example - that could be run in parallel instead of serial, for a potential improvement in page load times.&lt;/p&gt;
&lt;p&gt;My hope was that I could get away with this despite Python's infamous Global Interpreter Lock because the &lt;code&gt;sqlite3&lt;/code&gt; C module releases the GIL when it executes a query.&lt;/p&gt;
&lt;p&gt;My initial results weren't showing an increase in performance, even while the queries were shown to be overlapping each other. I opened &lt;a href="https://github.com/simonw/datasette/issues/1727"&gt;a research thread&lt;/a&gt; and spent some time this week investigating.&lt;/p&gt;
&lt;p&gt;My conclusion, sadly, was that the GIL was indeed to blame. &lt;code&gt;sqlite3&lt;/code&gt; releases the GIL to execute the query, but there's still a lot of work that happens in Python land itself - most importantly the code that assembles the objects that represent the rows returned by the query, which is still subject to the GIL.&lt;/p&gt;
&lt;p&gt;Then &lt;a href="https://lobste.rs/s/9hj80j/when_python_can_t_thread_deep_dive_into_gil#c_2n0fga"&gt;this comment&lt;/a&gt; on a thread about the GIL on Lobsters reminded me of the &lt;a href="https://github.com/colesbury/nogil"&gt;nogil fork&lt;/a&gt; of Python by Sam Gross, who has been working on this problem for several years now.&lt;/p&gt;
&lt;p&gt;Since that fork has &lt;a href="https://github.com/colesbury/nogil#docker"&gt;a Docker image&lt;/a&gt; trying it out was easy... and to my amazement &lt;a href="https://simonwillison.net/2022/Apr/29/nogil/"&gt;it worked&lt;/a&gt;! Running my parallel queries implementation against &lt;code&gt;nogil&lt;/code&gt; Python reduced a page load time from 77ms to 47ms.&lt;/p&gt;
&lt;p&gt;Sam's work is against Python 3.9, but he's &lt;a href="https://lukasz.langa.pl/5d044f91-49c1-4170-aed1-62b6763e6ad0/"&gt;discussing options&lt;/a&gt; for bringing his improvemets into Python itself with the core maintainers. I'm hopeful that this might happen in the next few years. It's an incredible piece of work.&lt;/p&gt;
&lt;p&gt;An amusing coincidence: one restriction of WASM and Pyodide is that they can't start new threads - so as part of getting Datasette to work on that platform I had to &lt;a href="https://github.com/simonw/datasette/issues/1735"&gt;add a new setting&lt;/a&gt; that disables the ability to run SQL queries in threads entirely!&lt;/p&gt;
&lt;h4&gt;datasette-copy-to-memory&lt;/h4&gt;
&lt;p&gt;One question I found myself asking while investigating parallel SQL queries (before I determined that the GIL was to blame) was whether parallel SQLite queries against the same database file were suffering from some form of file locking or contention.&lt;/p&gt;
&lt;p&gt;To rule that out, I built a new plugin: &lt;a href="https://datasette.io/plugins/datasette-copy-to-memory"&gt;datasette-copy-to-memory&lt;/a&gt; - which reads a SQLite database from disk and copies it into an in-memory database when Datasette first starts up.&lt;/p&gt;
&lt;p&gt;This didn't make an observable difference in performance, but I've not tested it extensively - especially not against larger databases using servers with increased amounts of available RAM.&lt;/p&gt;
&lt;p&gt;If you're inspired to give this plugin a go I'd love to hear about your results.&lt;/p&gt;
&lt;h4&gt;asgi-gzip and datasette-gzip&lt;/h4&gt;
&lt;p&gt;I mentioned &lt;code&gt;datasette-gzip&lt;/code&gt; last week: a plugin that acts as a wrapper around the excellent &lt;code&gt;GZipMiddleware&lt;/code&gt; from &lt;a href="https://www.starlette.io/"&gt;Starlette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The performance improvements from this - especially for larger HTML tables, which it turns out compress extremely well - were significant. Enough so that I plan to bring gzip support into Datasette core very shortly.&lt;/p&gt;
&lt;p&gt;Since I don't want to add the whole of Starlette as a dependency just to get gzip support, I extracted that code out into a new Python package called &lt;a href="https://github.com/simonw/asgi-gzip"&gt;asgi-gzip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The obvious risk with doing this is that it might fall behind the excellent Starlette implementation. So I came up with a pattern based on &lt;a href="https://simonwillison.net/2020/Oct/9/git-scraping/"&gt;Git scraping&lt;/a&gt; that would automatically open a new GitHub issue should the borrowed Starlette code change in the future.&lt;/p&gt;
&lt;p&gt;I wrote about that pattern in &lt;a href="https://simonwillison.net/2022/Apr/28/issue-on-changes/"&gt;Automatically opening issues when tracked file content changes&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Speaking at HYTRADBOI&lt;/h4&gt;
&lt;p&gt;I spoke at the &lt;a href="https://www.hytradboi.com/"&gt;HYTRADBOI conference&lt;/a&gt; last week: Have You Tried Rubbing A Database On It.&lt;/p&gt;
&lt;p&gt;HYTRADBOI was organized by Jamie Brandon. It was a neat event, with a smart format: 34 pre-recorded 10 minute long talks, arranged into a schedule to encourage people to watch and discuss them at specific times during the day of the event.&lt;/p&gt;
&lt;p&gt;It's worth reading Jamie's &lt;a href="https://www.scattered-thoughts.net/writing/hytradboi-2022-postmortem/"&gt;postmortem of the event&lt;/a&gt; for some insightful thinking on online event organization.&lt;/p&gt;
&lt;p&gt;My talk was &lt;a href="https://www.hytradboi.com/2022/datasette-a-big-bag-of-tricks-for-solving-interesting-problems-using-sqlite"&gt;Datasette: a big bag of tricks for solving interesting problems using SQLite&lt;/a&gt;. It ended up working out as a lightning-fast 10 minute tutorial on using the &lt;a href="https://sqlite-utils.datasette.io/en/stable/cli.html"&gt;sqlite-utils CLI&lt;/a&gt; to clean up some data (in this case &lt;a href="https://geodata.myfwc.com/datasets/myfwc::manatee-carcass-recovery-locations-in-florida/about"&gt;Manatee Carcass Recovery Locations in Florida&lt;/a&gt; since 1974) and then using Datasette to explore and publish it.&lt;/p&gt;
&lt;p&gt;I've posted &lt;a href="https://gist.github.com/simonw/c61447d866f7f29d368183fb09d9bf41"&gt;some basic notes&lt;/a&gt; to accompany the talk. My plan is to use this as the basis for an official tutorial on &lt;code&gt;sqlite-utils&lt;/code&gt; for the &lt;a href="https://datasette.io/tutorials"&gt;tutorials section&lt;/a&gt; of the Datasette website.&lt;/p&gt;
&lt;h4&gt;Releases this week&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/datasette"&gt;datasette&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/datasette/releases/tag/0.62a0"&gt;0.62a0&lt;/a&gt; - (&lt;a href="https://github.com/simonw/datasette/releases"&gt;111 releases total&lt;/a&gt;) - 2022-05-02
&lt;br /&gt;An open source multi-tool for exploring and publishing data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/sqlite-utils"&gt;sqlite-utils&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/sqlite-utils/releases/tag/3.26.1"&gt;3.26.1&lt;/a&gt; - (&lt;a href="https://github.com/simonw/sqlite-utils/releases"&gt;100 releases total&lt;/a&gt;) - 2022-05-02
&lt;br /&gt;Python CLI utility and library for manipulating SQLite databases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/click-default-group-wheel"&gt;click-default-group-wheel&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/click-default-group-wheel/releases/tag/1.2.2"&gt;1.2.2&lt;/a&gt; - 2022-05-02
&lt;br /&gt;Extends click.Group to invoke a command without explicit subcommand name (this version publishes a wheel)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/s3-credentials"&gt;s3-credentials&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/s3-credentials/releases/tag/0.11"&gt;0.11&lt;/a&gt; - (&lt;a href="https://github.com/simonw/s3-credentials/releases"&gt;11 releases total&lt;/a&gt;) - 2022-05-01
&lt;br /&gt;A tool for creating credentials for accessing S3 buckets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/datasette-copy-to-memory"&gt;datasette-copy-to-memory&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/datasette-copy-to-memory/releases/tag/0.2"&gt;0.2&lt;/a&gt; - (&lt;a href="https://github.com/simonw/datasette-copy-to-memory/releases"&gt;5 releases total&lt;/a&gt;) - 2022-04-30
&lt;br /&gt;Copy database files into an in-memory database on startup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/datasette-gzip"&gt;datasette-gzip&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/datasette-gzip/releases/tag/0.2"&gt;0.2&lt;/a&gt; - (&lt;a href="https://github.com/simonw/datasette-gzip/releases"&gt;2 releases total&lt;/a&gt;) - 2022-04-28
&lt;br /&gt;Add gzip compression to Datasette&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/simonw/asgi-gzip"&gt;asgi-gzip&lt;/a&gt;&lt;/strong&gt;: &lt;a href="https://github.com/simonw/asgi-gzip/releases/tag/0.1"&gt;0.1&lt;/a&gt; - 2022-04-28
&lt;br /&gt;gzip middleware for ASGI applications, extracted from Starlette&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TIL this week&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://til.simonwillison.net/service-workers/intercept-fetch"&gt;Intercepting fetch in a service worker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://til.simonwillison.net/github/custom-subdomain-github-pages"&gt;Setting up a custom subdomain for a GitHub Pages site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
    
        &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/projects"&gt;projects&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/speaking"&gt;speaking&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/datasette"&gt;datasette&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/asgi"&gt;asgi&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webassembly"&gt;webassembly&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/weeknotes"&gt;weeknotes&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pyodide"&gt;pyodide&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/datasette-lite"&gt;datasette-lite&lt;/a&gt;&lt;/p&gt;
    

</summary><category term="gil"/><category term="projects"/><category term="python"/><category term="speaking"/><category term="datasette"/><category term="asgi"/><category term="webassembly"/><category term="weeknotes"/><category term="pyodide"/><category term="datasette-lite"/></entry><entry><title>Testing Datasette parallel SQL queries in the nogil/python fork</title><link href="https://simonwillison.net/2022/Apr/29/nogil/#atom-tag" rel="alternate"/><published>2022-04-29T05:45:57+00:00</published><updated>2022-04-29T05:45:57+00:00</updated><id>https://simonwillison.net/2022/Apr/29/nogil/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/simonw/datasette/issues/1727#issuecomment-1112889800"&gt;Testing Datasette parallel SQL queries in the nogil/python fork&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
As part of my ongoing research into whether Datasette can be sped up by running SQL queries in parallel I’ve been growing increasingly suspicious that the GIL is holding me back. I know the sqlite3 module releases the GIL and was hoping that would give me parallel queries, but it looks like there’s still a ton of work going on in Python GIL land creating Python objects representing the results of the query.&lt;/p&gt;

&lt;p&gt;Sam Gross has been working on a nogil fork of Python and I decided to give it a go. It’s published as a Docker image and it turns out trying it out really did just take a few commands... and it produced the desired results, my parallel code started beating my serial code where previously the two had produced effectively the same performance numbers.&lt;/p&gt;

&lt;p&gt;I’m pretty stunned by this. I had no idea how far along the nogil fork was. It’s amazing to see it in action.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/docker"&gt;docker&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="python"/><category term="docker"/></entry><entry><title>[history] When I tried this in 1996</title><link href="https://simonwillison.net/2022/Feb/21/histor/#atom-tag" rel="alternate"/><published>2022-02-21T22:43:55+00:00</published><updated>2022-02-21T22:43:55+00:00</updated><id>https://simonwillison.net/2022/Feb/21/histor/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/colesbury/nogil/issues/8"&gt;[history] When I tried this in 1996&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
“I removed the GIL back in 1996 from Python 1.4...” is the start of a fascinating (supportive) comment by Greg Stein on the promising nogil Python fork that Sam Gross has been putting together. Greg provides some historical context that I’d never heard before, relating to an embedded Python for Microsoft IIS.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://twitter.com/simonw/status/1495891968291139584"&gt;@simonw&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/history"&gt;history&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="history"/><category term="python"/></entry><entry><title>The GIL and its effects on Python multithreading</title><link href="https://simonwillison.net/2021/Sep/29/the-gil-and-its-effects-on-python-multithreading/#atom-tag" rel="alternate"/><published>2021-09-29T17:23:15+00:00</published><updated>2021-09-29T17:23:15+00:00</updated><id>https://simonwillison.net/2021/Sep/29/the-gil-and-its-effects-on-python-multithreading/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://tenthousandmeters.com/blog/python-behind-the-scenes-13-the-gil-and-its-effects-on-python-multithreading/"&gt;The GIL and its effects on Python multithreading&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Victor Skvortsov presents the most in-depth explanation of the Python Global Interpreter Lock I’ve seen anywhere. I learned a ton from reading this.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=28690560"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/concurrency"&gt;concurrency&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/threads"&gt;threads&lt;/a&gt;&lt;/p&gt;



</summary><category term="concurrency"/><category term="gil"/><category term="python"/><category term="threads"/></entry><entry><title>jessenoller.com - python magazine</title><link href="https://simonwillison.net/2009/Feb/5/jessenollercom/#atom-tag" rel="alternate"/><published>2009-02-05T23:10:43+00:00</published><updated>2009-02-05T23:10:43+00:00</updated><id>https://simonwillison.net/2009/Feb/5/jessenollercom/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://jessenoller.com/category/python-magazine/"&gt;jessenoller.com - python magazine&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Jesse Noller has been sharing his articles originally published in Python Magazine. Topics include SSH programming with Paramiko, context managers and the with statement and an excellent explanation of Python’s threading support and the global interpreter lock.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/contextmanagers"&gt;contextmanagers&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jesse-noller"&gt;jesse-noller&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/paramiko"&gt;paramiko&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/pythonmagazine"&gt;pythonmagazine&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/ssh"&gt;ssh&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/threads"&gt;threads&lt;/a&gt;&lt;/p&gt;



</summary><category term="contextmanagers"/><category term="gil"/><category term="jesse-noller"/><category term="paramiko"/><category term="python"/><category term="pythonmagazine"/><category term="ssh"/><category term="threads"/></entry><entry><title>What's New in Python 2.6</title><link href="https://simonwillison.net/2008/Sep/1/whatus/#atom-tag" rel="alternate"/><published>2008-09-01T21:03:27+00:00</published><updated>2008-09-01T21:03:27+00:00</updated><id>https://simonwillison.net/2008/Sep/1/whatus/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://docs.python.org/dev/whatsnew/2.6.html"&gt;What&amp;#x27;s New in Python 2.6&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The new multiprocessing package looks pretty useful, especially as it provides a way to work around Python’s GIL.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/gil"&gt;gil&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/multiprocessing"&gt;multiprocessing&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="gil"/><category term="multiprocessing"/><category term="python"/></entry></feed>