In Python it takes more thinking and structure because async isn’t built in deeply like it is with javascript.
Even so, async versus sync doesn’t feel like a nightmare in either.
Having said that, it depends entirely on how much experience you have with async programming.
Async programming is a mind bender that will throw you completely until it becomes natural. Synchronous programming feels natural and logical and async requires a completely different mental model.
I can understand why anyone forced to do async would hate it. It’s something you have to want to do.
Ha! Integrating async I/O sources, namely the OPFS API, has been the single biggest development-time hit and runtime performance hit in sqlite.org's JS/WASM build of sqlite.
As soon as a single method is async, it cannot be hidden behind a synchronous interface because the async attribute is "viral," requiring the whole API above it to be async (which sqlite is not). We instead have to move all of the async I/O into its own worker and "fake" synchronous access to it using a complex proxy built from SharedArrayBuffer and the Atomics API. It's an abomination but it's the only(?) approach for making async functions behave fully synchronously which doesn't require third-party voodoo like Asyncify.
PS: the opposite - hiding sync stuff behind an async interface - is trivial. Hiding async behind a synchronous interface, however, is a tremendous pain in the bottom in JS.
PS: it's also limited to argument and result types which we can serialize into a byte array. i.e. its utility is more limited than direct use of async APIs is, as those can accept any argument type and resolve to any type of value. That fine for the case of sqlite but it's not a general-purpose solution.