【问题标题】:dll found but cannot be loaded from current working directory找到但无法从当前工作目录加载的 dll
【发布时间】:2019-10-12 18:11:12
【问题描述】:

我正在运行以下代码:

def PATH():
    return "\n"+"\n".join(os.environ["PATH"].split(os.pathsep))

def syspath():
    return "\n"+"\n".join(sys.path)

def test_haha():
    logger.info(f"CWD: {os.getcwd()}")
    logger.info(f"sys.path: {syspath()}")
    logger.info(f"PATH: {PATH()}")

    logger.info(f"Found? {str(util.find_library('PCANBasic'))}")
    windll.LoadLibrary("PCANBasic")
    # pcanbasic_path = str(Path(os.getcwd()) / "PCANBasic.dll")

我的PCANBasic.dll 就在我的工作目录中。我正在使用 Windows 10。

如果我从命令行运行 python,一切正常。

但是,我有一个用 pyqt 编写并与 PyInstaller 捆绑在一起的 IDE。该IDE具有运行python文件的功能(在运行我手动运行的相同命令的批处理文件中调用QProcess),在这种情况下它会失败并显示以下内容:

    def test_haha():
        logger.info(f"CWD: {os.getcwd()}")
        logger.info(f"sys.path: {syspath()}")
        logger.info(f"PATH: {PATH()}")

        logger.info(f"Found? {str(util.find_library('PCANBasic'))}")
>       windll.LoadLibrary("PCANBasic")

demo_test\test_dll.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Users\myuser\python3_portable\lib\ctypes\__init__.py:434: in LoadLibrary
    return self._dlltype(name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <WinDLL 'PCANBasic', handle 0 at 0x1e9e6480668>, name = 'PCANBasic'
mode = 0, handle = None, use_errno = False, use_last_error = False

    def __init__(self, name, mode=DEFAULT_MODE, handle=None,
                 use_errno=False,
                 use_last_error=False):
self._name = name
        flags = self._func_flags_
        if use_errno:
            flags |= _FUNCFLAG_USE_ERRNO
        if use_last_error:
            flags |= _FUNCFLAG_USE_LASTERROR
        if _sys.platform.startswith("aix"):
            """When the name contains ".a(" and ends with ")",
               e.g., "libFOO.a(libFOO.so)" - this is taken to be an
               archive(member) syntax for dlopen(), and the mode is adjusted.
               Otherwise, name is presented to dlopen() as a file argument.
            """
            if name and name.endswith(")") and ".a(" in name:
                mode |= ( _os.RTLD_MEMBER | _os.RTLD_NOW )

        class _FuncPtr(_CFuncPtr):
            _flags_ = flags
            _restype_ = self._func_restype_
        self._FuncPtr = _FuncPtr

        if handle is None:
>           self._handle = _dlopen(self._name, mode)
E           OSError: [WinError 126] The specified module could not be found

cwd,sys.path 相同,PATH 基本相同(IDE 版本有 PyQt5 bin 文件夹)。

总的来说,问题是:

1 - 什么可能导致这种行为差异,在一种情况下我能够从当前工作目录加载 dll,而在另一种情况下我不能?

2 - 在任何情况下,如果 dll 在 PATH 中的任何目录中,它都可以工作。依赖工作目录中的 dll 并将它们正确安装在某个地方可能是一种不好的做法吗?

谢谢!

【问题讨论】:

    标签: python dll pyinstaller ctypes


    【解决方案1】:

    我能够按照教程使用 Process Monitor 和过滤:

    • 操作是CreateFile
    • 路径包含PCANBasic

    我能够看到 PyInstaller 包的搜索路径与直接命令不同。

    然后我发现 this issue 提到 PyInstaller 使用 SetDllDirectoryA 调用将包自己的文件夹添加到 DLL 搜索路径,但具有删除当前目录的副作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-10
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多