pyinstaller可执行文件的差异更新(修改嵌入的PYZ-00.pyz)

2024-01-20

我计划创建一个巨大的可执行目录并将其安装在某些设备上。

想象一下,后来我发现我的 python 模块中有一个错误。 有没有办法只传输/复制修改后的字节码,并用新的字节码替换原始字节码。

我想这样做的原因是,在我的上下文中,带宽非常昂贵,我想远程修补代码。

示例:我有一个包含两个文件的项目:prog.py:(以下三行)

import mod1
if __name__ == "__main__":
    mod1.hello()

mod1.py:(以下两行)

def hello():
    print("hello old world")

现在我用PYTHONHASHSEED=2 pyinstaller prog.py创建我的目录并将其复制到我的设备

现在我修改mod1.py:

def hello():
    print("hello new world")

我重新编译PYTHONHASHSEED=2 pyinstaller prog.py完整目录(去皮和压缩)大小约为 10M 文件dist/prog/prog大小约为1M

with pyi-archive_viewer我可以提取PYZ-00.pyz从我的可执行文件中dist/prog/prog In PYZ-00.pyz我可以找到并提取mod1仅使用 133 字节。

现在,如果我将该文件复制到我的设备,我如何更新旧的dist/prog/prog这样,它就有了新的PYZ-00.pyz:mod1字节码。

我可以使用什么代码来分解,在替换一个特定文件(模块)后我可以使用什么代码来重新组装?

替代方案:将 pyc 文件移动到 zip 文件启动性能并不是那么重要。我还可以使用替代解决方案,其中不创建 PYZ 文件并将其添加到可执行文件中,但 dist 目录包含一个包含所有 .pyc 文件的 zip 文件

另一种选择:将 .pyc 文件复制到应用程序目录中这会导致__file__与 PYZ 模式中的值完全相同。性能方面可能不太好并创建大量文件,但如果增量更新至关重要,也许是处理它的一种选择。


这是一个相当复杂的问题,但我认为这可能至少是您正在寻找的问题的一部分。

根据你的例子,我改变了prog.py所以当从源代码运行时它导入得非常正常,但是当使用 pyinstaller 冻结时运行pyc直接文件。

import sys

def import_pyc(name):
    import py_compile
    import types
    import marshal
    
    pyversion = f"{sys.version_info.major}{sys.version_info.minor}"
    filename = f"{name}.cpython-{pyversion}.pyc"
    
    with open(filename, "rb") as pyc_file:
        # pyc files have 16 bytes reserved at the start in python 3.7+
        # due to https://www.python.org/dev/peps/pep-0552/
        # may change again in the future
        pyc_file.seek(16) 
        code_obj = marshal.load(pyc_file)

    module = types.ModuleType(name)
    exec(code_obj, module.__dict__)

    globals()[name] = module

def import_py(name):
    import importlib
    
    globals()[name] = importlib.import_module("mod1")
    
def import2(name):
    if getattr(sys, "frozen", False):
        import_pyc(name)
    else:
        import_py(name)


import2("mod1")

if __name__ == "__main__":
    mod1.hello()

这在很大程度上基于精彩的答案here https://stackoverflow.com/questions/34709390/how-can-i-import-a-pyc-compiled-python-file-and-use-it.

这意味着mod.py不是由 PyInstaller 打包的,您必须包含mod1.cpython-38.pyc作为数据文件。

执行此操作的一种便捷方法是使用命令PyInstaller --add-data "__pycache__/*;." prog.py(尽管如果您不在 Windows 上,请将分号切换为冒号)。这将所有内容都放在__pycache__文件夹,所有导入的模块,进入你的结局dist/prog文件夹。请注意,如果您多次运行此命令,PyInstaller 会将主 python 文件夹的 pyc 放入__pycache__,以便在后续运行中捆绑。

根据您捆绑和运行项目的方式,您可能会遇到当前工作目录关闭的问题,这将导致FileNotFound当你尝试加载时pycs。我不能给你一个灵丹妙药来找到你想要的路径,因为这取决于你最终如何做事,但我通常用来查找应该是当前工作目录的绝对路径的方法是os.path.dirname(sys.executable) and os.path.dirname(os.path.abspath(__file__)).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pyinstaller可执行文件的差异更新(修改嵌入的PYZ-00.pyz) 的相关文章

  • 缺少 python 配置

    我正在安装一个程序 需要安装 python config 唯一的问题是我目前没有 python config 而且我似乎不知道如何获取它 经过搜索后 我应该可以通过以下方式安装它 yum install python devel 然而 这样
  • 箱线图与箱线图有何不同?

    我想知道当我们在海生图书馆中有箱线图时为什么会有箱线图 我知道一件事是箱线图优化了表示数据的方式 特别是对于大型数据集 但我不知道为什么 除此之外 我没有任何充分的理由使用箱线图 箱线图将中位数显示为中心线 第 50 个百分位数 然后将第
  • 隐藏控制台并执行 python 脚本

    我正在尝试使用 pyinstaller 在 Windows 10 上使用 pyqt5 模块编译在 python 3 中构建的 python 脚本 该脚本在运行时隐藏窗口 为了编译我的脚本 我执行了以下命令 pyinstaller onefi
  • MySQL 的 read_sql() 非常慢

    我将 MySQL 与 pandas 和 sqlalchemy 一起使用 然而 它的速度非常慢 对于一个包含 1100 万行的表 一个简单的查询需要 11 分钟以上才能完成 哪些行动可以改善这种表现 提到的表没有主键 并且仅由一列索引 fro
  • Python:如何删除圆括号内的文本?

    我试过了 但没用 return re sub myResultStats text 建议 thanks 尝试这个 return re sub myResultStats text 括号表示捕获组 因此您必须转义它们
  • 这是我尝试安装 pip3 时得到的结果

    这是我尝试安装 pip3 时得到的结果 sudo apt get install python3 pip Reading package lists Done Building dependency tree Reading state i
  • 使用 asyncore 读取网站

    我想异步阅读一个网站 据我所知 这是不可能的 urllib 现在我尝试使用普通套接字进行阅读 但是 HTTP 给我带来了麻烦 我遇到了各种时髦的编码 例如传输编码 分块 必须手动解析所有这些东西 我现在想编码 C 而不是 python 难道
  • 使用python同时播放两个正弦音

    我正在使用 python 来播放正弦音 音调基于计算机的内部时间 以分钟为单位 但我想根据秒同时播放一个音调 以获得和谐或双重的声音 这就是我到目前为止所拥有的 有人能指出我正确的方向吗 from struct import pack fr
  • 映射器无法组装任何主键列

    我从 sqlite 表创建了一个临时表 该表是基于各种选择标准的原始表的子集 屏幕截图中有一个示例 我试图一次循环一个表记录 以便更新每个记录中的字段 我有 source table self source engine create en
  • 通过 Python 在 PostgreSQL 中的 unicode 字符串中是否允许空字节?

    unicode 字符串中是否允许空字节 我不问 utf8 我的意思是 unicode 字符串的高级对象表示 背景 我们通过 Python 在 PostgreSQL 中存储包含空字节的 unicode 字符串 如果我们再次读取字符串 字符串会
  • 将带有非字符串关键字的 dict 传递给 kwargs 中的函数

    我使用具有签名功能的库f args kwargs 我需要在 kwargs 参数中传递 python dict 但 dict 不包含关键字中的字符串 f 1 2 3 4 Traceback most recent call last File
  • Flask-httpauth: get_password 装饰器如何为 basic-auth 工作?

    我想知道有没有人用过这个烧瓶延伸 https github com miguelgrinberg flask httpauth简化 http basic auth 基本上我不明白这个example https github com migu
  • 从文件中读取单词并放入列表中

    本质上 我有一个巨大的文件 所有文件包含每行多个单词 每个单词用空格分隔 有点像这样 WORD WORD WORD WORD ANOTHER WORD SCRABBLE BLAH YES NO 我想要做的是将文件中的所有单词放入一个巨大的列
  • 遍历 globals() 字典

    我 尝试 使用globals 在我的程序中迭代所有全局变量 我就是这样做的 for k v in globals iteritems function k v 当然 这样做时 我只是创建了另外 2 个全局变量 k and v 所以我得到这个
  • __subclasses__ 没有显示任何内容

    我正在实现一个从适当的子类返回对象的函数 如果我搬家SubClass from base py 没有出现子类 subclasses 它们必须在同一个文件中吗 也许我从来没有直接导入subclass py对Python隐藏子类 我能做些什么
  • Emacs:调试Python的方法

    我把这个贴在程序员 stackexchange com https softwareengineering stackexchange com questions 29844 emacs methods for debugging pyth
  • Python 对象属性 - 访问方法

    假设我有一个具有某些属性的类 在 Pythonic OOP 中 如何访问这些属性是最好的 就像obj attr 或者也许编写 get 访问器 此类事物可接受的命名风格是什么 Edit 您能否详细说明使用单下划线或双前导下划线命名属性的最佳实
  • pip:证书失败,但curl 有效

    我们在客户端安装了根证书 https 连接适用于curl 但如果我们尝试使用pip 它失败 Could not fetch URL https installserver 40443 pypi simple pep8 There was a
  • 在Python中计算矩阵乘以其转置(AA^T)的最快方法

    在Python中将矩阵与其转置 AA T 相乘的最快方法是什么 我认为 NumPy SciPy 没有考虑使用例如时涉及的对称性 np dot or np matmul 得到的矩阵总是对称的 所以我可以想象有一个更快的解决方案 None
  • 继承自 NumPy 数组的类如何更改其自身的值?

    我有一个继承自 NumPy n 维数组的简单类 我想要该类的两个方法可以更改该类实例的数组值 其中一种方法应将类实例的数组设置为类实例的列表数据属性的值 另一种方法应将一些列表值附加到类实例的数组中 我不确定如何实现这一点 但我的尝试如下

随机推荐