This is sadly how things are in CPython, mainly due to the Global Interpreter Lock (GIL). Python code that’s CPU-bound simply doesn’t scale across threads (I/O-bound code, on the other hand, might scale to some extent).
There is a highly informative presentation by David Beazley where he discusses some of the issues surrounding the GIL. The video can be found here (thanks @Ikke!)
My recommendation would be to use the
multiprocessing module instead of multiple threads.