Raw multi-threading was always a "blowing your feet of" feature in almost any way imaginable. That's true for Python as well and not only for use together with asyncio (but in this context even more so, I agree).
No one should write production MT code based on pthread-esque abstractions in any language without knowing very very well what they're doing.
I think you're right. I have python threads and processes meshed together in production code, and it's not pretty to look at. Sometimes it would crash for no reason, like this morning, when a job got stuck because one of its child process refused to die properly, thus blocking the join.
Due to the GIL and resulting coarse-grained nature of Python threading, it was very easy to write Python code that accidentally worked most of the time.
Interpreter instructions in CPython are atomic (due to the GIL, actually) and calling into extension functions is a single instruction (incidentally). This makes it impossible to corrupt built-in data structures, even if no locks are used. In some simple cases this is sufficient, esp. if no one's going to run it with !CPython...
This is also neat for other reasons (think sandboxing).
That's the main issue. You can work with asyncio and threads at the same time but you need to know very well how the frameworks work.