python debug模式报错_关于Python38中调试PyQt5时import PyQt5.QtCore报错(ImportError: DLL load failed)的问题分析...

Python更新到了Python38,有一个非常好的更新,统一了Debug与Release模式下的ABI,也就是说在C/C++中嵌入Python时,可以直接在Debug模式下用Release的Python了,果断考虑从Python37更新到Python38。想当初为了调试在Debug模式下的C/C++&Python混合代码,把Python的模块都编译了个遍~~~~。

然而事情往往总是不会一帆风顺,在把代码移植后,本以为会执行得很好的代码报错了:

ImportError: DLL load failed while importing QtCore: 找不到指定的模块。

思考:这份代码在Python37下运行正常,会是什么原因呢?

1、dll系统搜索路径不对

加path解决,无效,看来不是这个原因导致的。

2、试试执行python3.exe 再执行import PyQt5.QtCore会不会报错

没有报错,但是仍然不知道是什么原因导致的。

3、将程序拷贝到Python目录,直接运行

没有报错,看到了成功的希望,但是这个不是解决问题的办法,还得继续找原因。

4、vs以调试模式运行拷贝到python目录的程序

仍然运行正常,还是对问题未知。(此时已一头雾水)

5、用DEPENDS.EXE分析QtCore.pyd对库的依赖,在执行import PyQt5.QtCore之前将这些依赖调用LoadLibraryA加载

过程中加载了Qt5Core.dll、Python3.dll、sip.cp38-win32.pyd,能正常运行

尝试只加载Python3.dll,依然能正常运行,此时貌似在程序运行前执行下LoadLibraryA("Python3.dll")能解决,但是没有找到导致这个问题的根本原因

6、分析Python代码,搜索LoadLibrary字眼

定位到dynload_win.c _PyImport_FindSharedFuncptrWindows函数,在该函数添加条件断点,当加载QtCore.pyd时断点

_PyImport_FindSharedFuncptrWindows调用了LoadLibraryExW,

这里有代码修改的注释:

/* bpo-36085: We use LoadLibraryEx with restricted search paths

to avoid DLL preloading attacks and enable use of the

AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to

ensure DLLs adjacent to the PYD are preferred. */

Py_BEGIN_ALLOW_THREADS

hDLL = LoadLibraryExW(wpathname, NULL,

LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |

LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);

Py_END_ALLOW_THREADS

从注释来看,这里比较python37进行了更改,通过查找windows api手册,发现LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR将不会在PATH中配置的路径中去寻找库,并且不会加载非程序目录之外的dll。通过分析可知,QtCore.pyd依赖Python3.dll,而Python3.dll位于PATH环境而非应用程序目录,在用加载LoadLibraryExW LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR加载QtCore.pyd时,不会去搜索PATH中的Python3.dll,导致QtCore.pyd加载失败。

验证:

将Python3.dll拷贝到执行程序所在目录,调试执行,一切正常,问题解决。

附:python import调用过程,将使用importlib模块

importlib会调用内置模块"_imp",创建新的模块时会调用_imp.create_dynamic

create_dynamic最终会调用到_PyImport_FindSharedFuncptrWindows

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值