Asyncio is weird. But check out Trio, an alternative and easier-to-understand async framework:
https://trio.readthedocs.io/en/stable/tutorial.htmlTrio solves a problem that threading does not: switching between tasks only happens at deterministic points (they don't run in parallel), and tasks are in a hierarchy so that exceptions are handled in reasonable ways (and you can do a lot of other associated cool things like cancel an entire tree of tasks).
Python has a GIL, so you're not getting parallel Python code anyway without multiprocessing.
This means that if I'm writing code that implements, like, a basic network server, by far the easiest way to do it is Trio. Unlike with threading (in Python or any other language) I don't have to worry about locks from concurrent access / tasks switching at unexpected points, and unlike with e.g. the select module, handling both directions of communication and multiple connections is doable with normal straight-line code instead of weird state machines.
It's not needed, yes, but neither is Python itself. You could just write C.