一、背景与目标
需要在同一个 Python 项目中同时支持:
- Elasticsearch 8.x / 9.x
- Easysearch(ES 兼容)
用户在前端选择搜索引擎后,后端要能正确连接并执行 DSL,且要处理 HTTPS 自签名证书等常见问题。
二、核心结论(先给结论)
| 方案 |
|---|
总结了在 Python 项目中同时适配 Elasticsearch 与 Easysearch 的解决方案。核心问题在于 elasticsearch-py 7.14 及以上版本增加了产品校验,会拒绝 Easysearch 等非官方分布。推荐使用 elasticsearch==7.13.1 作为唯一客户端,该版本无产品校验且兼容性好。此外,针对 NumPy 2.0 移除 np.float_/int_ 的问题提供了兼容补丁,并给出了 HTTPS 自签名证书的配置方法。相比双客户端或引入 opensearch-py,单客户端 7.13.1 方案维护成本最低,API 稳定。
需要在同一个 Python 项目中同时支持:
用户在前端选择搜索引擎后,后端要能正确连接并执行 DSL,且要处理 HTTPS 自签名证书等常见问题。
| 方案 |
|---|
| 适用场景 |
|---|
| 优缺点 |
|---|
| elasticsearch 7.13.1 | 同时连 ES 和 Easysearch | 无产品校验,兼容性好,需 NumPy 2.0 兼容补丁 |
| elasticsearch 8.x/9.x | 仅连接官方 Elasticsearch | 有产品校验,会拒绝 Easysearch |
| opensearch-py | 仅连 Easysearch/OpenSearch | 需多一个依赖,增加复杂度 |
推荐做法:
使用 elasticsearch==7.13.1 作为唯一客户端,可同时连接 Elasticsearch 8.x/9.x 和 Easysearch。

从 elasticsearch-py 7.14 起,客户端会校验服务端是否为'官方 Elasticsearch',连接 Easysearch、OpenSearch 等会抛出类似:
UnsupportedProductError / "The client noticed that the server is not a supported distribution of Elasticsearch"

官方文档明确说明:

所以若希望同一套代码同时支持 ES 和 Easysearch,应锁定到 7.13.1。
NumPy 2.0 移除了 np.float_ 和 np.int_,而 elasticsearch 7.13 仍在使用,需要在导入 elasticsearch 之前做兼容:
import numpy as _np
if not hasattr(_np, "float_"):
_np.float_ = _np.float64
if not hasattr(_np, "int_"):
_np.int_ = _np.int64
from elasticsearch import Elasticsearch
这样在 NumPy 2.0 下也能正常使用。
使用 HTTPS 且证书自签名时,常见错误:
SSLError: certificate verify failed: self-signed certificate in certificate chain
处理方式:在创建客户端时关闭证书校验(仅适合内网 / 自建环境):
kwargs = {
"hosts": [{"host": host, "port": port, "scheme": scheme}],
"timeout": 30,
"max_retries": 3,
"retry_on_timeout": True,
}
if scheme == "https" and not verify_certs:
kwargs["verify_certs"] = False
# 如 7.x 的默认 Transport 仍报错,可改用 RequestsHttpConnection
from elasticsearch import RequestsHttpConnection
client = Elasticsearch(
hosts=hosts,
connection_class=RequestsHttpConnection,
http_auth=http_auth,
use_ssl=True,
verify_certs=False,
timeout=30,
)
并配合 urllib3.disable_warnings() 抑制 SSL 告警。
elasticsearch==7.13.1
numpy<2 # 若使用 NumPy 2.0,则需上面的补丁
requests>=2.26.0
elasticsearch>=8opensearch-py问题:两个包、两套 API、分支多,维护成本高,我也明确不希望引入 opensearch。

尝试在 8.x 中通过自定义 Transport 或 monkey-patch 禁用产品校验。
问题:依赖非官方实现,升级风险大,不够稳妥。
elasticsearch==7.13.1结论:方案 C 最符合当前需求。
# 1. NumPy 兼容(若使用 NumPy 2.0)
import numpy as _np
if not hasattr(_np, "float_"):
_np.float_ = _np.float64
if not hasattr(_np, "int_"):
_np.int_ = _np.int64
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk as helpers_bulk
def create_es_client(host, port, scheme="http", http_auth=None, verify_certs=True):
hosts = [{"host": host, "port": port, "scheme": scheme}]
kwargs = {
"hosts": hosts,
"timeout": 30,
"max_retries": 3,
"retry_on_timeout": True,
}
if http_auth:
kwargs["http_auth"] = http_auth
if scheme == "https" and not verify_certs:
kwargs["verify_certs"] = False
try:
client = Elasticsearch(**kwargs)
except TypeError:
# 某些 7.x 版本参数不同
kwargs.pop("verify_certs", None)
from elasticsearch import RequestsHttpConnection
import urllib3
urllib3.disable_warnings()
client = Elasticsearch(
hosts=hosts,
connection_class=RequestsHttpConnection,
http_auth=http_auth,
use_ssl=True,
verify_certs=False,
timeout=30,
)
if not client.ping():
client.info() # 兜底
return client
前端/配置中只需区分 product: "elasticsearch" 或 "easysearch",后端都用同一套 elasticsearch 7.13.1 客户端即可。
elasticsearch==7.13.1 可同时支持 Elasticsearch 8.x/9.x 和 Easysearch。np.float_ / np.int_。verify_certs=False,必要时用 RequestsHttpConnection。如果后续需要同时使用 8.x 的新特性并支持 Easysearch,再考虑引入 opensearch-py 或按产品类型切换不同客户端会比较合适;目前以兼容性和维护成本为主时,7.13.1 单客户端方案是更稳妥的选择。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online