Comment by IshKebab
A painful rewrite in another language is usually the only option in my experience.
If you're really lucky you have a small hot part of the code and can move just that to another language (a la Pandas, Pytorch, etc.). But that's usually only the case for numerical computing. Most Python code has its slowness distributed over the entire codebase.
It’s not painful, that’s the point. You have a working prototype now ready to port. (If the destination language is painful perhaps, but don’t do that.)
I recently ported a Python program to Rust and it took me much less time the second time, even though I write Rust more slowly per-line. Because I knew definitively what the program needed.
And if even that is too much optimizing the Python or adding Cython to a few hot loops is less difficult.