达梦官方库排查 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. 环境变量 --- PYTHONPATHPATH 正常
  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 dmdpidmdpi.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.pysite 初始化中途 执行 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 是排查解释器级别问题的利器
相关推荐
moMo15 小时前
前后端模块化分离,web盒子布局思维
前端·后端
程序员牛奶15 小时前
[Algo-3]前缀和秒杀两道区间求和题:一维 + 二维统一模板
后端·算法
BileiX15 小时前
CC-Switch的安装与使用
后端
覆东流15 小时前
Python变量与数值类型
开发语言·后端·python
程序员cxuan15 小时前
Codex 官方:/goal 的正确打开方式
人工智能·后端·程序员
雨辰AI15 小时前
人大金仓慢 SQL 根治方法论:问题定位 - 分析 - 优化全流程
数据库·后端·sql·mysql·政务
invicinble15 小时前
springboot出现的原因二---作为web的后端服务一站式整合器
前端·spring boot·后端
zhz521416 小时前
Spring Boot + 腾讯 Kona 实现 TLCP 8443 国密 HTTPS 排障实录(奇安信浏览器已通)
spring boot·后端·https·国密·gmssl·kona
IT策士16 小时前
Django 从 0 到 1 打造完整电商平台:我的订单列表与订单详情
后端·python·django