工作中有一个颇具规模的 Python 工程,发布时会用 PyInstaller 打包成exe。其中有个很小的 Python 文件会经常修改,但每次打包时间非常长。于是就想:能否用已经编译好的 pyc 文件直接替换掉 exe 中对应的内容。经过对 PyInstaller 打包的 exe 文件格式的研究,实现了这个功能。
项目地址:
https://gitee.com/bruce_code/pyisrepack.git
https://github.com/bruce-yan/pyisrepack.git
Usage: python pyisrepack.py -ori -p -o
这是Demo代码, 使用 PyInstaller 将其打包为 main.exe
import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel
def main():
app = QApplication(sys.argv)
label = QLabel("Hello world.", alignment=Qt.AlignmentFlag.AlignCenter)
label.resize(300, 200)
label.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
运行效果如下
我们将通过以下步骤将 Hello world 改为 Hello earth
Step1. 使用 pyinstxtractor 将 exe 拆包
python pyinstxtractor.py main.exe
得到如下文件
其中main.pyc是我们要修改的文件
Step2. 使用 uncompyle6 将 pyc 文件反编译成 python 源文件
uncompyle6 -o . main.pyc
Step3. 修改python代码
label = QLabel("Hello earth.", alignment=Qt.AlignmentFlag.AlignCenter)
Step4. 将修改后的python源代码编译成 pyc
uncompyle6 -c main.py
Step5. 使用 pyisrepack.py 将 pyc 重新压入 exe
python pyisrepack.py -ori main.exe -p main.pyc -o new_main.exe
Step6. 运行效果
pos, length, uncompressed, iscompressed, type, name
[(0, 225, 293, 1, 'm', 'struct'),
(225, 1025, 1706, 1, 'm', 'pyimod01_os_path'),
(1250, 4025, 8765, 1, 'm', 'pyimod02_archive'),
(5275, 7386, 17758, 1, 'm', 'pyimod03_importers'),
(12661, 1456, 3638, 1, 'm', 'pyimod04_ctypes'),
(14117, 824, 1364, 1, 's', 'pyiboot01_bootstrap'),
(14941, 512, 797, 1, 's', 'pyi_rth_subprocess'),
(15453, 701, 1065, 1, 's', 'pyi_rth_pkgutil'),
(16154, 439, 660, 1, 's', 'pyi_rth_inspect'),
(16593, 330, 441, 1, 's', 'pyi_rth_pyside6'),
(16923, 381, 529, 1, 's', 'main'),
(17304, 1173690, 1173690, 0, 'z', 'PYZ-00.pyz')]
GNU General Public License v3.0