python可嵌入和可执行版本_在Window程序中嵌入Python

最近有个项目,需在 Windows 中调用 Python,执行脚本功能。功能已完成,但接下来就是 Python 环境部署的问题。主要有2种选择:

程序安装包不自带 Python 环境,由用户在自己机子上安装Python后,再将其配置在程序的 Python 路径中;

程序安装包自带 Python 环境,用户机子可不用安装;

第一种好处是程序会小些,但对用户而言不友好;第二种则程序变大,但比较完整,对用户友好;若增加的大小在可接受范围内,则果断采取第二种。

1. embeddable 包探索

经过种种探索,Python官网提供了embeddable版本,为最小可运行环境,解压完只有 12.9 M,完美适应第二种的需求。

进一步研究,embeddable 版本是将 python 运行所需要的库全部编译为 .pyc 文件,并且把一些常用的库压缩入一个 zip 文件里,这样做有2点好处:

提升了性能:pyc 为编编译过的字节码,可直接由解释器运行;

减少了大小:zip 压缩;

若只是简单地提供了 python 运行环境,至此功能已完全满足。

然而,python 的强大与流行,还在于有大量强大的第三方包,而 embeddable 中不包含其它第三方包,也不包含 pip 等 package 管理工具。

2. embeddable 包扩展

经研究,embeddable 可进一步扩展。如下:

增加 lib/site-packages 文件夹,同完整安装包一样,用于放第三方包,可在此放入 pip 等需要的 package;

修改 python36._pth,加入 "./Lib/site-packages" ,如此 python 解释器就能找到我们添加的 lib/site-packages 包了;

0aedd7b1e1a0?from=groupmessage

python36._pth

研究 python36._pth 可知,embeddable 版本的 python 解释器是读取这里路径,因此也可以自定义 zip 包后,在此加入路径配置。

3. site-packages 预编译(可选)

一般而言,site-packages的包一般是源码,若想进一步提高性能,可预先将 .py 编译为 .pyc 文件,步骤如下(由 python 脚本来处理):

编译 /lib 里的所有文件

import compileall

compileall.compile_dir('Lib/',force=True)

编译完成后,删除 .py 的源文件;

import os

import shutil

def delete_file(folder):

for file in os.listdir(folder):

file_path=os.path.join(folder,file)

try:

if file.endswith('.py'):

if os.path.isfile(file_path):

os.unlink(file_path)

if os.path.isdir(file_path):

delete_file(file_path)

except Exception as e:

print(e)

delete_file('Lib')

编译完的 .pyc 文件在 __pycache__ 文件夹,并且文件名带 .cpython-36.pyc 的后缀,需将其拷贝至 __pycache__ 外,并去除后缀中的 .cpython-36;

import os

import shutil

from pathlib import Path

def copy_cache_files(folder):

for file_name in os.listdir(folder):

file_path=os.path.join(folder,file_name)

print(file_name)

print(file_path)

try:

if os.path.isdir(file_path):

if file_name==('__pycache__'):

parent_dir=Path(file_path).parent

print(parent_dir)

files=os.listdir(file_path)

for pyc_file in files:

print(pyc_file)

source_file=os.path.join(file_path,pyc_file)

dest_file=os.path.join(parent_dir,pyc_file)

if dest_file.endswith('cpython-36.pyc'):

dest_file=dest_file.replace('cpython-36.pyc','pyc')

print(source_file)

print(dest_file)

shutil.move(source_file,dest_file)

os.rmdir(file_path)

else:

copy_cache_files(file_path)

except Exception as e:

print(e)

copy_cache_files('Lib')

删除 __pycache__ 文件夹;

import os

import shutil

def delete_cache(folder):

for file in os.listdir(folder):

file_path=os.path.join(folder,file)

try:

if file=='__pycache__':

shutil.rmtree(file_path)

elif os.path.isdir(file_path):

delete_cache(file_path)

except Exception as e:

print(e)

delete_cache('Lib')

可先这些脚本保存为不同的 .py 文件,最好注明先后运行的脚本,存放于 embeddable 的目录下。启动 embeddable 的脚本解释器 python.exe ,按步骤输入对应的脚本文件,回车运行即可。为保险起见,可每运行一步,查看 site-packages 的变化。

当然,也可以不预先编译 .pyc ,因为 .pyc 文件会比 .py 大,且python 解释器首次运行,会自动将 .py 编译为 .pyc 文件。

4. 总结

综上,总结一下:

使用 python 官网的 embeddable 版本;

若需要,可新增 zip 包,修改 python36._pth 配置;

若需要,可增加 Lib/site-packages 文件夹,修改 python36._pth 配置;

若需要,可把 Lib/site-packages 里的 .py 文件预先编译为 .pyc 文件;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值