前言
我通常用 Pyinstaller 将 PixivBiu 的 Python 代码打包成可执行文件,但打包后的体积很令人在意。
Pyinstaller 打包时会把本地环境的包饱和式塞进去,所以如果安装过的 Python 包比较多,那体积可能会很奇怪得偏大。因此,解决办法就是在纯净的虚拟环境中打包,这样就可以尽可能缩小体积了。个人认为这是一个简单但效果很明显的改进方法。
这里就记录一下 Pipenv 的简单使用及以此来缩小文件体积。
Pipenv
Pipenv is a tool that aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, yarn, etc.) to the Python world. Windows is a first-class citizen, in our world.
It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your
Pipfile
as you install/uninstall packages. It also generates the ever-importantPipfile.lock
, which is used to produce deterministic builds.
Pyinstaller
PyInstaller freezes (packages) Python applications into stand-alone executables, under Windows, GNU/Linux, Mac OS X, FreeBSD, Solaris and AIX.
Pipenv
安装
官方文档有说明各种安装方法,这里就简单列举一个不负责任的方法吧。
~ pip install pipenv
创建虚拟环境
- 如果是一个新的项目,我更偏向通过指定 Python 版本的方式来创建虚拟环境。
~ cd <project_path>
~ pipenv --two # 使用系统中的 Python2 创建环境
~ pipenv --three # 使用系统中的 Python3 创建环境
~ pipenv --python x.x # 使用指定版本的 Python 创建环境
但需要注意的是,Pipenv 并不会安装新的 Python。也就是说,虚拟环境中的 Python 版本只能是已经安装过的了(并且存在于系统的环境变量中)。
如果想要方便管理多个版本的 Python,或是在项目中使用指定的版本,可以使用 Pyenv。
并且,此命令并不能用来切换一个环境的 Python 版本,每次执行都等于创建一个新的虚拟环境。
- 当然,你也可以通过安装包的形式来快速创建。推荐在存在环境配置文件的情况下使用此方法。
~ pipenv install # 仅安装默认包,不包含开发所需的
~ pipenv --dev # 安装默认以及开发所需的包
~ pipenv --dev-only # 仅安装开发所需的包
此时的创建逻辑是:
- 如果目录下没有 Pipfile 和 Pipfile.lock 文件,则默认创建一个新的虚拟环境
- 如果有,则使用已有的 Pipfile 和 Pipfile.lock 文件配置创建一个虚拟环境
- Python 以及包版本会跟随上述配置文件中的
关于环境文件
Pipenv 并没有安装新的 Python 版本,只是链接。各个环境的包文件都集中放置在一个文件夹中,很是整齐。
使用
Usage: pipenv [OPTIONS] COMMAND [ARGS]...
Options:
--where Output project home information.
--venv Output virtualenv information.
--py Output Python interpreter information.
--envs Output Environment Variable options.
--rm Remove the virtualenv.
--bare Minimal output.
--completion Output completion (to be executed by the
shell).
--man Display manpage.
--support Output diagnostic information for use in
GitHub issues.
--site-packages / --no-site-packages
Enable site-packages for the virtualenv.
[env var: PIPENV_SITE_PACKAGES]
--python TEXT Specify which version of Python virtualenv
should use.
--three / --two Use Python 3/2 when creating virtualenv.
--clear Clears caches (pipenv, pip, and pip-tools).
[env var: PIPENV_CLEAR]
-v, --verbose Verbose mode.
--pypi-mirror TEXT Specify a PyPI mirror.
--version Show the version and exit.
-h, --help Show this message and exit.
Usage Examples:
Create a new project using Python 3.7, specifically:
$ pipenv --python 3.7
Remove project virtualenv (inferred from current directory):
$ pipenv --rm
Install all dependencies for a project (including dev):
$ pipenv install --dev
Create a lockfile containing pre-releases:
$ pipenv lock --pre
Show a graph of your installed dependencies:
$ pipenv graph
Check your installed dependencies for security vulnerabilities:
$ pipenv check
Install a local setup.py into your virtual environment/Pipfile:
$ pipenv install -e .
Use a lower-level pip command:
$ pipenv run pip freeze
Commands:
check Checks for PyUp Safety security vulnerabilities and against PEP
508 markers provided in Pipfile.
clean Uninstalls all packages not specified in Pipfile.lock.
graph Displays currently-installed dependency graph information.
install Installs provided packages and adds them to Pipfile, or (if no
packages are given), installs all packages from Pipfile.
lock Generates Pipfile.lock.
open View a given module in your editor.
run Spawns a command installed into the virtualenv.
shell Spawns a shell within the virtualenv.
sync Installs all packages specified in Pipfile.lock.
uninstall Uninstalls a provided package and removes it from Pipfile.
update Runs lock, then sync.
常用命令记录
~ pipenv shell # 激活虚拟环境
~ pipenv run <command>
# ---
~ pipenv --where # 显示当前项目目录
~ pipenv --venv # 显示虚拟环境文件目录
~ pipenv --py # 显示虚拟环境 Python 目录
# ---
~ pipenv install xxx # 安装 xxx 包并写入配置文件
~ pipenv install xxx==1.0 # 安装指定版本的 xxx 包并写入配置文件
~ pipenv install --dev xxx # 安装开发所需的 xxx 包并写入配置文件
# ---
~ pipenv graph # 查看当前环境下安装的包及依赖关系
~ pipenv check
# ---
~ pipenv update --outdated # 检查需要更新的包
~ pipenv update # 更新所有包
~ pipenv update xxx # 更新指定的包
# ---
~ pipenv uninstall xxx # 卸载 xxx 包并从配置文件中移除
~ pipenv uninstall --all # 卸载全部包并从配置文件中移除
~ pipenv uninstall --all-dev # 卸载全部开发所需的包并从配置文件中移除
# ---
~ pipenv --rm # 删除虚拟环境以及文件,但不会删除配置文件
# ---
~ pipenv install -r requirements.txt
虽然传统的 pip install
方式仍可以安装包,但此方法并不会将其写入 Pipfile
以及 Pipfile.lock
文件。因此不是很推荐这种方法安装。
瘦身
在创建完虚拟环境后,仅安装项目所需的包。最后安装 Pyinstaller,开始打包即可。
注意
以下两种代码在打包时并没有体积差别。
import numpy as np
a = np.arange(10).reshape(2, 5)
print(a)
from numpy import arange, reshape
a = arange(10).reshape(2, 5)
print(a)
后言
如果只是在 Pyinstaller 打包瘦身的时候用虚拟环境,那就太大材小用了。
之前写 Python 小脚本的时候习惯直接 pip install
全局安装各种包。虽然问题不大,但有时候更新的时候会各种依赖版本报错。
虚拟环境很好地解决了这一点,还方便代码的分发和管理。而且,一个项目搭配一个干净的环境,想想就有点舒服。((