1. 所有异步函数在主线程里使用,所有耗时的同步函数在子线程里使用
  2. Django ASGIHandler 自动区分了这一点,因此不用担心同步 View 和异步 View 混用的问题
  3. Python 异步模型类似于 JavaScript 的 Promise 模型(调用异步函数返回一个对象,可以向对象查询执行结果、或者 await),但有一点区别是,Python 创建的 coroutine 对象只有在被 awaitcreate_task 调用时才会被执行,而 JavaScript 的 Promise 对象在创建时就会立即执行。

# 为什么异步卡住了

大概率是主线程在运行 I/O 阻塞的代码(如 time.sleep()requests.get()、大文件 f.read())。因为 Python 兼容性问题,还有大量代码是使用阻塞 I/O 的。

注意一个坑点:asgiref.sync.sync_to_async 这个函数可以把同步函数转换为异步函数,但它有一个参数 thread_sensitive,默认值为 True,表示如果同步函数是线程敏感的(如使用了线程锁、Django ORM),则会在子线程中运行,否则会在主线程中运行。这个参数的默认值可能会导致异步函数卡住。所以如果同步函数有 I/O 阻塞的代码,需要调用 sync_to_async(func, thread_sensitive=False) 来确保它在子线程中运行,这样就等价于 loop.run_in_executor(None, func)

现在事件循环被同步函数卡住的问题还是很麻烦,没有显式的警告或错误提示,只能靠开发者的经验和对代码的熟悉程度来判断。

# 异步的好处

Async IO doesn't necessarily speeds up your code, it just reduces the server resources usage for concurrent tasks by leveraging concurrent network IO in a single-threaded application.


I think this misses the main appeal of async. It's not about speed but about the programming model. Async makes it much easier to work with and compose concurrency compared to the thread based model. Just the fact that you can cancel tasks makes it trivial to do proper timeouts, which nobody gets right in sync applications, for example. 我认为这忽略了异步的主要吸引力。异步的魅力不在于速度,而在于编程模型。与基于线程的模型相比,异步使得并发处理和编写更加容易。仅仅因为可以取消任务,就使得实现适当的超时变得轻而易举,而这在同步应用程序中是很难做到的。

It also allows things like structured concurrency. 它还允许诸如结构化并发之类的事情。

https://www.reddit.com/r/Python/comments/x9x8pb/comment/inqvsi0/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button