Z.S.K.'s Records

pyinstaller打包Flask(-)

每当写完一个脚本工具之后,我们常常被要求需要对客户友好一键式,能有多傻瓜式就多傻瓜式,更别去说给客户机器装些乱七八糟的运行环境,python的打包工具也很好几种,pyinstaller做为python程序打包成windows下的exe,还是非常给力的,当然,还有其它的一些比较好的作用于python打包工具,本人我只用过pyinstaller,对其它的不好评价,这里主要记录下pyinstaller在windows下对python程序打包,总之一句话:pyinstaller会把代码中所有涉及到有包或者库都抽离出来,exe运行的前再全部解压到一个目录下

pyinstaller的安装

在windows下,pyinstaller需要PyWin32的支持,当用pip安装pyinstaller时未找到PyWin32,会自动安装pypiwin32.

pyinstaller的官网其实有非常详细的步骤,最新版为pyinstaller-3.2.1

1
2
##使用pip安装
pip install pyinstaller

pyinstaller常用选项

pyinstaller安装好之后,便可以用来打包了,最常用的打包命令:

1
2
3
4
5
6
7
8
9
10
11
12
#将所有文件打包成一个exe
pyinstaller -F name.exe
#将所有文件打包在一个文件夹里,这是默认的打包方式
pyinstaller -D /path/to/go
#指定icon
pyinstaller -F name.exe -i name.icon
#指定python程序中依赖的包文件
pyinstaller -p /path/to/go
#使用控制台界面,只在windows下有效,默认是不使用
pyinstaller -c ...
#使用--add-data
pyinstaller --add-data /src/path/:/dest/path

使用.SPEC文件

我们可以直接把命令写在一个叫.spec的文件中,这样就不用每次都写那么一长串命令,直接使用

1
2
#使用.spec文件
pyinstaller name.spec

.spec文件的内容格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- mode: python -*-

block_cipher = None

added_files = [
('.\\templates', 'templates'),
('.\\static', 'static')
]

a = Analysis(['chartson.py'],
pathex=['D:\\chartson'],
hiddenimports=[],
binaries=[],
datas=added_files,
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='chartson',
debug=False,
strip=False,
upx=True,
console=True , icon='chartson.ico')

spec中的datas选项

上面的命令中有个很重要的选项: datas,我们知道,在flask架构中,我们常用的项目结构一般都包含有static,用来存放一些引用的js,css文件等,template中则用来存放模板文件,这些文件夹都是在flask代码之外,flask在运行的时候是需要去找这些文件夹里的文件,那么在用pyinstaller打包时如何把这些额外文件夹一同打包进去呢,换一句话说:如何把我们在项目中引用的其它非二进制文件跟python程序打包在一个exe中,这就是datas需要做的

而在Flask的app.py中,app的声明应该如下:

1
2
3
4
5
6
if getattr(sys, 'frozen', False):
template_folder = os.path.join(sys._MEIPASS, 'templates')
static_folder = os.path.join(sys._MEIPASS, 'static')
app = Flask(__name__, template_folder=template_folder,static_folder=static_folder)
else:
app = Flask(__name__)

上面的added_files(这个名字可随意,只要跟Analysis中的datas配对即可)中指定了templates指向的当前目录下的templates,而且if/else保证了即使是单独使用python app.py运行项目也能跑起来

exe解压路径如果没有指定的话默认是在C:\Users***\AppData\Roaming\pyinstaller\下,在这目录下,你能看到很多pyd文件,当然这些都是被编译过的了,还有很多项目中import的库跟windows下的dll.

参考文章:

转载请注明原作者: 周淑科(https://izsk.me)


 wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?