V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
justou
V2EX  ›  Python

如何将一个 class pickle, 在缺失源码的情况下也能 unpickle 后生成实例

  •  
  •   justou · 2023-02-03 15:55:31 +08:00 · 1596 次点击
    这是一个创建于 685 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我用一些伪代码来说明这个问题, 假设有如下目录结构

    ├── main.py
    ├── media
    │   ├── __init__.py
    │   ├── ....
    │   └── media.py
    └── player
        ├── __init__.py
        ├── ....
        └── player.py
    

    main.py 中:

    from media.media import Media
    from player.player import Player
    
    p = Player()
    m = Media()
    p(m)
    

    Media, Player的实现依赖于很多自己写的模块以及第三方模块的类和函数, 想把MediaPlayer类 pickle 到文件,

    with open('media.pkl', 'wb') as f, open('player.pkl', 'wb') as g:
    	my_super_pickle.dump(Media, f)
    	my_super_pickle.dump(Player, g)
    

    缺失源码情况下也能 unpickle 出完整的类用于生成实例正常使用:

    # 没有以上实现源码, 只有 media.pkl, 'player.pkl' 和第三方依赖的 python 环境
    with open('media.pkl', 'rb') as f, open('player.pkl', 'rb') as g:
    	Media = my_super_pickle.load(f)
    	Player = my_super_pickle.load(g)
        
    p = Player()
    m = Media()
    p(m)
    

    所以my_super_pickle 需要将项目下与 Media 和 Player 所有相关的依赖都以某种方式 pickle, 且忽略掉不在该目录下的第三方依赖.

    • 如果使用标准库的 pickle, pickle.dump(Media, f), 结果只有一条 import 语句from media.media import Media, 所以依赖于源码和原来的目录结构.
    • 使用一些工具库如: dill, cloudpickle 可以将 Media 的源码 pickle,但是无法将 Media 实现所有依赖的类也同时 pickle, 这跟直接用inspect.getsource得到源码然后用标准库的 pickle 又有什么区别呢?

    目的: 发布一些自带源码的数据包, 数据包中的数据是主角, 源码是解释数据的手段. 在后续源码更新后, 旧的数据包也能正常使用——旧的数据和旧的源码绑定在一起,新的数据跟新的源码绑定在一起.

    请问各位有什么好的解决方案?

    第 1 条附言  ·  2023-02-03 17:42:00 +08:00
    pickle 的方式主要是序列化 class instance , 可能不太适用于我的目的。使用 dill 这种工具来达到我的目的很别扭,而且不一定成功,于是我选择了另一种方式,通过将必要的包源码按照包的目录结构打包到 zip 中,把 zip 一起 pickle 到数据包,之后再从 zip 中 import 对应的 class
    1 条回复    2023-02-03 16:17:21 +08:00
    justou
        1
    justou  
    OP
       2023-02-03 16:17:21 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2669 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 15:23 · PVG 23:23 · LAX 07:23 · JFK 10:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.