前言
最近公司项目需要用到FastApi做一个打印web接口服务,然后将这个服务打包成Windows可执行程序,在使用pyinstaller打包出现问题之后,了解到Python官方推荐的是使用cx_Freeze打包。于是开始了cx_Freeze折腾
安装
使用命令安装:
pip install cx_Freeze
验证是否安装成功,打开控制台(cmd)输入:
cxfreeze -h
# 如果有类似提示则表示安装成功:Usage: cxfreeze [options] [SCRIPT]
打包exe
简单的使用
在控制台中进入到需要打包的文件夹,执行命令:
cxfreeze run.py --target-dir=build
-
run.py
表示打包的文件名称,一般为程序的入口文件 -
--target-dir=build
表示打包后的文件存放路径
执行完成之后可以在同路径下的build/xxx/
文件夹中找到刚刚打包的run.exe
如果存在需要引入的某些三方库,用这种方法可能找不到,所以不推荐这种方法
使用setup.py
进行打包
- 在需要打包的路径下新建一个
setup.py
(名字随意,你喜欢就好),输入以下内容
import sys
from cx_Freeze import setup, Executable
include_files = ['.\\printing_server\\templates\\log_websocket_client.html']
build_exe_options = {'packages': ['uvicorn','ipaddress','jinja2.ext'],
'excludes': [],
'include_files':include_files
}
base = None
if sys.platform == 'win32':
base = 'Win32GUI'
setup( name = 'runFastApi',
version = '0.1',
description = '打印服务',
options = {'build_exe': build_exe_options},
executables = [Executable('run.py')])
-
include_files
需要引入的静态文件、动态链接库等等内容 -
packages
需要引入的三方扩展包,虽然可以自动根据py文件引入三方库进入导入,但是避免不了有些库,它无法识别,所以需要手动显性的引入 -
setup
name表示文件名称,version,exe描述,options 打包时需要引入的文件或者三方库包,executables 设置程序的入口文件
- 然后在终端中执行命令:
python setup.py build
等待打包结束,在同级目录下会出现build目录,需要的exe文件存在build/xxx/
中
打包过程还算简单,可以直接运行exe进行测试了
遇到的问题
- 打包完成之后,直接双击会闪退,在cmd中运行exe提示
ModuleNotFoundError: No module named 'xxx'
这个时候就需要在setup.py 文件中的packages
文件中加入需要的扩展包 - 由于是web服务打包成了exe,其中不免会包含HTML等文件,打包的时候可以在
include_files
中指定文件路径。指定了路径之后cx_freeze会自动将文件复制到生成的可执行文件的同级目录下,这个时候仍然可能会出现提示找不到html等文件。
解决办法一:
我的文件目录:
printing_server
|_templates(存放的是HTML文件)
|_xxx.py
run.py
setup.py
我在xxx.py文件中指定的html文件存放位置:template = Jinja2Templates(directory=".\\printing_server\\templates")
打包成exe之后运行时会默认在当前路径下面找printing_server\templates
文件夹,这个时候就会提示没有NotFound
所以我们可以在setup.py的incloude_files直接指定路径为.\\printing_server
,生成exe之后在exe同级目录下会有printing_server
的文件夹名称,这个时候运行exe可以正常运行。
缺点:打包时会将printing_server中的所有内容都复制过来(包括py文件),
可能会有人有疑问,说我直接在include_files中指定文件夹到templates中不就好了吗,这个倒是解决了只导入HTML等文件,但是运行的仍然会报找不到文件的错误,因为这个时候在exe的同级目录生成的文件是templates,而我们py文件中指定的是.\\printing_server\\templates
,所以还是找不到
针对该缺点的解决办法:将templates文件夹放在其他不包含py文件的目录,然后重新在py文件中指定存放路径,在setup.py的include_files中引入文件夹templates
(可能项目文件夹有要求,所以根据实际的来吧)。或者将exe同级目录中的静态资源文件夹中的无关资源删除
解决办法二:
后来发现一个简单的方法,简直简单不要不要的。突然发现自己好蠢哈哈哈
由于我在xxx.py文件中指定的HTML的路径为.\\printing_server\\templates
, 我们可以在生成exe文件之后,在exe文件的同级目录中新建一个文件夹printing_server
,然后将templates整个文件夹复制至其中,运行exe 完美!!
这个问题的原因还是因为打包成exe之后会自动在同级目录下去寻找需要的静态文件,所以只需要将py文件中指定的静态资源文件按照指定的目录存放在exe同级目录下。虽然解决办法一比较麻烦,但是还是推荐第一种方法,因为文件多了之后不用一个个的复制过去。
虽然有点啰嗦,还有些没有讲清楚!另外水平有限,还请谅解- - -
一定记得使用相对路径呀!!
个人网站:https://www.diaoyc.cn/