dm-pure:纯 Python 达梦 DM8 数据库驱动
零 native 依赖、100% Python 实现的达梦数据库驱动。支持达梦 DM8 常用功能,适合受限环境(无编译工具/无法加载 native 库的机器)。
特性
- ✅ 连接:DH 密钥交换 + DES-CFB 加密登录(内置纯 Python 加密,零依赖)
- ✅ 查询:SELECT / INSERT / UPDATE / DELETE,支持参数绑定(含 NULL)
- ✅ 类型:INT / BIGINT / DECIMAL / DATE / TIME / DATETIME / FLOAT / 中文等
- ✅ 字符集:自动检测服务器编码(GB18030 / UTF-8 / EUC-KR),也可手动指定,中文读写不乱码
- ✅ 大结果集:分批 fetch(cmd=7)
- ✅ LOB:CLOB / BLOB 读写(含大 LOB 分段传输)
- ✅ 事务:begin / commit / rollback / 隔离级别
- ✅ 存储过程:CALL + IN/OUT 参数
- ✅ 批量插入:executemany(协议级 batch)
- ✅ 连接池:线程安全,自动重连
- ✅ DB-API 2.0 兼容层:惰性游标(fetchone/fetchmany/fetchall 按需拉取)
- ✅ 健壮性:超时控制、断线重连、错误码表
安装
pip install dm-pure
零依赖:加密算法(DES/AES/RC4)内置纯 Python 实现。若环境已安装 pycryptodome 会自动优先使用(性能更优),否则用内置实现,功能完全一致。
快速上手
底层 API
from dmpy import DMClient
c = DMClient("127.0.0.1", 5236, "SYSDBA", "password") # 默认自动检测服务器字符集
c = DMClient(..., encoding="UTF-8") # 也可手动指定编码
c.connect()
c.execute("SELECT id, name FROM t WHERE id = ?", [1]) # → (cols, rows)
c.execute("INSERT INTO t VALUES (?, ?)", [1, "x"]) # → (None, 影响行数)
c.begin(); c.execute(...); c.commit() # 事务
c.close()
中文/字符集支持
达梦 DM8 服务器初始化时可指定字符集(GB18030 或 UTF-8 等),服务器在握手响应参数区偏移 28
(int32:1=UTF8, 2=EUCKR, 其他=GB18030,对照 Go 驱动 zq.go Dm_build_1282=28)告知客户端。
- 默认自动检测:
DMClient(host, port, user, pwd)(encoding=None)连接握手时读取偏移 28 并 切换到对应编码,SQL 文本、参数绑定、结果集、CLOB 读写在检测后统一按该编码编解码。 - 手动覆盖:
DMClient(..., encoding="UTF-8")强制指定(服务器不返回编码或需要特殊处理时使用)。
中文乱码的根因:服务器为 UTF-8 而客户端固定按 GB18030 编解码(或反之)。 旧版驱动硬编码 GB18030;本版握手时自动适配,GB18030 服务器行为与旧版完全一致。
DB-API 2.0(sqlite3/pymysql 风格)
import dmpy.dbapi as dm
conn = dm.connect(host="127.0.0.1", port=5236, user="SYSDBA", password="...")
cur = conn.cursor()
cur.execute("SELECT id, name FROM t WHERE id >= ?", [1])
rows = cur.fetchall() # 大结果集自动分批拉取
cur.executemany("INSERT INTO t VALUES (?, ?)", [[1, "a"], [2, "b"]])
conn.commit()
conn.close()
存储过程
from dmpy import DMClient, OUT
c = DMClient("127.0.0.1", 5236, "SYSDBA", "password")
c.connect()
r = c.execute("CALL sp_test(?, ?, ?, ?)", [5, "hello", OUT(int), OUT(str)])
print(r[2]) # → [10, "hello"](OUT 参数返回值)
连接池
from dmpy.pool import ConnectionPool
pool = ConnectionPool(host="127.0.0.1", port=5236, user="SYSDBA", password="...",
min_connections=2, max_connections=10)
with pool.connection() as conn:
cur = conn.cursor()
cur.execute("SELECT 1")
pool.close()
大 LOB
# 写入 1MB CLOB/BLOB(自动分段传输)
c.execute("INSERT INTO t (id, content, data) VALUES (?, ?, ?)",
[1, "大文本..." * 50000, b"\x00\x01..." * 100000])
# 读取(自动完整拉取)
rows = c.execute("SELECT content, data FROM t WHERE id = ?", [1])[1]
项目结构
dmpy/
├── client.py # 核心:连接/查询/参数绑定/LOB/事务/存储过程/惰性查询
├── crypto.py # 加密(内置纯 Python + 可选 pycryptodome)
├── _pure_crypto.py # 纯 Python DES/AES/RC4 实现
├── frame.py # 协议帧封装/解析
├── result.py # 列描述符/行数据/类型解码
├── dbapi.py # DB-API 2.0 兼容层
└── pool.py # 连接池
环境要求
- Python >= 3.8
- 可达的达梦 DM8 服务器(TCP 5236 端口)
测试
python test_all.py # 22 项回归断言(需可达的达梦服务器,修改 test_all.py 中的连接参数)
发布
发布到 PyPI 的流程见 PUBLISHING.md。
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dm_pure-1.0.2-cp312.py3-none-any.whl.
File metadata
- Download URL: dm_pure-1.0.2-cp312.py3-none-any.whl
- Upload date:
- Size: 66.1 kB
- Tags: CPython 3.12, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1749752cf410ededa5752a381087112869add1f9aa1638bb04334e56f5906eee
|
|
| MD5 |
887a6230cfd3f0f25af154f44b50fd98
|
|
| BLAKE2b-256 |
adb2a87226b7afd5e1c28e267c7b3eb7ce7f9e4e2cbdeb81b808b8c3ccab7645
|
File details
Details for the file dm_pure-1.0.2-cp311.py3-none-any.whl.
File metadata
- Download URL: dm_pure-1.0.2-cp311.py3-none-any.whl
- Upload date:
- Size: 69.2 kB
- Tags: CPython 3.11, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03495a1b9bb44670595883e006518bc719103945efa020399230846a1a30d5d3
|
|
| MD5 |
7964591eead1310e1f59fe3616ba038a
|
|
| BLAKE2b-256 |
530247e69910e981ba84980f9d17655c6188f7ef3c00b56a67952538a7969689
|
File details
Details for the file dm_pure-1.0.2-cp310.py3-none-any.whl.
File metadata
- Download URL: dm_pure-1.0.2-cp310.py3-none-any.whl
- Upload date:
- Size: 45.2 kB
- Tags: CPython 3.10, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42083b8761fe9e199f3bc1e3babf4f6f265418d7b275dfe0a65446feda19d903
|
|
| MD5 |
5548152c3449381366fafdeecddd19c1
|
|
| BLAKE2b-256 |
d8da853647644efe55b92c07576748ba41fc8a49e3a4167f7b35e73752b47c09
|
File details
Details for the file dm_pure-1.0.2-cp39.py3-none-any.whl.
File metadata
- Download URL: dm_pure-1.0.2-cp39.py3-none-any.whl
- Upload date:
- Size: 44.9 kB
- Tags: CPython 3.9, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33dbd395e3499122d3a4e288a16d6a82c44fea31bcaf827e7a699e0efc05bde8
|
|
| MD5 |
1d2f7e8677798668af048187423aa3f2
|
|
| BLAKE2b-256 |
816dd2c42a5e65bb57867f4c696d9ed3b2cbc55bc2ba690303c47c8d80c53cbc
|
File details
Details for the file dm_pure-1.0.2-cp38.py3-none-any.whl.
File metadata
- Download URL: dm_pure-1.0.2-cp38.py3-none-any.whl
- Upload date:
- Size: 44.9 kB
- Tags: CPython 3.8, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.8.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30c722d814af01f8428400c5446af888b3f3c19753738de6a6937e2c70dccfbb
|
|
| MD5 |
8784e54e3267ad618539c5e41b29859b
|
|
| BLAKE2b-256 |
af5a08a0619cb718a74b06622e5c86147a0fac24ad77f07d42560e9dac45691c
|