从.py到.exe完整路线+排雷(PyInstaller+NSIS)

编程环境PyCharm
用到的第三方库PyInstaller
用到的软件NSIS

PyInstaller部分

  1. 首先确保自己编写好的Python程序无中文路径(我的程序使用了PyQt5和PyQtGraph制作了界面);

  2. 通过pip install PyInstaller或直接通过PyCharm界面的File->Settings->Project->Python Interpreter,点击‘+’进行第三方库安装;

  3. 在PyCharm界面的Terminal上(一般在界面的最下方,如下图所示)
    在这里插入图片描述

    导航到需要生成exe的.py文件路径下
    在这里插入图片描述

  4. 执行命令PyInstaller -D -w example.py(这里换成你自己程序的名字),等待3min左右,就会在example.py所在的路径生成两个文件夹:buliddist,以及一个配置文件spec。其中我们程序生成的.exe文件就在dist文件夹下。

讲解一下上面命令中参数的含义,方便大家根据需要使用:

  1. -D:表示打包后生成一个文件夹,文件夹中包含我们的.exe,这样做的好处是,生成的可执行文件运行速度更快;它可以替换为-F,表示打包后生成一个纯.exe文件,其体积较大,运行速度较慢,但是比前面的方法更整洁。
  2. -w: 表示生成的.exe不显示控制台(就是类似cmd出来的那个窗口),只显示我们自己做的界面,但是如果你的python程序没有界面,那就什么都不会显示了;它可以替换为-c,表示生成的.exe显示控制台界面和自己的ui,我个人建议,在第一次运行程序的时候,使用PyInstaller -D -c example.py(这里换成你自己程序的名字),这样可以看到界面运行时出现错误的原因,等全部排查后,再重新生成一个用户使用的界面时,使用PyInstaller -D -w example.py(这里换成你自己程序的名字)

到这里,PyInstaller部分完成,如果只是自己用的话,看到这里就OK了。接下来使用NSIS对这个exe进行二次打包,效果就是,打包后把一个文件夹变成一个纯.exe,双击后就是常见的安装向导了。

NSIS部分

  1. 下载NSIS:NSIS官网下载链接
    在这里插入图片描述
  2. 将刚才使用PyInstaller打包后生成的dist目录下的目录(就是你的python程序名)进行压缩,生成ZIP文件;
  3. 点击下载的NSIS.exe,通过安装向导来安装;安装成功后出现一个名为NSIS的文件夹,进入后点击NSIS.exe在这里插入图片描述
    选择下面的命令在这里插入图片描述
    然后将你的ZIP文件导入,其他选项都不变
    在这里插入图片描述
    等待Extracted开始统计文件夹中文件数目;结束后Generate按键变亮,点击后,等待5min左右,就可以在dist文件夹下得到打包后的.exe向导文件了。
    到这里,NSIS部分完成。

排雷

在我使用这两个工具打包的时候,没有想象中一帆风顺,顺利的就完成了毕业设计最后一步,由于自己毕设的特殊性,遇到了下面的问题,重复打包了N次后才成功。
  1. Python程序中涉及到文件路径导航时:由于我设计的界面需要显示本地文件夹下其他Python程序的名称,我通过PyInstaller打包后,把这些程序所在的文件夹也移到了这个打包后的文件夹中,但是运行.exe时,界面却没有显示这些名称。

解决方法: 1.首先排查了源代码,发现使用了绝对路径os.path.abspath,把所有的绝对路径都删掉了,并将路径冻结,整体修改方法如下:

首先在if __name__ == '__main__':下面添加

   if getattr(sys, 'frozen', False):
        path = os.path.dirname(sys.executable)
    elif __file__:
       path = os.path.dirname(__file__)

对路径进行冻结,此时path获得的就是.exe所在的路径;
其次,把程序中的

file_path = os.path.abspath(os.path.join(path1, question_file))

os.path.abspath都删掉,使用相对路径;此时重新进行打包后,生成的.exe就可以显示程序名称了;

  1. 虽然GUI上显示了Python程序的名称,但是我希望它可以在GUI上运行,之前在PyCharm中实现时,使用subprocess模块,具体的代码如下:
subprocess.Popen([sys.executable, fn])

其中fn是Python程序的路径(上面修改为了相对路径导航);但是在.exe中点击运行按钮后,没有弹出这个程序运行的界面,而是又弹出了一个相同的GUI
仔细分析后,我认为问题一定出现在sys.executable这个参数上。果不其然,在PyCharm中打印了这个参数的地址,发现它指向了本地的python.exe文件;因此猜想,在.exe中,这个参数指向的是我们生成的.exe,所以又运行了一次这个GUI。
但是我没找到特别好的办法,只是把本地的Python.exe文件所在文件夹整个移到了我们生成的.exe的文件夹下,然后把源代码中sys.executable参数修改为这个Python.exe的路径(相对路径)。再次运行PyInstaller -D -c example.py(这里换成你自己程序的名字)命令,把本地的Python.exe文件所在文件夹整个再移过去,运行,结果!闪现了一个黑乎乎的窗口,失败/(ㄒoㄒ)/~~
我又尝试运行了一下这个移动过来的Python.exe,结果发现,它本身就是闪现的窗口(我也不知道为什么),但是意外发现,文件夹下的ipython.exe文件可以正常运行。
在这里插入图片描述
反正功能相同,我就试着把源代码中sys.executable参数再次指向ipython.exe,**再次,再次打包!**结果,又一次闪现黑窗口/(ㄒoㄒ)/~~
再次排查问题,找到了一个大佬的帖子帖子链接,发现这个subprocess.Popen中的参数,可以进行调整。

shell=True 可以防止执行subprocess.Popen()时闪现一个黑糊糊的dos窗口。
打包是关闭了命令行窗口,stdin, stdout 无处安放,应该把它们用subprocess.PIPE 管道代替。

最后修改代码如下:

subprocess.Popen([path_python, fn], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

其中path_python就是指向移到生成文件夹的ipython.exe的相对路径,fn是要执行的python程序的相对路径。
再次PyInstaller后,运行.exe,成功通过子线程运行了另一个Python程序!

  1. 使用NSIS打包后,我尝试换了一个盘运行这个软件,结果发现,GUI只是出现不到2s,又退出了/(ㄒoㄒ)/~~
    还好之前生成.exe时,设置了控制台可以显示,在GUI闪现的时候,立马按下PrintScreen按键,看到了出错的原因:
    在这里插入图片描述
    这个问题,我也百度到了答案,这里放一下链接

除此之外,大家应该可以看到,我的路径包含了中文,这也预示着我又得多打包一次/(ㄒoㄒ)/~~。排查了这个问题之后(不要让路径包含中文),再走一遍流程,终于成功做完毕设!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值