设计描述文件的python pickleable对象

sea*_*avi 3 python pickle

我想创建一个描述文件资源的类,然后将其pickle.这部分很简单.具体来说,假设我有一个类"A",它具有对文件进行操作的方法.如果它不包含文件句柄,我可以pickle这个对象.我希望能够创建文件句柄以访问"A"描述的资源.如果我在类"A"中有一个"open()"方法打开并存储文件句柄供以后使用,那么"A"不再是pickleable.(我在这里添加打开文件包括一些不能缓存的非平凡索引 - 第三方代码 - 因此在需要时关闭和重新打开并非没有费用).我可以将类"A"编码为可以生成所描述文件的文件句柄的工厂,但这可能导致多个文件句柄同时访问文件内容.我可以使用另一个类"B"来处理类"A"中文件的打开,包括锁定等.我可能会过度思考这个,但任何提示都会受到赞赏.

Gle*_*ard 6

问题不太明确; 看起来是这样的:

  • 你有一个第三方模块,它有可选择的类
  • 这些类可能包含对文件的引用,这使得类本身不可选,因为打开的文件不可选.

从本质上讲,您希望将可打开的文件设为可选.你可以相当容易地做到这一点,但有一些警告.这是一个不完整但功能齐全的样本:

import pickle
class PicklableFile(object):
    def __init__(self, fileobj):
        self.fileobj = fileobj

    def __getattr__(self, key):
        return getattr(self.fileobj, key)

    def __getstate__(self):
        ret = self.__dict__.copy()
        ret['_file_name'] = self.fileobj.name
        ret['_file_mode'] = self.fileobj.mode
        ret['_file_pos'] = self.fileobj.tell()
        del ret['fileobj']
        return ret

    def __setstate__(self, dict):
        self.fileobj = open(dict['_file_name'], dict['_file_mode'])
        self.fileobj.seek(dict['_file_pos'])
        del dict['_file_name']
        del dict['_file_mode']
        del dict['_file_pos']
        self.__dict__.update(dict)

f = PicklableFile(open("/tmp/blah"))
print f.readline()
data = pickle.dumps(f)
f2 = pickle.loads(data)
print f2.read()
Run Code Online (Sandbox Code Playgroud)

注意事项和注释,有些是显而易见的,有些则不那么:

  • 此类应直接对您获得的文件对象进行操作open.如果您在文件上使用包装类gzip.GzipFile,那些应该高于此值,而不是低于它.从逻辑上讲,将其视为装饰器类file.
  • 如果在unpickle时该文件不存在,则无法进行unpickled并将引发异常.
  • 如果它是不同的文件,则行为可能有意义也可能没有意义.
  • 如果文件模式包括文件创建('w +'),并且该文件不存在,则将创建该文件; 我们不知道要使用哪些文件权限,因为它不与文件一起存储.如果这很重要 - 它可能不应该 - 然后在您第一次创建时在类中存储正确的权限.
  • 如果文件不可搜索,尝试寻找旧位置可能会引发IOError; 如果您使用的是这样的文件,则需要决定如何处理.
  • Python 2和Python 3中的文件类是不同的; filePython 3中没有类.即使你现在只使用Python 2,也不要继承file.

我不会这样做; 根据外部文件的腌制数据不会改变并停留在同一个地方是很脆弱的.这使得甚至难以重新定位文件,因为您的pickle数据将没有意义.