Note that Python does do multithreading - just the actual Python interpreter will not interpret Python code from two threads at once. If threads are busy running code that doesn't require the interpreter, whether it is CPU bound work or not, then as many threads can run as you have cores. In most CPU bound applications, the performance critical parts are not pure Python - they're calling out to some extension code such as numpy or cython or something. Such code runs in parallel in CPython if you start multiple threads.
This might have been what you meant when you said the runtime isn't really multi-threaded - but since the CPython ecosystem rests so heavily on C code, in practice multithreading is a good solution a lot of the time.
This might have been what you meant when you said the runtime isn't really multi-threaded - but since the CPython ecosystem rests so heavily on C code, in practice multithreading is a good solution a lot of the time.