[HN Gopher] Free-threaded CPython is ready to experiment with
       ___________________________________________________________________
        
       Free-threaded CPython is ready to experiment with
        
       Author : ngoldbaum
       Score  : 188 points
       Date   : 2024-07-12 19:52 UTC (3 hours ago)
        
 (HTM) web link (labs.quansight.org)
 (TXT) w3m dump (labs.quansight.org)
        
       | nas wrote:
       | Very encouraging news!
        
       | OutOfHere wrote:
       | It has been ready for a few months now, at least since 3.13.0
       | beta 1 which released on 2024-05-08, although alpha versions had
       | it working too. I don't know why this is news _now_.
       | 
       | With it, the single-threaded case is slower.
        
         | TylerE wrote:
         | FTA: "Yesterday, py-free-threading.github.io launched! It's
         | both a resource with documentation around adding support for
         | free-threaded Python, and a status tracker for the rollout
         | across open source projects in the Python ecosystem."
        
           | OutOfHere wrote:
           | Before the article came the misleading title: "Free-threaded
           | CPython is ready to experiment with".
           | 
           | The link should have been to https://py-free-
           | threading.github.io/tracking/
        
         | JBorrow wrote:
         | This release coincides with the SciPy 2024 conference and a
         | number of other things. I would suggest reading the article to
         | learn more.
        
           | OutOfHere wrote:
           | > This release
           | 
           | What release. The last release of CPython was 3.13.0b3 on
           | 2024-06-27.
           | 
           | SciPy is irrelevant to the title.
        
       | nine_k wrote:
       | Python 3 progress so far:                 [x] Async.       [x]
       | Optional static typing.       [x] Threading.       [ ] JIT.
       | [ ] Efficient dependency management.
        
         | janice1999 wrote:
         | Not sure what this list means, there are successful languages
         | without these feature. Also Python 3.13 [1] has an optional JIT
         | [2], disabled by default.
         | 
         | [1] https://docs.python.org/3.13/whatsnew/3.13.html
         | 
         | [2] https://peps.python.org/pep-0744/
        
           | jolux wrote:
           | The successful languages without efficient dependency
           | management are painful to manage dependencies in, though. I
           | think Python should be shooting for a better package
           | management user experience than C++.
        
             | yosefk wrote:
             | If Python's dependency management is better than anything,
             | it's better than C++'s. Python has pip and venv. C++ has
             | nothing (you could say less than nothing since you also
             | have ample opportunity for inconsistent build due to
             | mismatching #defines as well as using the wrong binaries
             | for your .h files and nothing remotely like type-safe
             | linkage to mitigate human error. It also has an infinite
             | number of build systems where each system of makefiles or
             | cmakefiles is its own build system with its own conventions
             | and features). In fact python is the best dependency
             | management system for C++ code when you can get binaries
             | build from C++ via pip install...
        
               | wiseowise wrote:
               | > If Python's dependency management is better than
               | anything, it's better than C++'s.
               | 
               | That's like the lowest possible bar to clear.
        
             | Galanwe wrote:
             | Not sure this is still a valid critic of Python in 2024.
             | 
             | Between pip, poetry and pyproject.toml, things are now
             | quite good IMHO.
        
               | Arcanum-XIII wrote:
               | All is well, then, one day, you have to update one
               | library.
               | 
               | Some days later, in some woods or cave, people will hear
               | your screams of rage and despair.
        
               | Galanwe wrote:
               | Been using python for 15 years now, and these screams
               | were never heard.
               | 
               | Dev/test with relaxed pip installs, freeze deployment
               | dependencies with pip freeze/pip-
               | tools/poetry/whateveryoulike, and what's the problem?
        
               | neeleshs wrote:
               | same here. Been using python/pip for 10+ years and this
               | was never a problem. In the java world, there is jar
               | hell, but it was never a crippling issue, but a minor
               | annoyance once a year or so.
               | 
               | In general, is dependency management such a massive
               | problem it is made to be on HN? Maybe people here are
               | doing far more complex/different things than I've done in
               | the past 20 years
        
               | arp242 wrote:
               | I guess that depends from your perspective. I'm not a
               | Python developer, but like many people I do want to run
               | Python programs from time to time.
               | 
               | I don't really know Rust, or Cargo, but I never have
               | trouble building any Rust program: "cargo build
               | [--release]" is all I need to know. Easy. Even many C
               | programs are actually quite easy: "./configure", "make",
               | and optionally "make install". "./configure" has a nice "
               | --help". There is a lot to be said about the ugly
               | generated autotools soup, but the UX for people just
               | wanting to build/run it without in-depth knowledge of the
               | system is actually quite decent. cmake is a regression
               | here.
               | 
               | With Python, "pip install" gives me an entire screen full
               | of errors about venv and "externally managed" and
               | whatnot. I don't care. I just want to run it. I don't
               | want a bunch of venvs, I just want to install or run the
               | damn program. I've taken to just use "pip install
               | --break-system-packages", which installs to ~/.local. It
               | works _shrug_.
               | 
               | Last time I wanted to just run a project with a few small
               | modifications I had a hard time. I ended up just editing
               | ~/.local/lib/python/[...] Again, it worked so whatever.
               | 
               | All of this is really where Python and some other
               | languages/build systems fail. Many people running this
               | are not $language_x programmers or experts, and I don't
               | want to read up on every system I come across. That's not
               | a reasonable demand.
               | 
               | Any system that doesn't allow non-users of that language
               | to use it in simple easy steps needs work. Python's
               | system is one such system.
        
               | simonw wrote:
               | "I don't want a bunch of venvs"
               | 
               | That's your problem right there.
               | 
               | Virtual environments are the Python ecosystem's solution
               | to the problem of wanting to install different things on
               | the same machine that have different conflicting
               | requirements.
               | 
               | If you refuse to use virtual environments and you install
               | more than one separate Python project you're going to run
               | into conflicting requirements and it's going to suck.
               | 
               | Have you tried pipx? If you're just installing Python
               | tools (and not hacking on them yourself) it's fantastic -
               | it manages separate virtual environments for each of your
               | installations without you having to think about them (or
               | even know what a virtual environment is).
        
               | arp242 wrote:
               | Managing a farm of virtualenvs and mucking about with my
               | PATH doesn't address the user-installable problem at all.
        
             | est wrote:
             | Deps in CPython are more about .so/.dll problem, not much
             | can be done since stuff happens outside python itself.
        
         | GTP wrote:
         | I don't get how this optional static typing works. I had a
         | quick look at [1], and it begins with a note saying that
         | Python's runtime doesn't enforce types, leaving the impression
         | that you need to use third-party tools to do actual type
         | checking. But then it continues just like Python does the
         | check. Consider that I'm not a Python programmer, but the main
         | reason I stay away from it is the lack of a proper type system.
         | If this is going to change, I might reconsider it.
         | 
         | [1] https://docs.python.org/3/library/typing.html
        
           | wk_end wrote:
           | The interpreter does not and probably never will check types.
           | The annotations are treated as effectively meaningless at
           | runtime. External tools like mypy can be run over your code
           | and check them.
        
           | davepeck wrote:
           | Third party tools (mypy, pyright, etc) are expected to check
           | types. cpython itself does not. This will run just fine:
           | 
           | python -c "x: int = 'not_an_int'"
           | 
           | My opinion is that with PEP 695 landing in Python 3.12, the
           | type system itself is starting to feel robust.
           | 
           | These days, the python ecosystem's key packages all tend to
           | have extensive type hints.
           | 
           | The type checkers are of varying quality; my experience is
           | that pyright is fast and correct, while mypy (not having the
           | backing of a Microsoft) is slower and lags on features a
           | little bit -- for instance, mypy still hasn't finalized
           | support for PEP 695 syntax.
        
           | zitterbewegung wrote:
           | Optional static typing is just like a comment (real term is
           | annotation) of the input variable(s) and return variable(s).
           | No optimization is performed. Using a tool such as mypy that
           | kicks off on a CI/CD process technically enforces types but
           | they are ignored by the interpreter unless you make a syntax
           | error.
        
             | nine_k wrote:
             | A language server in your IDE kicks in much earlier, and is
             | even more helpful.
        
           | sveiss wrote:
           | The parser supports the type hint syntax, and the standard
           | library provides various type hint related objects.
           | 
           | So you can do things like "from typing import Optional" to
           | bring Optional into scope, and then annotate a function with
           | -> Optional[int] to indicate it returns None or an int.
           | 
           | Unlike a system using special comments for type hints, the
           | interpreter will complain if you make a typo in the word
           | Optional or don't bring it into scope.
           | 
           | But the interpreter doesn't do anything else; if you actually
           | return a string from that annotated function it won't
           | complain.
           | 
           | You need an external third party tool like MyPy or Pyre to
           | consume the hint information and produce warnings.
           | 
           | In practice it's quite usable, so long as you have CI
           | enforcing the type system. You can gradually add types to an
           | existing code base, and IDEs can use the hint information to
           | support code navigation and error highlighting.
        
           | nine_k wrote:
           | At MPOW most Python code is well-type-hinted, and mypy and
           | pyright are very helpful at finding issues, and also for
           | stuff like code completion and navigation, e.g. "go to the
           | definition of the type of this variable".
           | 
           | Works pretty efficiently.
           | 
           | BTW, Typescript also does not enforce types at runtime. Heck,
           | C++ does not enforce types at runtime either. It does not
           | mean that their static typing systems don't help during at
           | development time.
        
             | GTP wrote:
             | > BTW, Typescript also does not enforce types at runtime.
             | Heck, C++ does not enforce types at runtime either. It does
             | not mean that their static typing systems don't help during
             | at development time.
             | 
             | Speaking of C here as I don't have web development
             | experience. The static type system does help, but in this
             | case, it's the compiler doing the check at compile time to
             | spare you many surprises at runtime. And it's part of the
             | language's standard. Python itself doesn't do that. Good
             | that you can use external tools, but I would prefer if this
             | was part of Python's spec.
             | 
             | Edit: these days I'm thinking of having a look at Mojo, it
             | seems to do what I would like from Python.
        
           | VeejayRampay wrote:
           | python will never be "properly typed"
           | 
           | what it has is "type hints" which is way to have richer
           | integration with type checkers and your IDE, but will never
           | offer more than that as is
        
             | hot_gril wrote:
             | It is properly typed: it has dynamic types :)
        
               | GTP wrote:
               | Then we have very different ideas of what proper typing
               | is :D Look at this function, can you tell me what it
               | does?                 def plus(x, y):         return x+y
               | 
               | If your answer is among the lines of "It returns the sum
               | x and y" then I would ask you who said that x and y are
               | numbers. If these are strings, it concatenates them. If
               | instead you pass a string and a number, you will get a
               | runtime exception. So not only you can't tell what a
               | function does just by looking at it, you can't even know
               | if the function is correct (in the sense that will not
               | raise an exception).
        
               | hot_gril wrote:
               | When is the last time you had a bug IRL caused by passing
               | the wrong kind of thing into plus(x, y), which your tests
               | didn't catch?
        
               | andrewaylett wrote:
               | It calls x.__add__(y).
               | 
               | Python types are strictly specified, but also dynamic.
               | You don't need _static_ types in order to have _strict_
               | types, and indeed just because you 've got static types
               | (in TS, for example) doesn't mean you have strict types.
               | 
               | A Python string is always a string, nothing is going to
               | magically turn it into a number just because it's a
               | string representation of a number. The same (sadly) can't
               | be said of Javascript.
        
               | nequo wrote:
               | Both Haskell and OCaml can raise exceptions for you, yet
               | most people would say that they are properly typed.
               | 
               | The plus function you wrote is not more confusing than
               | any generic function in a language that supports that.
        
           | hot_gril wrote:
           | I think static typing is a waste of time, but given that you
           | want it, I can see why you wouldn't want to use Python. Its
           | type-checking is more half-baked and cumbersome than other
           | languages, even TS.
        
             | baq wrote:
             | Typescript is pretty much the gold standard, it's amazing
             | how much JavaScript madness you can work around just on the
             | typechecking level.
             | 
             | IMHO Python should shamelessly steal as much typescript's
             | typing as possible. It's tough since the Microsoft
             | typescript team is apparently amazing at what they do so
             | for now it's a very fast moving target but some day...
        
               | hot_gril wrote:
               | Well the TS tooling is more painful in ways. It's not
               | compatible with some stuff like the NodeJS profiler. Also
               | there's some mess around modules vs "require" syntax that
               | I don't understand fully but TS somehow plays a role.
        
             | GTP wrote:
             | I instead think that the lack of static typing is a waste
             | of time, since without it you can have programs that waste
             | hours of computation due to an exception that would have
             | been prevented by a proper type system ;)
        
             | nine_k wrote:
             | I used to think like that until I tried.
             | 
             | There are areas where typing is more important: public
             | interfaces. You don't have to make every piece of your
             | program well-typed. But signatures of your public functions
             | / methods matter a lot, and from them types of many
             | internal things can be inferred.
             | 
             | If your code has a well-typed interface, it's pleasant to
             | work with. If interfaces of the libraries you use are well-
             | typed, you have easier time writing your code (that
             | interacts with them). Eventually you type more and more
             | code you write and alter, and keep reaping the benefits.
        
               | hot_gril wrote:
               | I shouldn't have said it's a waste of time period, cause
               | every project I work on _does_ have static typing in two
               | very important places: the RPC or web API (OpenAPI, gRPC,
               | whatever it is), and the relational database. But not in
               | the main JS or Py code. That 's all I've ever needed.
               | 
               | I did try migrating a NodeJS backend to TS along with a
               | teammate driving that effort. We caught absolutely 0
               | additional bugs with the new type-checking in place, and
               | the extra time we spent on that stuff could've gone into
               | better testing instead. So it actually made things more
               | dangerous.
        
               | simonw wrote:
               | This was the thing that started to bring me around to
               | optional typing as well. It makes the most sense to me as
               | a form of documentation - it's really useful to know what
               | types are expected (and returned) by a Python function!
               | 
               | If that's baked into the code itself, your text editor
               | can show inline information - which saves you from having
               | to go and look at the documentation yourself.
               | 
               | I've started trying to add types to my libraries that
               | expose a public API now. I think it's worth the extra
               | effort just for the documentation benefit it provides.
        
         | alfalfasprout wrote:
         | The conda-forge ecosystem is making big strides in dependency
         | management. No more are we stuck with the abysmal pip+venv
         | story.
        
         | ramses0 wrote:
         | You forgot:                   [X] print requires parentheses
        
         | VeejayRampay wrote:
         | the efficient dependency management is coming, the good people
         | of astral will take care of that with the uv-backed version of
         | rye (initially created by Armin Ronacher with inspirations from
         | Cargo), I'm really confident it'll be good like ruff and uv
         | were good
        
         | agumonkey wrote:
         | I'm eager to see what a simple JIT can bring to computing
         | energy savings on python apps.
        
       | eigenvalue wrote:
       | Really excited for this. Once some more time goes by and the most
       | important python libraries update to support no GIL, there is
       | just a tremendous amount of performance that can be automatically
       | unlocked with almost no incremental effort for so many
       | organizations and projects. It's also a good opportunity for new
       | and more actively maintained projects to take market share from
       | older and more established libraries if the older libraries don't
       | take making these changes seriously and finish them in a timely
       | manner. It's going to be amazing to saturate all the cores on a
       | big machine using simple threads instead of dealing with the
       | massive overhead and complexity and bugs of using something like
       | multiprocessing.
        
         | phkahler wrote:
         | I feel like most things that will benefit from moving to
         | multiple cores for performance should probably not be written
         | in Python. OTH "most" is not "all" so it's gonna be awesome for
         | some.
        
           | MBCook wrote:
           | But it would give you more headroom before rewriting for
           | performance would make sense right? That alone could be
           | beneficial to a lot of people.
        
           | DanielVZ wrote:
           | Usually performance critical code is written in cpp, fortran,
           | etc, and then wrapped in libraries for Python. Python still
           | has a use case for glue code.
        
       | mihaic wrote:
       | Does anyone know if there is more serious single threaded
       | performance degradation (more than a few percent for instance)? I
       | couldn't find any benchmarks, just some generic reassurance that
       | everything is fine.
        
         | ngoldbaum wrote:
         | Right now there is a significant single-threaded performance
         | cost. Somewhere from 30-50%. Part of what my colleague Ken Jin
         | and others are working on is getting back some of that lost
         | performance by applying some optimizations. Expect single-
         | threaded performance to improve for Python 3.14 next year.
        
           | arp242 wrote:
           | To be honest, that seems a lot. Even today a lot of code is
           | single-threaded, and this performance hit will also affect a
           | lot of code running in parallel today.
           | 
           | There have been patches to remove the GIL going back to the
           | 90s and Python 1.5 or thereabouts. But the performance impact
           | has always been the show-stopper.
        
             | ngoldbaum wrote:
             | It's an experimental release in 3.13, definitely no where
             | near final. Another example: objects that will have
             | deffered reference counts in 3.14 are made immortal in 3.13
             | to avoid scaling issues from reference count thrashing.
             | This wasn't originally the plan but deferred reference
             | counting didn't land in time for 3.13. It will be several
             | years before free-threading becomes the default, at that
             | point there will no longer be any single-threaded
             | performance drop. Of course that assumes everything shakes
             | out as planned, we'll see.
        
         | deschutes wrote:
         | To my understanding there is and there isn't. The driving force
         | behind this demonstrated that it was possible to speed up the
         | existing CPython interpreter by more than the performance cost
         | of free threading with changes to the allocator and various
         | other things.
         | 
         | So the net is actually a small performance win but lesser than
         | if there was no free threading. That said, many of the
         | techniques he identified were immediately incorporated into
         | CPython and so I would expect benchmarks to show some
         | regression as compared with the single threaded interpreter of
         | the previous revision.
        
       | Sparkyte wrote:
       | My body is ready. I love python because the ease of writing and
       | logic. Hopefully the more complicated free-threaded approach is
       | comprehensive enough to write it like we traditionally write
       | python. Not saying it is or isn't I just haven't dived enough
       | into python multithreading because it is hard to put those demons
       | back once you pull them out.
        
         | ZhongXina wrote:
         | Precisely, ease of _writing_ , not ease of reading (the whole
         | project, not just a tiny snippet of code) or supporting it
         | long-term.
        
         | ameliaquining wrote:
         | The semantic changes are negligible for authors of Python code.
         | All the complexity falls on the maintainers of the CPython
         | interpreter and on authors of native extension modules.
        
           | stavros wrote:
           | Well, I'm not looking forward to the day when I upgrade my
           | Python and suddenly I have to debug a ton of fun race
           | conditions.
        
             | teaearlgraycold wrote:
             | It's kept behind a flag. Hopefully will be forever.
        
         | hot_gril wrote:
         | What are the common use cases for threading in Python? I feel
         | like that's a lower level tool than most Python projects would
         | want, compared to asyncio or multiprocessing.Pool. JS is the
         | most comparable thing to Python, and it got pretty darn far
         | without threads.
        
           | BugsJustFindMe wrote:
           | Working with asyncio sucks when all you want is to be able to
           | do some things in the background, possibly concurrently. You
           | have to rewrite the worker code using those stupid async
           | await keywords. It's an obnoxious constraint that completely
           | breaks down when you want to use unaware libraries. The
           | thread model is just a million times easier to use because
           | you don't have to change the code.
        
             | hot_gril wrote:
             | Asyncio is designed for things like webservers or UIs where
             | some framework is probably already handling the main event
             | loop. What are you doing where you just want to run
             | something else in the background, and IPC isn't good
             | enough?
        
               | BugsJustFindMe wrote:
               | Non-blocking HTTP requests is an extremely common need,
               | for instance. Why the hell did we need to reinvent
               | special asyncio-aware request libraries for it? It's
               | absolute madness. Thread pools are much easier to work
               | with.
               | 
               | > _where some framework is probably already handling the
               | main event loop_
               | 
               | This is both not really true and also irrelevant. When
               | you need a flask (or whatever) request handler to do
               | parallel work, asyncio is still pretty bullshit to use vs
               | threads.
        
               | hot_gril wrote:
               | Non-blocking HTTP request is the bread and butter use
               | case for asyncio. Most JS projects are doing something
               | like this, and they don't need to manage threads for it.
               | You want to manage your own thread pool for this, or are
               | you going to spawn and kill a thread every time you make
               | a request?
        
               | BugsJustFindMe wrote:
               | > _Non-blocking HTTP request is the bread and butter use
               | case for asyncio_
               | 
               | And the amount of contorting that has to be done for it
               | in Python would be hilarious if it weren't so sad.
               | 
               | > _Most JS projects_
               | 
               | I don't know what JavaScript does, but I do know that
               | Python is not JavaScript.
               | 
               | > _You want to manage your own thread pool for this..._
               | 
               | In Python, concurrent futures' ThreadPoolExecutor is
               | actually nice to use and doesn't require rewriting
               | existing worker code. It's already done, has a clean
               | interface, and was part of the standard library before
               | asyncio was.
        
               | stavros wrote:
               | I feel you. I know asyncio is "the future", but I usually
               | just want to write a background task, and really hate all
               | the gymnastics I have to do with the color of my
               | functions.
        
               | BugsJustFindMe wrote:
               | I feel like "asyncio is the future" was invented by the
               | same people who think it's totally normal to switch to a
               | new javascript web framework every 6 months.
        
               | hot_gril wrote:
               | ThreadPoolExecutor is the most similar thing to asyncio:
               | It hands out promises, and when you call .result(), it's
               | the same as await. JS even made its own promises
               | implicitly compatible with async/await. I'm mentioning
               | what JS does because you're describing a very common JS
               | use case, and Python isn't all that different.
               | 
               | If you have async stuff happening all over the place,
               | what do you use, a global ThreadPoolExecutor? It's not
               | bad, but a bit more cumbersome and probably less
               | efficient. You're running multiple OS threads that are
               | locking, vs a single-threaded event loop.
               | 
               | Also, I was originally asking about free threads. GIL
               | isn't a problem if you're just waiting on I/O. If you
               | want to compute on multiple cores at once, there's
               | multiprocessing, or more likely you're using stuff like
               | numpy that uses C threads anyway.
        
               | BugsJustFindMe wrote:
               | > _Python isn 't all that different_
               | 
               | Again, Python's implementation of asyncio does not allow
               | you to background worker code without explicitly altering
               | that worker code to be aware of asyncio. Threads do. They
               | just don't occupy the same space.
               | 
               | > _there 's multiprocessing_
               | 
               | Eh, the obvious reason to not want to use separate
               | processes is a desire for some kind of shared state
               | without the cost or burden of IPC.
        
               | kristjansson wrote:
               | You don't? concurrent.futures.ThreadPoolExecutor can get
               | a lot done without touching async code.
        
               | BugsJustFindMe wrote:
               | I am a big advocate for ThreadPoolExecutor. I'm saying
               | it's superior to asyncio. The person I'm responding to
               | was asking why use threads when you can use asyncio
               | instead.
        
           | bongodongobob wrote:
           | Same as any other language. Separating UI from calculations
           | is my most common need for it.
        
       | vldmrs wrote:
       | Great news ! It would be interesting to see performance
       | comparison for IO-bound tasks like http requests between single-
       | threaded asyncio code and multi-threaded asyncio
        
       | discreteevent wrote:
       | I remember back around 2007 all the anxious blog posts about the
       | free lunch (Moore's law) being over. Parallelism was mandatory
       | now. We were going to need exotic solutions like software
       | transactional memory to get out of the crisis (and we could
       | certainly forget about object orientation).
       | 
       | Meanwhile what takes the crown? - Single threaded python.
       | 
       | (Well, ok Rust looks like it's taking first place where you
       | really need the speed and it does help parallelism without
       | requiring absolute purity)
        
       | elijahbenizzy wrote:
       | I'm really curious to see how this will work with async. There's
       | a natural barrier (I/O versus CPU-bound code), which isn't always
       | a perfect distinction.
       | 
       | I'd love to see a more fluid model between the two -- E.G. if I'm
       | doing a "gather" on CPU-bound coroutines, I'm curious if there's
       | something that can be smart enough to JIT between async and
       | multithreaded implementations.
       | 
       | "Oh, the first few tasks were entirely CPU-bound? Cool, let's
       | launch another thread. Oh, the first few threads were I/O-bound?
       | Cool, let's use in-thread coroutines".
       | 
       | Probably not feasible for a myriad of reasons, but even a more
       | fluid programming model could be really cool (similar interfaces
       | with a quick swap between?).
        
       | anacrolix wrote:
       | Was ready for this 15 years ago when I loved Python and regularly
       | contributed. At the time, nobody wanted to do it and I got bored
       | and went to Go.
        
       | throwaway5752 wrote:
       | GVR, you are sorely missed, though I hope you are enjoying life.
        
       | gnatolf wrote:
       | Good to hear. The authors are touching on the journey it is to
       | make Cython continue to work. I wonder how hard it'll be to
       | continue to provide bdist packages, or within what timeframe, if
       | at all, Cython can transparently ensure correctness for a no-gil
       | build. Anyone got any insights?
        
       ___________________________________________________________________
       (page generated 2024-07-12 23:00 UTC)