1、pycharm创建python虚拟环境
(我目前创建的虚拟环境是基于python3.8的环境创建的)(一定创建虚拟环境,我开始用python38环境,打包删除都非常慢,耗时太久)
2、项目根目录下生成requirements.txt
3、项目下执行 pip install -r requirements.txt
4、编辑如下配置文件
5、datas下的任何一个目录里不能是空文件夹,不然打包不进去
-*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['main.py',
'catchLog.py',
'common\\adb_connect_devices.py' ,
'utils\\board.py',
'utils\\running_circle.py',
'utils\\threads.py'],
pathex=['D:\\DB_Programs\\ZhuanXiangTest\\Test\\log_tool'],
binaries=[],
datas=[('utils','utils'),('common','common'),('file','file'),('catchLog.py','.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
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,
[],
exclude_binaries=True,
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='D:\\DB_Programs\\ZhuanXiangTest\\Test\\log_tool\\file\\icons\\Logo.png',
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='main',
)
暂时无法在飞书文档外展示此内容
5、pip install pyinstaller
6、执行pyinstaller main.spec
踩坑:
踩坑1:之前项目目录有中文,创建了虚拟环境(如下红色路径)。怕打包中文会报错。把路径改成了英文的,pycharm也修改了python解释器的路径。但是编译打包exe文件时还是显示之前的中文路径。
解决办法:删除上面创建的虚拟环境(删除venv目录即可删除虚拟环境),基于3.8创建一个新的虚拟环境。重新打包就不会会出现路径不一致了。
踩坑2:
执行编译后的exe,报AttributeError: module 'serial' has no attribute 'Serial'错误。
解决办法:
卸载之后重新安装两个第三方库文件:pip3 uninstall serial和pip3 uninstall pyserial,卸载之后就可以重 新安装(本人尝试过,这种方法,可用)
踩坑3:
打包后其它电脑执行报错如下
解决办法:
1、卸载pyqt5后重新安装
2、pip install PyQt5 -i https://pypi.douban.com/simple
3、pip install PyQt5-tools -i https://pypi.douban.com/simple ( pip install pyqt5-tools,这个是重点。需要这个工具依赖。pyqt5 下载有附加工具 pyqt5-tools需要同步下载)
4、将项目目录下的venv\Lib\site-packages 里面的PyQt5、pyqt5_plugins包复制到venv\Lib下
踩坑4:
解决办法:
4.1、不要在init初始化serial.Serial()
4.2、在实际调用的地方初始化serial.Serial()
4.5 解决python调用cmd命令或第三方exe时出现cmd黑框
在Windows环境下,python程序中会调用cmd命令或第三方exe文件,很多时候要么会直接打开cmd黑框显示完整的运行过程,要么会显示一个无内容显示的cmd黑框。
举例1:使用os.system调用ping http://www.baidu.com之类的命令,然后返回调用结果。调用的过程中,会出现完整的ping命令黑框执行全过程;
举例2:使用os.popen方式调用静默打印pdf文件的exe,调用过程中,会出现一个无内容的cmd黑框,在打印完成后才会消失。
整体思路,使用subprocess代替os模块,如下总结了几种可以解决上述黑框的方法,以下在windows环境下测试通过:
不需要返回,只是调用程序或命令
run方式默认为阻塞方式,即需要等调用命令完成后才会接着运行python下一步代码:
def run_cmd( cmd_str:str): from subprocess import run
run(cmd_str, shell=True) shell=True是关键,需要加上,否则还是会有黑框print('需要等上述命令完成后,才会显示这一行")
run_cmd("ping www.baidu.com") 调用自定义函数测试阻塞run_cmd('notepad') 会打开一个记事本程序,需要手工关闭记事本后才会显示print内容
得到调用程序执行后的输出详细结果:
def run_cmd(cmd_str:str):import subprocessreturn subprocess.Popen(cmd_string, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).communicate()[0]print(run_cmd('ping www.baidu.com'))
其中:text=True,可以将输出结果变为文字,且避免选择编码格式
subprocess.Popen()方法为一个非阻塞方法,因此需要使用communicate()进行阻塞获取输出结果,与wait()的区别在于:wait()默认pipe size为64KB,超出限制容易导致死锁;而communicate()会将输出放在内存中,上限与可分配的内存相关
得到调用程序执行后的返回值
(即表示程序运行是否成功的标志,不返回详细程序输出值)
def run_cmd(cmd_str:str):import subprocessreturn subprocess.Popen(cmd_str, shell=True, stdout=None, stderr=None).wait()print(run_cmd('ping www.baidu.com'))返回0表示程序执行成功不要if not run_cmd('ping www.baidu.com'): 这样来判断执行成功做一个超时强行关闭pipe机制后,返回的结果为None,用逻辑判断的结果和0是一样的,但其实是运行不成功的
subprocess.Popen的典型参数:
p=subprocess.Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True, Text=True, cwd='d:/')
其中:
args即为传入要运行的命令或程序,有两种形式:
['ping','www.baidu.com','-t'] # 用list方式分隔命令参数
'ping www.baidu.com -t' # 注意参数如包含空格,应使用类似'"xxxxx"'来处理
cwd传入一个绝对路径,会将传入的命令或程序工作目录改为cwd
returncode属性,返回传入运行的命令或程序exit code,运行正常为0
p.communicate()
p.returncode