使用pyinstaller进行打包成exe可执行文件
安装:pip install pyinstaller
打包命令:pyinstaller main.py //但打包出来的文件很多
-F: 打包成单个文件
-w: 指定生成 GUI 软件,也就是运行时不打开控制台
-i <Icon File>: 指定打包后可执行文件的图标
--clean: 在构建之前清理PyInstaller缓存并删除临时文件
觉得命令太多,想偷懒的话其实是有办法的,直接pip install auto-py-to-exe
安装后,在终端输入auto-py-to-exe,就得到了一个基于pyinstaller开发的GUI界面,方便好用!!!
–key lyb888: 使用秘钥进行加密(简单的加密方式)此加密方式官方在6.0后已弃用
打包文件太大
如果你已经使用了纯净的虚拟环境,打包文件还是很大的话,那就无解了
打包安装包
将程序使用pyinstaller打包成一个exe后,可能需要附带一些其他文件,比如存储数据的json文件或第三方exe,dll文件等
有很多需要配合主程序使用的文件,所以就需要打包成一个安装包。
Inno Setup 目前不支持中文版的,打包成安装包的过程有些多,所以建议英语不好的在网上找一个汉化版的。
官方版地址:https://jrsoftware.org/isdl.php
具体使用步骤,请移步其他博客,网上一堆。
一个可视化操作界面
推荐使用pyqt5,但原生的页面,小白来写的话,实在太丑,美化界面耗时实在太长
先安装一些依赖包:pip install pyqt5 pip install pyqt5-tools
安装后,可以在终端输入designer,打开ui排版控制界面
将排版后的ui文件转换成py文件:pyuic5 input.ui -o output.py
学会使用基础pyqt5搭建一个页面,整个流程后,可以直接参考一位大佬的杰作
https://github.com/zhiyiYo/PyQt-Fluent-Widgets
这是一个非常美观的可视化界面,并附带各种常用功能的效果展示
pip install "PyQt-Fluent-Widgets[full]" -i https://pypi.org/simple/
数据应该怎么存储?
软件分发给各种用户,为了防止线上数据库压力,数据管理,数据库防护攻击,等等问题
采用sqlite3本地数据库xxx.db文件,进行数据的增删改查,数据更方便管理,比较与json与ini文件,更加便捷,轻盈,高效
db文件与打包的exe一起发送给用户,db文件就用来统计所有的数据,文件非常小,并且对于低端电脑甚至低端硬件都可以使用
pip install sqlite3
遇到的问题
pyinstaller 使用(隐藏控制台)进行打包时,代码中使用了类似subprocess的方法时,闪烁终端,
解决方法:重点:在于后面的参数:creationflags=0x08000000
subprocess.check_output(cmd, creationflags=0x08000000)
subprocess.call(cmd, creationflags=0x08000000)
res = subprocess.Popen(strcmd, shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=0x08000000,encoding='gb2312')
output, error = res.communicate()
可以获取到输出的日志,并且使用encoding='gb2312'编码格式,可以解析中文
其他
轻量级,获取系统中的所有 GPU型号,以便适配各种GPU加速(排坑)
GPUtil 有部分低端GPU检测不到,明明有显卡却什么都检测不到
pyopencl 有部分GPU调用方法直接闪退,退出程序无任何报错
pynvml
import GPUtil
def get_gpu_info():
gpus = GPUtil.getGPUs()
logger.info(gpus)
for gpu in gpus:
logger.info(gpu.name)
if 'NVIDIA' in gpu.name or 'nvidia' in gpu.name or 'GeForce' in gpu.name:
elif 'AMD' in device.name or 'amd' in device.name:
elif 'Intel' in device.name or 'intel' in device.name:
return gpus
import pyopencl as cl
platforms = cl.get_platforms()
for platform in platforms:
print("Platform:", platform.name)
devices = platform.get_devices()
for device in devices:
print((device.name, device.global_mem_size,type(device.global_mem_size)))
if 'NVIDIA' in device.name or 'nvidia' in device.name or 'GeForce' in device.name:
elif 'AMD' in device.name or 'amd' in device.name:
elif 'Intel' in device.name or 'intel' in device.name:
sqlite3示例
class sql_local_db ():
def __init__(self):
# 连接到SQLite数据库 数据库文件是 tianji.db,如果文件不存在,会自动在当前目录创建
self.db = sqlite3.connect('py_fun/tianji.db',check_same_thread = False)
self.sql_lock = threading.Lock()
def select_db (self, sql, chiose='none', insert_many=None):
with self.sql_lock :
cur = self.db.cursor()
if chiose == 'executemany': # 一次性添加多条数据
cur.executemany(sql, insert_many)
self.db.commit()
return
cur.execute(sql)
if chiose == 'SELECT': # 查询
data = [dict(line) for line in [zip([column[0] for column in cur.description], row) for row in cur.fetchall()]]
return data
elif chiose == 'INSERT': # 新增并返回最后插入的id
self.db.commit()
return cur.lastrowid
else: # 修改,删除,等
self.db.commit()
return
def is_table_exists (self, table_name): # 判断表是否存在
sql = '''SELECT tbl_name FROM sqlite_master WHERE type = 'table' '''
values = self.select_db (sql, chiose='cha')
tables = []
for v in values:
tables.append(v[0])
if table_name not in tables: return False # 可以建表
else: return True # 不能建表
sql_db_fun = sql_local_db() # 创建一个数据库对象
createTb_video_material = """CREATE TABLE "video_material" (
"id" INTEGER NOT NULL,
"reId" INTEGER,
"name" TEXT,
"size" REAL,
"duration" TEXT,
"use_count" TEXT,
PRIMARY KEY ("id")
);"""