如何通过pip安装编译后的.pyc格式Python包用于部署
问题原因
pip的--compile参数仅会在安装过程中对源文件执行编译操作,但生成的.pyc文件默认存储在各模块目录下的__pycache__子目录中,文件名携带Python版本标识(如.cpython-37.pyc),且不会自动删除原始.py源文件,因此你直接打包时拿到的仍然是源文件。
解决方法
调整代码,在依赖安装完成后新增编译、pyc文件规整、源文件删除的逻辑即可,修改后的可运行代码如下:
import tempfile import subprocess import shutil import os import compileall import glob temp_dir = tempfile.mkdtemp() try: # 安装依赖 subprocess.call([ 'pip', 'install', '-r', 'requirements.txt', '-t', temp_dir, '--compile', '--no-cache-dir' # 避免本地缓存干扰编译流程 ]) # 二次编译目录下所有.py文件,确保无遗漏 compileall.compile_dir(temp_dir, quiet=1) # 处理所有编译生成的pyc文件 for root, dirs, files in os.walk(temp_dir): if '__pycache__' in root: continue pycache_dir = os.path.join(root, '__pycache__') if not os.path.exists(pycache_dir): continue # 匹配Python3.7版本对应的pyc文件 for pyc_path in glob.glob(os.path.join(pycache_dir, '*.cpython-37.pyc')): # 重命名为标准pyc文件名,移动到对应模块的同级目录,保证import逻辑正常 pyc_name = os.path.basename(pyc_path).replace('.cpython-37.pyc', '.pyc') target_path = os.path.join(root, pyc_name) shutil.move(pyc_path, target_path) # 删除已处理完毕的空__pycache__目录 shutil.rmtree(pycache_dir) # 删除所有.py源文件 for root, dirs, files in os.walk(temp_dir): for file in files: if file.endswith('.py'): os.remove(os.path.join(root, file)) add_to_zip(package, temp_dir) finally: shutil.rmtree(temp_dir)
注意事项
- 编译环境的Python版本必须和部署环境完全一致,否则
.pyc文件无法正常加载 - 上述逻辑不会误删依赖包中的二进制扩展文件(
.so/.pyd/.dll)、静态资源、配置文件等非.py后缀的必要文件 - 若不需要保留
.pyi类型的类型注解文件,可在删除.py源文件的步骤中添加规则同步删除
内容的提问来源于stack exchange,提问作者xulo
相关产品推荐
相关产品推荐

