无法加载使用 setuptools 打包的 dll
Can't load dll packaged with setuptools
我正在 windows,使用带有 python 3 和 setuptools 的 anaconda。
我在将 DLL 加载到我的包中时遇到问题。我尝试遵循“Packaging resources with setuptools/distribute' as well as 'Python copy a DLL to site-packages on Windows”中的建议,但我似乎遗漏了一些东西。
所以,我的包裹看起来像:
setup.py
package
|--- __init__.py
|--- main.py
|--- subpackage
|--__init__.py
|--foo.py
|--bar.DLL
里面foo.py
我做:
import ctypes
my_dll = ctypes.cdll.LoadLibrary('bar.dll')
当我在控制台中 运行 我的脚本时,这有效。但是,一旦我将所有内容打包并安装(例如通过 setuptools 和 pip),我似乎无法加载 dll。
在setup.py
里面我设置了package_data={'':['*.dll', '*.h', '*.lib']}
。安装后,我可以看到所有文件都正确放置在安装位置。一旦我尝试导入我的包,我得到错误:
File "path\to\subpackage\foo.py", line 3, in <module>
my_dll = ctypes.cdll.LoadLibrary('bar.dll')
[...]
OSError: [WinError 126] Das angegebene Modul wurde nicht gefunden
(Could not find the given module)
所以,我很确定,我需要首先在 运行 时间更改我的 dll
文件的加载,但我不知道如何。
我正在寻找一个解决方案,它仍然允许我在编辑器中 运行 单个文件 foo.py
,但允许我在安装后使用包内的相同文件。
更新 为清楚起见进行了编辑。
更新 16.12.2019 我又发现了一件事:
我尝试了 Sergey 的以下回答
import os
this_dir = os.path.abspath(os.path.dirname(__file__))
my_dll = ctypes.cdll.LoadLibrary(os.path.join(this_dir, 'bar.dll'))
这仅在我当前的工作目录等于 ...\package\subpackage
时有效,因此我假设 LoadLibrary
甚至不尝试搜索给定路径,而只取文件名。
您的 DLL 不在 PATH 中,因此无法找到。
在 foo.py
中使用 importlib.util
检索其位置:
import os
import importlib.util
spec = importlib.util.find_spec('subpackage', 'package')
my_dll = ctypes.cdll.LoadLibrary(os.path.join(spec.submodule_search_locations, 'bar.dll'))
我没有针对您的特定设置测试此代码,但您应该有一个总体思路
有关 find_spec
的更多信息在 documentation
中
更简单的方法:
import os
this_dir = os.path.abspath(os.path.dirname(__file__))
my_dll = ctypes.cdll.LoadLibrary(os.path.join(this_dir, 'bar.dll'))
我正在 windows,使用带有 python 3 和 setuptools 的 anaconda。
我在将 DLL 加载到我的包中时遇到问题。我尝试遵循“Packaging resources with setuptools/distribute' as well as 'Python copy a DLL to site-packages on Windows”中的建议,但我似乎遗漏了一些东西。
所以,我的包裹看起来像:
setup.py
package
|--- __init__.py
|--- main.py
|--- subpackage
|--__init__.py
|--foo.py
|--bar.DLL
里面foo.py
我做:
import ctypes
my_dll = ctypes.cdll.LoadLibrary('bar.dll')
当我在控制台中 运行 我的脚本时,这有效。但是,一旦我将所有内容打包并安装(例如通过 setuptools 和 pip),我似乎无法加载 dll。
在setup.py
里面我设置了package_data={'':['*.dll', '*.h', '*.lib']}
。安装后,我可以看到所有文件都正确放置在安装位置。一旦我尝试导入我的包,我得到错误:
File "path\to\subpackage\foo.py", line 3, in <module>
my_dll = ctypes.cdll.LoadLibrary('bar.dll')
[...]
OSError: [WinError 126] Das angegebene Modul wurde nicht gefunden
(Could not find the given module)
所以,我很确定,我需要首先在 运行 时间更改我的 dll
文件的加载,但我不知道如何。
我正在寻找一个解决方案,它仍然允许我在编辑器中 运行 单个文件 foo.py
,但允许我在安装后使用包内的相同文件。
更新 为清楚起见进行了编辑。
更新 16.12.2019 我又发现了一件事:
我尝试了 Sergey 的以下回答
import os
this_dir = os.path.abspath(os.path.dirname(__file__))
my_dll = ctypes.cdll.LoadLibrary(os.path.join(this_dir, 'bar.dll'))
这仅在我当前的工作目录等于 ...\package\subpackage
时有效,因此我假设 LoadLibrary
甚至不尝试搜索给定路径,而只取文件名。
您的 DLL 不在 PATH 中,因此无法找到。
在 foo.py
中使用 importlib.util
检索其位置:
import os
import importlib.util
spec = importlib.util.find_spec('subpackage', 'package')
my_dll = ctypes.cdll.LoadLibrary(os.path.join(spec.submodule_search_locations, 'bar.dll'))
我没有针对您的特定设置测试此代码,但您应该有一个总体思路
有关 find_spec
的更多信息在 documentation
更简单的方法:
import os
this_dir = os.path.abspath(os.path.dirname(__file__))
my_dll = ctypes.cdll.LoadLibrary(os.path.join(this_dir, 'bar.dll'))