Async code has its traps, but they are very managable once you've learned them. I haven't found them on the level of manual memory management which is a footgun that even experienced devs keep firing.
The benefits are also there, doing slow things in parallel like HTTP calls or database queries is trivial with async code and trickier in sync code.
Of course you prefer sync code when you don't need it, but async/await style code doesn't prevent sync code. If you only support sync doing anything async because very cumbersome and dangerous, and doing so requires things like managing threads or locks yourself which is an even greater recipe for bugs.
You can of course do parallel HTTP calls or database queries with Python's existing threads (IO releases the GIL in Python) or via multiprocessing.
You don't have to use locks either - straight parallelism can be done very easily with the Executors in concurrent.futures. There are a lot of good concurrency primitives in the threading library in the stdlib including conditions, semaphores and barriers. Of course best to avoid parallelism with shared data if at all possible (and IMO it doesn't really come up much).
Async code has its traps, but they are very managable once you've learned them. I haven't found them on the level of manual memory management which is a footgun that even experienced devs keep firing.
The benefits are also there, doing slow things in parallel like HTTP calls or database queries is trivial with async code and trickier in sync code.
Of course you prefer sync code when you don't need it, but async/await style code doesn't prevent sync code. If you only support sync doing anything async because very cumbersome and dangerous, and doing so requires things like managing threads or locks yourself which is an even greater recipe for bugs.