python - 为什么 Python 3 http.client 比 python-requests 快这么多?

标签 python http python-requests

我今天正在测试不同的 Python HTTP 库,我意识到 http.client库似乎比 requests 执行得快得多.

要测试它,您可以运行以下两个代码示例。

import http.client

conn = http.client.HTTPConnection("localhost", port=8000)
for i in range(1000):
    conn.request("GET", "/")
    r1 = conn.getresponse()
    body = r1.read()
    print(r1.status)

conn.close()

这里是用 python-requests 做同样事情的代码:

import requests

with requests.Session() as session:
    for i in range(1000):
        r = session.get("http://localhost:8000")
        print(r.status_code)

如果我启动 SimpleHTTPServer:

> python -m http.server

并运行上面的代码示例(我使用的是 Python 3.5.2)。我得到以下结果:

http.客户端:

0.35user 0.10system 0:00.71elapsed 64%CPU 

python 请求:

1.76user 0.10system 0:02.17elapsed 85%CPU 

我的测量和测试是否正确?你也能复制它们吗?如果是,有没有人知道 http.client 内部发生了什么让它变得更快?为什么处理时间会有这么大的差异?

最佳答案

基于对两者的分析,主要区别似乎是 requests 版本为每个请求执行 DNS 查找,而 http.client 版本这样做一次。

# http.client
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1974    0.541    0.000    0.541    0.000 {method 'recv_into' of '_socket.socket' objects}
     1000    0.020    0.000    0.045    0.000 feedparser.py:470(_parse_headers)
    13000    0.015    0.000    0.563    0.000 {method 'readline' of '_io.BufferedReader' objects}
...

# requests
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1481    0.827    0.001    0.827    0.001 {method 'recv_into' of '_socket.socket' objects}
     1000    0.377    0.000    0.382    0.000 {built-in method _socket.gethostbyname}
     1000    0.123    0.000    0.123    0.000 {built-in method _scproxy._get_proxy_settings}
     1000    0.111    0.000    0.111    0.000 {built-in method _scproxy._get_proxies}
    92000    0.068    0.000    0.284    0.000 _collections_abc.py:675(__iter__)
...

您将主机名提供给 http.client.HTTPConnection() 一次,因此调用一次 gethostbyname 是有意义的。 requests.Session 可能可以缓存主机名查找,但显然不能。

编辑:经过进一步研究,这不仅仅是缓存的简单问题。有一个函数用于确定是否绕过最终调用 gethostbyname 的代理,而不考虑实际请求本身。

关于python - 为什么 Python 3 http.client 比 python-requests 快这么多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39435443/

相关文章:

python 和 python3 命令没有指向 pyenv 全局版本

python - 在 Python Selenium 中创建页面倒计时

c - C 中的 HTTP : Why do I have to call recv() multiple times?

jquery - 无法使用 JQUERY 及其 JSON REST API 创建 Rally 缺陷

python-3.x - python : request dependency idna failed "ImportError: No module named idna"

python - 摧毁一个 Flask Restful token

python - 使用python代码而不是html更改QLabel颜色?

http - API 何时应抛出 4xx 状态代码(错误),何时抛出 5xx?

python - 类型错误 : cannot unpack non-iterable bool object

python - 如何在Python中的请求中禁用代理socks5?