It's really bad in Python, because the baseline awaitable of Python is a coroutine — same as Rust but without compiler support.
The issue of coroutine-based async is that a coroutine does not do anything until it's awaited (and the chain goes up to the reactor), so in Python when you create a coroutine nothing happens. This is unlike Javascript or C# (IIRC) where the baseline awaitable is a task, with tasks awaiting is a synchronisation point, but if you create a task and drop it the task will go and do its own thing.
In Rust, this is mitigated by `[must_use]`, so the compiler will warn you when you've created a coroutine (Future) and dropped it on the floor, not so Python, you just get a warning when the runtime shuts down, it's way harder to track missing awaits.
The issue of coroutine-based async is that a coroutine does not do anything until it's awaited (and the chain goes up to the reactor), so in Python when you create a coroutine nothing happens. This is unlike Javascript or C# (IIRC) where the baseline awaitable is a task, with tasks awaiting is a synchronisation point, but if you create a task and drop it the task will go and do its own thing.
In Rust, this is mitigated by `[must_use]`, so the compiler will warn you when you've created a coroutine (Future) and dropped it on the floor, not so Python, you just get a warning when the runtime shuts down, it's way harder to track missing awaits.