如何使用pyinstaller?(解决pyinstaller打包时Failed to execute script xxx.exe)

说明

在使用pyinstaller打包py文件时候,竟然会有一个需求是要求在允许exe的时候不带控制台,这并不是一个很难的操作,但是往往在打包之后,允许exe时会弹出Failed to execute script xxx.exe的报错信息,折腾了一下午,终于搞明白了原因以及解决方法.


预备知识

  • 根据打包时输入的参数的不同,可以进行不同类型的打包,首先需要大致了解一下几个常用的参数,或许有助于对解决方法的理解:

  • -D Create a one-file bundled executable(创建一个包含可执行文件的单文件夹包,换句话说,就是打包出来的程序,会是一个文件夹,里面包含了许多的依赖文件等等,和一个exe可执行文件,就像windows的许多软件一样的形式。).

  • -F Create a one-file bundled executable(创建一个单文件绑定的可执行文件,换句话说,就是只会打包出一个exe可执行文件,没有多余的文件。).

  • w Windows and Mac OS X: do not provide a console window
    for standard i/o. On Mac OS X this also triggers
    building an OS X .app bundle. On Windows this option
    will be set if the first script is a ‘.pyw’ file. This
    option is ignored in NIX systems(Windows和Mac OSX:不提供控制台窗口标准i / o。在Mac OS X上也会触发构建一个OS X .app包。在Windows上这个选项。如果第一个脚本是’,则设置。pyw”文件。这选项在NIX系统中被忽略。简而言之,在windows上运行时不显示cmd窗口。).

简单示例

  • 最简单的打包
# 这是最简单的打包
pyinstaller main.py
  • 使用参数-D
"""
加上-D的打包可以理解为是打包的第一种方式,和上面是一样的效果,因为-D是属于默认的。
此时打包完成后,在main.py的路径下会又一个dist文件夹,dist文件夹下是一个main文件夹,
再往里面打开,就会像我们大多数windows软件一样,有一个目录专门放
一堆运行时所需要的依赖文件等等,但一定有一个main.exe文件用于运行。
"""
pyinstaller -D main.py
  • 使用参数-F
"""
加上-F可以理解是打包的第二种方式,与-D不能同时使用。
打包完成后,在main.py路径下同样会有一个dist文件夹,但不同的是,
dist文件夹下只有一个main.exe的可运行文件。
"""
pyinstaller -F main.py
  • 使用参数-w
"""
无论是使用-F 还是 -D参数,打包出来的exe文件在运行的时候都会自动打开一个cmd窗口,
如果我们想让他关闭而不影响程序运行的话,需要在打包时再加上-w参数。
无论是-F 还是-D都支持和-w参数配合使用,以此来关闭运行时打开的cmd窗口。
"""
pyinstaller -F -w main.py
# 或者
pyinstaller -D -w main.py

打包的生成的文件.spec文件

  • 当我们每次打包的时候,除了生成的dist、build、__pycache__三个文件夹外,还有一份后缀为.spec的文件。通过pycharm(或者其他IDE)打开后内容如下:
    无需过多关注这份代码,需要用到的下面会提到,并且我们可能有所差异
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['main.py'],
             pathex=['C:\\Users\\HYT\\Desktop\\shili'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='main',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True )
  • 关于这份代码,我们需要知道的是,将console的值即代表着运行时是否打开cmd窗口。
  • hiddenimports可以帮助我们解决许多报错信息。
  • 并且我们可以通过修改.spec文件,然后进行二次打包,速度相对快得多,格式如下:
"""
注意不在是main.py,而是main.spec。
比如将原本的console=True改为console=False再进行打包,
就不会显示cmd窗口了
"""
pyinstaller -D -w main.spec 

打包的常见误区

  • 打包完成,并不意味着打包成功,这就是为什么有时候生成的exe文件无法运行,仔细观察打包过程的日志信息,往往会有一些报错信息藏在里头,通过这些报错信息,可以很高效的在网上搜索到解决方法。
  • 需要打包一个不带命令行窗口的exe时,不要直接一上来就加上-w参数,因为这样可能导致查看不了报错信息,因此无法解决问题。当我们执行带cmd窗口的exe时,即使报错了,也可以在cmd窗口看到报错信息,根据报错信息找到对应的解决方法,然后再进行二次打包,并加上-w参数,就可以完美的打包出一个可以运行的无cmd窗口的exe文件了。

解决方法

  • 当发现打包完成后的exe无法运行,报出Failed to execute script xxx.exe时,可以去除-w参数重新进行打包。再次运行后可以捕捉到报错信息。
  • 常见的报错信息如下:
No such file or directory: 
'C:\\Users\\HYT\\AppData\\Local\\Temp\\_MExx\\xx\xx错误
  • 关于这个错误,一个可行的解决方法是替换pyinstaller下的hooks文件,以及添加一些缺失的module到.spec文件下的hiddenimports中,然后对该.spec文件进行二次打包。
    详细的修改方法可以查看大佬的博客。点击这里

一个可行的打包流程

  • 1.首先不带-w参数打包一份可以显示cmd窗口的exe,进行运行测试。
  • 2.注意cmd窗口的日志信息,如果出现报错信息,根据上面的解决方法修改.spec文件的内容以及hooks-xx.py文件。
  • 3.确认程序无误后修改.spec文件的console为False,重新对该.spec文件进行二次打包。

-F -D 打包出来的区别

  • -F打包处理的exe占用的空间通常会比-D打包出来的exe大得多,启动速度上也会快得多,但是只有一个exe,没有多余的文件,使用起来相对也比较方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值