ImportError: DLL load failed when importing win32c

2019-02-18 17:31发布

I've got a Python 2.7 program that imports win32clipboard. I tried to freeze it with cx_Freeze 4.2.3 on Windows XP SP3 32-bit, to create an installation MSI. I made a setup.py according to the cx_Freeze documentation, and used the following command:

c:\python27\python.exe setup.py bdist_msi

When I run it on another PC that doesn't have Python 2.7 installed, I get an exception on the line that imports win32clipboard:

ImportError: DLL load failed: The specified module could not be found.

I can see that win32clipboard.pyd is being included in the build.

What dependency is missing, and how can I ensure it is included?

2条回答
贪生不怕死
2楼-- · 2019-02-18 18:19

I eventually figured that win32clipboard.pyd is being included, however, win32clipboard.pyd depends on pywintypes27.dll, which cx_Freeze is not copying from c:\windows\system32.

The short-term hack is to manually copy c:\windows\system32\pywintypes27.dll into build\exe.win32-2.7, then run setup.py bdist_msi again.

An improved hack is to use the following in the setup.py:

import os
import sys
import win32api
...
pywintypes_dll = 'pywintypes{0}{1}.dll'.format(*sys.version_info[0:2])      # e.g. pywintypes27.dll
build_exe_options = {..., "include_files": [ (os.path.join(win32api.GetSystemDirectory(), pywintypes_dll), pywintypes_dll)]}
...
setup(  ...,
        options = { 'build_exe': build_exe_options, 
                    ...,
                  },
        ...)

(It would be preferable for cx_Freeze to be improved to automatically detect the pywintype27.dll dependency, but I guess that's always a work-in-progress.)

查看更多
混吃等死
3楼-- · 2019-02-18 18:22

cx_Freeze uses a hooking mechanism to handle this sort of situation. The hooks are stored in the module cx_Freeze.hooks. Each hook is named after the action being investigated, load or missing, and the module name. The module itself provides lots of examples.

Here is how you'd handle the win32clipboard module:

from cx_Freeze import hooks
def load_win32clipboard(finder, module):
    finder.IncludeModule("pywintypes")

hooks.load_win32clipboard = load_win32clipboard
...

Now when cx_Freeze encounters win32clipboard, it will also include pywintypes. cx_Freeze already has a pywintypes hook that will copy the appropriate file.

查看更多
登录 后发表回答