Moving all the DLL and PYD to a sub-folder with cx

2019-02-08 13:06发布

问题:

This has come up quite a few times on the cx_Freeze mailing lists

(see

cx_Freeze and moving files around

Creating fewer files when freezing a Python application

cx_freeze python single file? )

and it seems to me like it ought to be a simple fix, but I can't see how to begin.

I have a python application that depends on scipy, wxpython, numpy and a bunch of other packages that each have a LOT of dynamically linked libraries. The main executable folder gets very cluttered with PYD and DLL files and it is hard to even find the executable amongst all the files. My users are not particularly computer savvy, so clarity is very important.

I don't require a single executable like can theoretically be generated by bbfreeze. I like how the distutils setup.py file works with cx_Freeze and in every other way cx_Freeze is pretty much brilliant.

All I want is a way to clean up the main executable folder. I would be completely happy with manually moving the DLL files into a freeze_libs folder or something and then munging the shared library loading path to help it find the dynamic libraries if that is possible. Or something like that.

Thanks

回答1:

I understand your frustration. What I tend to do is take the entire build folder and move it to the program files directory assuming you are using a windows machine. Then create a shortcut on the desktop to the executable. I then generally change the icon to something pleasing to the eye. In other words all the system files are hidden and all you are left with is a single nice looking icon on the desktop.



回答2:

"manually" did it , but is this the correct way ? i'm on win7 x64 cx_freeze 4.3.2

my init_script, combined from Console.py and ConsoleSetLibPath.py

import encodings
import os
import sys
import warnings
import zipimport

paths = os.environ.get("LD_LIBRARY_PATH", "").split(os.pathsep)
if DIR_NAME not in paths:
    paths.insert(0, DIR_NAME)
    os.environ["LD_LIBRARY_PATH"] = os.pathsep.join(paths)
    os.execv(sys.executable, sys.argv)

sys.frozen = True
sys.path = sys.path[:4]

# i added this line
sys.path.append(r'lib')

os.environ["TCL_LIBRARY"] = os.path.join(DIR_NAME, "tcl")
os.environ["TK_LIBRARY"] = os.path.join(DIR_NAME, "tk")

m = __import__("__main__")
importer = zipimport.zipimporter(INITSCRIPT_ZIP_FILE_NAME)

# The following if/else is copied from ConsoleSetLibPath.py
if INITSCRIPT_ZIP_FILE_NAME != SHARED_ZIP_FILE_NAME:
    moduleName = m.__name__
else:
    name, ext = os.path.splitext(os.path.basename(os.path.normcase(FILE_NAME)))
    moduleName = "%s__main__" % name

code = importer.get_code(moduleName)
exec code in m.__dict__

versionInfo = sys.version_info[:3]
if versionInfo >= (2, 5, 0) and versionInfo <= (2, 6, 4):
    module = sys.modules.get("threading")
    if module is not None:
        module._shutdown()

Then i save this file in C:\Python27\Lib\site-packages\cx_Freeze\initscripts as ConsoleSetLibPathx.py and in my setup.py

setup(
    name = 'xxx',
    version = '0.1',
    options = {'build_exe': {'includes':includes,
                             'excludes':excludes,
                             'packages':packages,
                             'include_files':includefiles,
                             'create_shared_zip':True,
                             'include_in_shared_zip':True,
                              # use the "hacked" init_script ?
                             'init_script':'ConsoleSetLibPathx',
                             'include_msvcr':True,
                             }

                             }, 
    executables = [exe]
)

# Am i supposed to do the mkdir lib , and copy *.pyd *.dll into it in the end of this setup.py here? 
# I verified this is working by manually creating lib dir and copy all files inside, it works.

i feel i should do it in the options, or somewhere, but don't quite understand the cx_freeze doc right now. maybe --target-dir or --default-path or --replace-paths ? not sure how to use them

edit: sorry this needs improving, when i test this in another clean win7 in vmware, it's working but it's acting weird, my code of non-blocking read keypress is not working. not sure which part is wrong.