- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个 io.BytesIO()
我想写一个对坐在线程上的响应:
f = io.ByteIO()
with requests.Session() as s:
r = s.get(url, stream = True)
for chunk in r.iter_content(chunk_size = 1024):
f.write(chunk)
现在这不是在硬盘上而是在内存中(为了我的目的得到了很多),所以我不必担心针头会成为瓶颈。我知道对于阻塞 I/O(文件读/写),GIL 从 docs 中释放。而这个 SO post由 Alex Martelli 编写,但我想知道,GIL 是否只是在 f.write()
上释放,然后在循环的 __next__()
调用上重新获取?
所以我最终得到的是一堆快速的 GIL 获取和发布。显然,我必须计时才能确定任何值得注意的事情,但是在多线程网络抓取程序上写入内存文件对象通常是否支持 GIL 绕过?
如果没有,我将只处理大量响应并将它们转储到队列中并在 __main__
上处理。
最佳答案
根据我在 BytesIO
type's source code 中看到的内容,在调用 BytesIO.write
期间不会释放 GIL,因为它只是在进行快速内存复制。只有对于可能阻塞的系统调用,释放 GIL 才有意义。
r.iter_content
生成器的__next__
方法中可能有这样一个系统调用(当从套接字读取数据时),但在写入端没有.
但我认为您的问题反射(reflect)了对内置函数在执行阻塞操作时释放 GIL 意味着什么的错误理解。它会在执行可能阻塞的系统调用之前释放 GIL。但它会在返回 Python 代码之前重新获取 GIL。所以不管你在一个循环中有多少这样的 GIL 释放操作,所有涉及的 Python 代码都将在持有 GIL 的情况下运行。 GIL 永远不会被一个操作释放并被另一个操作回收。它作为一个独立的步骤针对每个操作进行释放和回收。
例如,您可以查看 the C code that implements writing to a file descriptor .宏 Py_BEGIN_ALLOW_THREADS
释放 GIL。几行之后,Py_END_ALLOW_THREADS
重新获取 GIL。在这些步骤之间没有运行 Python 级别,只有一些关于 errno
的低级 C 分配,以及可能阻塞的 write
系统调用,在磁盘上等待。
关于python - GIL 如何处理分块 I/O 读/写?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50123928/
我是一名优秀的程序员,十分优秀!