关于python:不同模块中的Pickling和Unpickling

Pickling and Unpickling in different modules

我知道这已经被许多其他问题所覆盖(无法使用pickle和multipile模块加载文件)但我看不出他们的解决方案如何适用于我的情况。

这是我的项目结构(尽可能少):

1
2
3
4
5
6
7
classify-updater/
├── main.py
└── updater
    ├── __init__.py
    └── updater.py
classify
└── main.py

classify-updater/main.py中:

1
2
3
4
5
6
7
8
9
10
11
import sys
from sklearn.feature_extraction.text import CountVectorizer
from updater.updater import Updater

def main(argv):
    vectorizer = CountVectorizer(stop_words='english')
    updater = Updater(vectorizer)
    updater.update()

if __name__ =="__main__":
    main(sys.argv)

classify-updater/updater/updater.py中:

1
2
3
4
5
6
7
8
9
10
11
import dill

class Updater:

    def __init__(vectorizer):
        vectorizer.preprocessor = lambda doc: doc.text.encode('ascii', 'ignore')
        self.vectorizer = vectorizer

    def update(self):
        pickled_vectorizer = dill.dumps(self.vectorizer)
        # Save to Google Cloud Storage

classify/main.py

1
2
3
4
5
6
7
8
9
import dill
import sys

def main(argv):
    # Load from Google Cloud Storage
    vectorizer = dill.loads(vectorizer_blob)

if __name__ =="__main__":
    main(sys.argv)

这导致ImportError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Traceback (most recent call last):
  File"classify.py", line 102, in <module>
    app.main(sys.argv)
  File"classify.py", line 50, in main
    vectorizer = self.fetch_vectorizer()
  File"classify.py", line 86, in fetch_vectorizer
    vectorizer = dill.loads(vectorizer_blob.download_as_string())
  File"/usr/local/lib/python2.7/site-packages/dill/dill.py", line 299, in loads
    return load(file)
  File"/usr/local/lib/python2.7/site-packages/dill/dill.py", line 288, in load
    obj = pik.load()
  File"/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 864, in load
    dispatch[key](self)
  File"/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1096, in load_global
    klass = self.find_class(module, name)
  File"/usr/local/lib/python2.7/site-packages/dill/dill.py", line 445, in find_class
    return StockUnpickler.find_class(self, module, name)
  File"/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1130, in find_class
    __import__(module)
ImportError: No module named updater.updater

在其他地方已经解释过,pickle需要类定义来加载对象,但是我无法看到对updater模块的引用来自何处,因为我只是在腌制Vectorizer的一个实例。

我大量简化了这个例子。 就我们的代码库而言,这两个软件包相距甚远。 将一个模块导入另一个模块可能不可行。 有什么方法可以解决这个问题吗?


这里的问题是lambda(匿名函数)。

完全可以腌制像Vectorizer这样的自包含对象。 但是,示例中使用的预处理函数的作用域是Updater类,因此需要Updater类进行unpickle。

不是拥有预处理器功能,而是自己预处理数据并将其传递给适合矢量化器。 这将在unpickling时删除对Updater类的需求。