达梦官方库排查 dmPython 安装后 python -m 报错:.pth + os.execve 的排查实录

dmPython 安装后 python -m 报错:.pth + os.execve 的排查实录

背景

信创项目,业务系统从 MySQL 迁移到达梦数据库。安装 dmPython 驱动后,import dmPython 正常,但 python3 -m pip 突然报错:

bash 复制代码
$ python3 -m pip install xxx
/usr/bin/python3: No module named -V

信创环境是手动编译的 Python,pip 可执行文件不在 PATH 里,只能用 python3 -m pip 调用。而现在整个 -m 机制都报错,模块名变成了 -V 或其他奇怪参数。

排查过程

常规检查(无果)

  1. 环境变量 --- PYTHONPATH、PATH 正常
  2. 重装 pip --- 问题依旧
  3. 查看 dmPython 文件 --- 除了多出一些文件,没发现明显异常

strace 定位 .pth

用 strace -f 跟踪系统调用,发现 CPython 初始化时读取了 dmPython.pth:

bash 复制代码
$ strace -f python3 -m pip 2>&1 | grep pth
openat(AT_FDCWD, "/site-packages/dmPython.pth", O_RDONLY) = 3

查看内容:

bash 复制代码
$ cat /site-packages/dmPython.pth
import dmdpi

继续查看 dmdpi.py:

python 复制代码
import os, sys
if 'LD_LIBRARY_PATH' not in os.environ:
    os.environ['LD_LIBRARY_PATH'] = dpi_path
    if sys.argv[0] == '':
        os.execve(sys.executable, [sys.executable, ...], os.environ)
    else:
        os.execve(sys.executable, [sys.executable] + sys.argv, os.environ)

问题初步定位:.pth 文件触发了 import dmdpi,dmdpi.py 又执行了 os.execve。

根因分析

CPython 的 -m 参数处理机制

执行 python3 -m pip install xxx 时:

  1. C 层解析命令行 ,模块名 pip 被单独保存 ,不在 sys.argv 里
  2. sys.argv = ['-m', 'install', 'xxx'] (只含 -m 和模块名之后的参数)
  3. import site → 处理 .pth → 执行 import dmdpi
  4. site 走完 → runpy 用单独保存的模块名执行

问题在第 3 步

dmdpi.py 在 site 初始化中途 执行 os.execve,用 sys.argv 拼接新命令:

ini 复制代码
原始命令:python3 -m pip install xxx
sys.argv = ['-m', 'install', 'xxx']      ← 模块名 pip 已移除
execve 执行:python3 -m install xxx      ← install 被当成模块名

实际报错显示 python3 -m -V,就是因为 sys.argv 里 -m 后面的参数被当成了模块名。

验证 site 阶段的 sys.argv

写个 usercustomize.py 打印 sys.argv:

bash 复制代码
$ cat /site-packages/usercustomize.py
import sys, os
os.environ['ARGV_DEBUG'] = str(sys.argv)

$ python3 -m pip --version
$ echo $ARGV_DEBUG
['-m', '--version']   # 模块名 pip 确实不在

为什么 import dmPython 没问题

dmPython.so 内置了 RPATH($ORIGIN/dmPython.libs),能自己找到 libdmdpi.so。根本不需要:

  • dmdpi.py 设置 LD_LIBRARY_PATH
  • os.execve 替换进程

dmdpi.py 是多余的,且破坏了正常启动流程。

修复

删除 .pth 文件:

bash 复制代码
rm /site-packages/dmPython.pth

删除后 python3 -m pip 恢复正常,import dmPython 也正常。

后续

问题反馈给达梦官方,后续版本改为 wheel 格式。

旧版(egg)文件结构:

arduino 复制代码
dmPython.pth              ← 触发 import dmdpi
dmdpi.py                  ← 执行 os.execve,导致问题
dpi/libdmdpi.so           ← 依赖库单独存放
dmPython.cpython-xxx.so
dmpython-2.5.5.dist-info/

新版(wheel)文件结构:

bash 复制代码
dmPython.cpython-310-x86_64-linux-gnu.so
dmPython.libs/libcrypto-xxx.so
dmpython-2.5.32.dist-info/

对比:.pth 没了,dmdpi.py 没了,dpi/ 目录没了。所有依赖编译进 .so 或通过 dmPython.libs/ 加载,不再需要在 site 初始化阶段执行代码。

教训

  1. .pth 文件里的 import 会在 site 初始化时无条件执行
  2. .pth 里如果用 os.execve,site 初始化阶段 sys.argv 是残缺的(-m 模块名已被 CPython 移除)
  3. strace 是排查解释器级别问题的利器
相关推荐
脚本自动化开发8 小时前
存储涨价后,磐镭WO5迷你主机值得买吗
后端
一只爱撸猫的程序猿10 小时前
我看着一个 AI 引擎在 14 天里,从"记忆"走进了"搜索"
人工智能·后端·架构
陈随易13 小时前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
卷无止境13 小时前
RAGFlow 项目全景报告:从文档解析引擎到 Agent 原生数据库
后端·python
小Z先生14 小时前
我用 Go + 系统 WebView 写了个纯本地 Postman:不装 Electron、不连云端
后端·github
IT_陈寒14 小时前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
灿飞屋15 小时前
Kotlin与Java虚拟机三:控制流
android·java·开发语言·后端·python·kotlin·安卓
石小石Orz15 小时前
AI 正在蚕食我们的编码能力
前端·后端·算法
陈随易15 小时前
专注飞机 FocusFlight,两个人把番茄钟做成了一趟航班
前端·后端·程序员
量化分析码农15 小时前
【Python量化波动率实战 04】低波动异象:低波组真的跑赢高波组吗
后端