What are the differences between a \"coroutine\" and a \"thread\"?
In a word: preemption. Coroutines act like jugglers that keep handing off to each other a well-rehearsed points. Threads (true threads) can be interrupted at almost any point and then resumed later. Of course, this brings with it all sorts of resource conflict issues, hence Python's infamous GIL - Global Interpreter Lock.
Many thread implementations are actually more like coroutines.