从Python 3.7.6转到Python 3.10.3后找不到DLL

发布于 2025-01-17 17:41:54 字数 1677 浏览 2 评论 0原文

我正在尝试将库升级到 Python 3.10。到目前为止,我一直使用3.7.6。

在我的库中,我使用 DLL。在包 __init__.py 中,我将 DLL 路径添加到 PATH 变量中。因为我想让代码与 32 和 64 位系统兼容,所以我在运行时检查位数并将适当的 DLL 文件夹添加到 PATH:

import os
import sys

# Add libs to PATH environment variable such that DLLs can be loaded.
# Load either x64 or x86 depending on whether we are running a 32/64
# bit system.
package_directory = os.path.dirname(os.path.abspath(__file__))
if sys.maxsize > 2**32:
    path_dir = os.path.join(package_directory, 'libs', 'x64')
else:
    path_dir = os.path.join(package_directory, 'libs', 'x86')

os.environ['PATH'] += os.pathsep + path_dir

相应的文件夹结构是

package_root
|- libs
   |- x64
      |- libbristolpolled.dll
      ...
   |- x86
      |- libbristolpolled.dll
      ...

然后在子包中,我正在使用:

from ctypes import CDLL

dll = "libbristolpolled.dll"
_lib_bristlp = CDLL(dll)

这已经有效在 3.7.6 中很好,但在 3.10.3 中失败,并显示以下错误消息:

  File "C:\...\lib\site-packages\optoMD\sensor\optical\bristol\dll_api.py", line 37, in <module>
    _lib_bristlp = CDLL(dll)  # The correct DLL
  File "C:\Program Files\Python310\lib\ctypes\__init__.py", line 374, in __init__
    self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'libbristolpolled.dll' (or one of its dependencies). Try using the full path with constructor syntax.

如果我改为使用绝对路径,如错误消息所示,它可以工作:

from ctypes import CDLL

dll = r"C:\...\libs\x64\libbristolpolled.dll"
_lib_bristlp = CDLL(dll)

旧方法不再工作的原因是什么,或者如何我能让它再次工作吗?我不想在代码中使用绝对路径,而且我喜欢在 init 文件中处理一次 DLL 路径,然后只需要使用文件名导入 DLL 即可。

I am trying to upgrade a library to Python 3.10. Up to now, I have been using 3.7.6.

In my library, I am using DLLs. In the package __init__.py, I add the DLL path to the PATH variable. Since I want to have the code compatible with 32 and 64 bit systems, I check the bitness at runtime and add the appropriate DLL folder to the PATH:

import os
import sys

# Add libs to PATH environment variable such that DLLs can be loaded.
# Load either x64 or x86 depending on whether we are running a 32/64
# bit system.
package_directory = os.path.dirname(os.path.abspath(__file__))
if sys.maxsize > 2**32:
    path_dir = os.path.join(package_directory, 'libs', 'x64')
else:
    path_dir = os.path.join(package_directory, 'libs', 'x86')

os.environ['PATH'] += os.pathsep + path_dir

The corrresponding folder structure is

package_root
|- libs
   |- x64
      |- libbristolpolled.dll
      ...
   |- x86
      |- libbristolpolled.dll
      ...

Then in a sub-package, I am using:

from ctypes import CDLL

dll = "libbristolpolled.dll"
_lib_bristlp = CDLL(dll)

This has worked fine in 3.7.6 but fails in 3.10.3 with the following error message:

  File "C:\...\lib\site-packages\optoMD\sensor\optical\bristol\dll_api.py", line 37, in <module>
    _lib_bristlp = CDLL(dll)  # The correct DLL
  File "C:\Program Files\Python310\lib\ctypes\__init__.py", line 374, in __init__
    self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'libbristolpolled.dll' (or one of its dependencies). Try using the full path with constructor syntax.

If I instead use the absolute path, as the error message suggests, it works:

from ctypes import CDLL

dll = r"C:\...\libs\x64\libbristolpolled.dll"
_lib_bristlp = CDLL(dll)

What is the reason the old method doesn't work anymore, or how can I make it work again? I'd prefer not to have absolute paths in my code and I liked the fact that I handle the DLL path once in the init file and afterwards I just need to import the DLL using the file name.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

硬不硬你别怂 2025-01-24 17:41:54

此特定功能(通过将查找 .dll 的路径添加到 PATH 环境变量)已在 Python 3.8 中删除。根据通知,新函数 os.add_dll_directory;引用文档说明更改的原因:

版本 3.8 中的新功能:以前版本的 CPython 将使用当前进程的默认行为解析 DLL。这导致了不一致,例如有时仅搜索 PATH 或当前工作目录,并且 AddDllDirectory 等操作系统功能不起作用。

未来更可移植的解决方案是尝试使用该函数,或者只生成绝对路径,就像您当前使用 os.path.dirname 和 os.path.join 所做的那样> 在 dll 变量上 - 即保持与之前的 Python 版本的兼容性;另外,这还假设这些 .dll 文件没有外部依赖项,如果有的话,此线程 有关当前问题的更多详细信息(即使使用绝对路径 - 尽管考虑到它确实适用于您的程序和库,但这对于您的用例来说不应该是问题) 。

This particular features (by adding the path to find a .dll to PATH environment variable) has been removed in Python 3.8. As per the notice, the new function os.add_dll_directory is provided; quoting the documentation for the reason for the change:

New in version 3.8: Previous versions of CPython would resolve DLLs using the default behavior for the current process. This led to inconsistencies, such as only sometimes searching PATH or the current working directory, and OS functions such as AddDllDirectory having no effect.

The more portable solution going forward is to attempt to use that function, alternatively just generate the absolute path as you have current done using os.path.dirname and os.path.join on the dll variable - i.e. to maintain compatibility with prior Python versions; also this assumes those .dll files do not have external dependencies, if there are, this thread has a significantly more detail regarding the issues at hand (even with absolute paths - though given that it did appear to work for your program and library, this should not an issue for your use case).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文