As for threading vs. explicit yielding (e.g. coroutines), I’d say it’s a matter of taste. I generally prefer to see where code is going to yield. Something like gevent can make control flow confusing, since it’s unclear what will yield, and you need to implement explicit yielding for CPU-bound tasks anyway. Its green threads are based on greenlet, which are cooperative coroutines.
Cooperative multitasking was a big problem in operating systems, where you can’t tell whether other processes are looking for CPU time or not. But within your own code, you can control it however you want!