Comment by Spivak
Of all the responses, this was perhaps my least expected one when I was talking about being chained to an async framework. Async isn't a replacement for threads, async doesn't let you spread your work out over multiple cores and doesn't give you time slicing. In Python the asyncio module actually gives you a threadpool to run computationally intensive work in as kind of one-offs. But when you need something like background job processing and want to also reap the benefits of asyncio, like being able to pull multiple tasks off the queue, and progress on others while a job does io, then you need an event loop in the other thread. It was specifically avoiding locking up FastAPI that lead me to use multiple event loops in the first place.
You're free to spin the job worker off to another process but however you swing it it's still multiple event loops you deal with. But with threads you get to only load your Python app into memory once.
Skipping to the end here: if you're inside a Python thread and you're making your own event loop, something has gone badly. Maybe you made a bad choice (using threads inside an async task instead of an executor), maybe you have some legacy nightmare dependency thing to deal with, but multiple event loops, let alone nested event loops, are suboptimal from a resource usage standpoint.