简体   繁体   中英

how to exclude opengl32sw.dll from pyqt5 library when using pyinstaller?

How to write the correct syntax for excluding opengl32sw.dll from pyqt5.

I have tried using exclude in the spec file but its not working.

excludes=['cryptography','PyQt5/bin/opengl32sw.dll']

Exclude unwanted binaries in your spec file

Method 1: Subtract from a.binaries

Add the following to your spec file, after the analysis:

a.binaries -= TOC([
    ('opengl32sw.dll', None, None)
])

you can add other dlls to this list in the same way. This works because a.binaries is TOC type, which is an ordered list of tuples where the uniqueness is based on name, and it has a __sub__ function that allows subtracting other TOC s from it. See the docs and this answer by timlukins.

os.path.normcase gets called on the filenames (see L112 and L35 in PyInstaller/building/datastruct.py ), so on Windows, any binary names you subtract in this way should be all lowercase (eg Qt5DBus.dll should be given as qt5dbus.dll ) or they will not get removed. In that case it is better to import os and call os.path.normcase yourself, so that it works as expected whatever the operating system is.

Also, there appears to be a bug with TOC that will cause the list to be blanked out if you subtract from it and then subtract from the result of the first subtraction.

So to expand this to several modules dynamically, first construct the list of tuples and then subtract it in one:

to_exclude = {'opengl32sw.dll', 'Qt5DBus.dll'}
a.binaries -= [(os.path.normcase(x), None, None) for x in to_exclude]

Method 2: Iterate through a.binaries and only keep what you want

Brénainn Woodsend suggests something like the following (again, in your spec file after the analysis):

to_keep = []
to_exclude = {'opengl32sw.dll'}

# Iterate through the list of included binaries.
for (dest, source, kind) in a.binaries:
    # Skip anything we don't need.
    if os.path.split(dest)[1] in to_exclude:
        continue
    to_keep.append((dest, source, kind))

# Replace list of data files with filtered one.
a.binaries = to_keep

With this method, the names of the binaries you add to to_exclude should be in the same casing as they appear on disk (eg Qt5DBus.dll should be given as is, Qt5DBus.dll ). Or you could name them all in lowercase and add .lower() after os.path.split(dest)[1] .

The exclude command only works for Python modules and not for DLLs. I think an easy but dirty way in here is to create a virtualenv and manually deleting the DLLs you don't need.

Another way which is more complicated is to locate the PyQt 's hook file located in <Python_Path>\lib\site-packages\PyInstaller\utils\hooks\qt.py and disable the line which bundles opengl32sw.dll file:

# Gather required Qt binaries, but only if all binaries in a group exist.
def get_qt_binaries(qt_library_info):
    binaries = []
    angle_files = ['libEGL.dll', 'libGLESv2.dll', 'd3dcompiler_??.dll']
    binaries += find_all_or_none(angle_files, 3, qt_library_info)

    # comment the following two lines to exclude the `opengl32sw.dll`
    # opengl_software_renderer = ['opengl32sw.dll']
    # binaries += find_all_or_none(opengl_software_renderer, 1, qt_library_info)

    # Include ICU files, if they exist.
    # See the "Deployment approach" section in ``PyInstaller/utils/hooks/qt.py``.
    icu_files = ['icudt??.dll', 'icuin??.dll', 'icuuc??.dll']
    binaries += find_all_or_none(icu_files, 3, qt_library_info)

    return binaries

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM