python Windows运行时依赖项

时间:2019-06-06 08:54:09

标签: python-3.x dll

我正在使用Python 3.7,正在使用CFFI构建Python扩展模块,该模块封装了另一个使用V140平台工具集构建的DLL。我将.pyd文件和.dll与python wheel捆绑在一起,Windows 10上的用户可以毫无问题地使用它。

但是,当尝试在全新安装了Python 3.7的干净Windows 7计算机上使用它时,出现ImportError: Dll load failed错误。我知道解决的方法是安装“ Visual Studio 2015的Visual C ++可再发行组件”。 我已经对此进行了测试,并且可以正常工作。我对此有一些疑问:

  1. 从Python 3.5开始,vcruntime140.dll与Python一起打包。为什么是这样?为什么不仅仅依靠系统之一?我发现史蒂夫·道尔(Steve Dower)的博客post最接近回答这个问题。 他说:

      

    由于DLL加载的工作方式,如果尚未加载该版本的DLL,则将使用与扩展模块相邻的那个版本。如果已加载,将使用当前内存中的那个。

         

    实际上,我们只需要包含一次即可。诀窍是确保先加载它。最终,唯一可靠的方法是将其包含在所有地方。

         

    在此阶段,Python 3.5始终将包含vcruntime140.dll(尽管有时它可能会从顶级目录移动到DLL中),所以使用MSVC 14.0构建的扩展将始终具有它。

  2. Python的安装程序installation notes建议在安装过程中可能需要更新系统的C运行时。但是,在上述干净的Windows 7计算机上,这似乎没有发生,并且系统文件夹(vcruntime140.dll中没有C:\windows\SysWOW64。那么这是什么意思呢?它有什么作用?我本以为它会像静默安装上述可再发行组件那样做。

      

    您无需成为管理员(除非需要对C运行时库进行系统更新,或者为所有用户安装适用于Windows的Python启动器)

  3. 对于使用与他们所针对的Python解释器版本相同的运行时来构建扩展的用户,分发运行时依赖项(例如vcruntime140.dll)的指导是什么?我希望我根本不必关心,而依靠Python安装程序来解决这个问题。我也知道在Windows 10上默认安装vcruntime140.dll,这是Windows 7上的建议Windows更新。或者,为了获得更多上下文,我实际上是在创建一个安装程序,其中捆绑了一些脚本,这些脚本是我创建的库以及来自Python.org的Python安装程序。如果是Windows 7,我真的还需要捆绑并以静默方式安装Visual C ++可再发行组件吗?
  4. 此处是有关DLL依赖关系的其他问题。如何确定DLL或应用程序是否已通过完整路径名指定了其DLL依赖关系?通过阅读Search Order for Desktop Applications的工作方式,这显然会影响DLL的来源。例如,当检查依赖扩展程序中扩展模块的依赖关系时,它会将vcruntime140.dll依赖关系放入我的系统文件夹中。但是,当我使用dumpbin /dependencies检查依赖项时,它只是按名称提及它们。

更新

我尝试在x86和x86-64 Windows 7安装上安装Python 3.7.3。我没有选择为所有用户安装Python,而是选择将其安装在本地用户目录中。我可以看到C运行时依赖项DLL实际上保存在此目录中。 现在,在将扩展模块创建并安装到虚拟环境中之后,仅当PATH中存在Python安装目录时,我才可以使用扩展模块而不会出现问题。在Windows DLL search order中,似乎在以下路径上找到了运行时DLL:

  

PATH环境变量中列出的目录。请注意,这不包括“应用程序路径”注册表项指定的每个应用程序路径。计算DLL搜索路径时不使用“应用路径”键。

我仍然不明白的是为什么为什么不使用已经加载的运行时?

如果我打开进程浏览器(来自systinternals)并从虚拟环境中打开python解释器会话,则可以看到C运行时已经加载。根据微软的说法:(重点是我的)

  

在系统搜索DLL之前,它会检查以下内容:

     

如果已在内存中加载了具有相同模块名称的DLL,则系统将使用已加载的DLL,无论它位于哪个目录中。系统都不会搜索该DLL。      

如果该DLL在运行该应用程序的Windows版本的已知DLL列表中,则系统使用其已知DLL的副本(以及已知DLL的从属DLL,如果有的话)。系统不搜索DLL。有关当前系统上已知DLL的列表,请参见以下注册表项:HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs。

0 个答案:

没有答案