In asyncio and in most other asynchronous frameworks for Python, threads aren&#x27;t usually involved.<p>Your Python interpreter is doing one thing at a time. However, a function can get to a statement that needs to wait for something <i>outside</i> of the interpreter -- usually I&#x2F;O, but it could also be a timer.<p>What happens at that point isn&#x27;t thread-switching. The function gets suspended and control goes elsewhere in the program, just like if you yielded from a generator. (It&#x27;s the same mechanism.) The function can be woken up again by feeding it the data it was waiting for -- the asyncio main loop is responsible for this.<p>If you actually want your processor to do more things at the same time, though, asyncio&#x27;s model of asynchronous computing isn&#x27;t going to do it. Python programmers are afraid of threads (I mean, they have a lot of disadvantages and not much benefit in Python, due to the GIL), so they&#x27;ll tend to use multiple processes for that, instead of threads.<p>EDIT: But at this point I realize you&#x27;re asking about a much more specific thing in the article. This article is asking you to not be afraid of combining threads and asyncio. It&#x27;s suggesting that a useful asynchronous thing you can do is to spawn a thread, perform a computation in it, and wait for the result.<p>At this point you do need to worry about the GIL. C extensions can release the GIL, so the article suggests you use one of those (NumPy).