先安装这个依赖:pywin32
future
pefile (future)
pip安装PyInstaller:
pip install pyinstaller
或者源码安装:
pip install .
python setup.py install
使用方法:
pyinstaller yourprogram.py
参数说明:
-D 表示生成一个包含可执行文件的文件夹(默认)
-F 表示生成单个可执行文件
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!
-p 表示你自己自定义需要加载的类路径,一般情况下用不到
-i 表示可执行文件的图标
注:不能放着中文目录下,否则会报错:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb9 in position 4: ordinal not in range(128)
添加exe文件[os.popen()],采用编辑 .spec 文件的方式:
1、先正常生成:
pyinstaller -F yourprogram.py
2、编辑yourprogram.spec
binaries=[('./MegaCli.exe', '.')],
binaries=[('./MegaCli.exe', 'bin')],
前面pyinstaller 自动生成的spec文件中,binaries原本是空的:
binaries=[] 我这边是:binaries=None
就是一个空的list,把要添加的资源文件以tuple的形式传入,tuple的第一个元素是资源文件的路径,第二个元素是打包后存放资源的文件夹。
3、
pyinstaller -F yourprogram.spec
还需要改其他东西,不搞了
lightt 2019.06.05 17:54:01 字数 504 阅读 3,656
如果想把python程序发布成.exe的话,一般我们都会使用pyinstaller, 怎么打包这里我就不说了。有时我们打包的结果会非常大,我最大的一次居然有900M......下面我就总结一下可以对发布结果瘦身的方法。
注意:下面的方法只对打包成多个文件夹(pyinstaller -D)的情况有效;对打包成一个.exe文件(pyinstaller -F)的情况无效。
from ... import ...进行引用,尽量减少不必要的引用(但是某些依赖比如opencv,所有的方法都在一个.pyd(78M)里面,所以即使只引用一个方法,整个.pyd都会引入);anaconda;sys.setrecursionlimit(5000), 但是打包遇到recursion error时就只能用了;在这里详细说明一下第四种方法:
tasklist / m | more >> .\include.txt,(此时程序需要在执行中) 这个命令会把所有运行程序的.dll依赖存到include.txt;然后搜索程序名,比如image_register, 结果如下:image_register.exe 7752 ntdll.dll, kernel32.dll, KERNELBASE.dll,
WS2_32.dll, msvcrt.dll, RPCRT4.dll,
NSI.dll, api-ms-win-core-synch-l1-2-0.DLL,
python36.dll, VERSION.dll, SHLWAPI.dll,
GDI32.dll, USER32.dll, LPK.dll, USP10.dll,
ADVAPI32.dll, sechost.dll, ole32.dll,
OLEAUT32.dll, VCRUNTIME140.dll,
api-ms-win-crt-runtime-l1-1-0.dll,
ucrtbase.DLL,
api-ms-win-core-localization-l1-2-0.dll,
api-ms-win-core-processthreads-l1-1-1.dll,
api-ms-win-core-file-l1-2-0.dll,
api-ms-win-core-timezone-l1-1-0.dll,
api-ms-win-core-file-l2-1-0.dll,
api-ms-win-crt-string-l1-1-0.dll,
api-ms-win-crt-heap-l1-1-0.dll,
api-ms-win-crt-stdio-l1-1-0.dll,
api-ms-win-crt-convert-l1-1-0.dll,
api-ms-win-crt-math-l1-1-0.dll,
api-ms-win-crt-locale-l1-1-0.dll,
api-ms-win-crt-time-l1-1-0.dll,
api-ms-win-crt-environment-l1-1-0.dll,
api-ms-win-crt-process-l1-1-0.dll,
api-ms-win-crt-conio-l1-1-0.dll,
api-ms-win-crt-filesystem-l1-1-0.dll,
IMM32.DLL, MSCTF.dll, CRYPTSP.dll,
rsaenh.dll, CRYPTBASE.dll, _ctypes.pyd,
_socket.pyd, select.pyd, _bz2.pyd,
_lzma.pyd, pyexpat.pyd, _hashlib.pyd,
api-ms-win-crt-utility-l1-1-0.dll,
win32api.pyd, SHELL32.dll,
pywintypes36.dll, secur32.dll, SSPICLI.DLL,
pythoncom36.dll, uxtheme.dll, urlmon.dll,
api-ms-win-downlevel-ole32-l1-1-0.dll,
api-ms-win-downlevel-shlwapi-l1-1-0.dll,
api-ms-win-downlevel-advapi32-l1-1-0.dll,
api-ms-win-downlevel-user32-l1-1-0.dll,
api-ms-win-downlevel-version-l1-1-0.dll,
api-ms-win-downlevel-normaliz-l1-1-0.dll,
normaliz.DLL, iertutil.dll, WININET.dll,
USERENV.dll, profapi.dll,
cv2.cp36-win_amd64.pyd, MSVFW32.dll,
WINMM.dll, COMCTL32.dll, AVIFIL32.dll,
MSACM32.dll, AVICAP32.dll, COMDLG32.dll,
MFPlat.DLL, AVRT.dll, MF.dll, ATL.DLL,
ksuser.dll, MFReadWrite.dll,
multiarray.cp36-win_amd64.pyd, mkl_rt.dll,
umath.cp36-win_amd64.pyd,
lapack_lite.cp36-win_amd64.pyd,
_umath_linalg.cp36-win_amd64.pyd,
_mklinit.cp36-win_amd64.pyd,
fftpack_lite.cp36-win_amd64.pyd,
mtrand.cp36-win_amd64.pyd
这些.dll文件以及.pyd文件全在我们打包后的dist文件里,都是程序运行需要的,除了这些以外base_library.zip和.exe.manifest也是需要的,最后只要把不需要的移出来就可以瘦身啦。python操作文件很方便:
def move_file_of_py_installer_by_tree(root_path, dll_names, exclude_path):
# tasklist / m | more
dll_names = dll_names + ['base_library.zip',
'image_register.exe',
'image_register.exe.manifest']
for root, dirs, files in os.walk(root_path):
for file in files:
if file not in dll_names:
old_path = os.path.join(root, file)
new_dir = root.replace(root_path, exclude_path)
if not os.path.exists(new_dir):
os.makedirs(new_dir)
new_path = os.path.join(new_dir, file)
shutil.move(old_path, new_path)
print(old_path)
dll_names 就是在include.txt里的依赖名字。
总结一下,如果使用了anaconda环境,那打包真的是胖,使用第四个方法真的可以瘦下来好多。我那个image_register瘦了500M.,还剩100M,其中78M是opencv。 ^ _ ^
1、最简用法
pyinstaller main.py
2、隐藏命令行窗口
pyinstaller main.py --noconsole
3、有些模块是通过import导入的,如PySide2.QtXml,pyinstaller无法检测到这些模块,因而无法打包进去,需要添加额外命令
pyinstaller main.py --noconsole --hidden-import PySide2.QtXml
4、为文件和应用程序添加图标
pyinstaller main.py --noconsole --hidden-import PySide2.QtXml --icon=“logo.ico”
5、为应用程序添加图标的另一种方法
app.setWindowIcon(QIcon(‘logo.png’))