如何序列化一个扫描目录.Python中用于通过网络套接字发送的DirEntry



我有通过网络套接字相互通信的服务器和客户端程序。

我想通过套接字发送从scandir.scandir()获得的目录条目(scandir.DirEntry)。

目前我正在使用picklecPickle模块,并提出了以下(仅摘录):

import scandir, pickle
s = scandir.scandir("D:\PYTHON")
entry = s.next()
data = pickle.dumps(entry)

然而,我得到以下错误堆栈:

File "untitled.py", line 5, in <module>
  data = pickle.dumps(item)
File "C:Python27Libpickle.py", line 1374, in dumps
  Pickler(file, protocol).dump(obj)
File "C:Python27Libpickle.py", line 224, in dump
  self.save(obj)
File "C:Python27Libpickle.py", line 306, in save
  rv = reduce(self.proto)
File "C:Python27Libcopy_reg.py", line 70, in _reduce_ex
  raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle DirEntry objects

我怎样才能消除这个错误?

我听说使用marshallJSONUPDATE: JSON不转储对象中的所有数据。

是否有完全不同的方式通过套接字发送对象?

提前感谢您的帮助。

是的,os.DirEntry对象旨在是短暂的,而不是真正保存或序列化。如果您需要序列化其中的数据,看起来您已经在自己的答案中找到了答案——序列化(pickle)您需要的属性的字典版本。

要反序列化成一个像os.DirEntry实例一样的对象,创建一个PseudoDirEntry类来模仿你需要的东西。

请注意,您可以直接序列化stat对象,这节省了您从中选择字段的时间。

组合起来,看起来像这样:

class PseudoDirEntry:
    def __init__(self, name, path, is_dir, stat):
        self.name = name
        self.path = path
        self._is_dir = is_dir
        self._stat = stat
    def is_dir(self):
        return self._is_dir
    def stat(self):
        return self._stat

然后:

>>> import os, pickle
>>> entry = list(os.scandir())[0]
>>> pickled = pickle.dumps({'name': entry.name, 'path': entry.path, 'is_dir': entry.is_dir(), 'stat': entry.stat()})
>>> loaded = pickle.loads(pickled)
>>> pseudo = PseudoDirEntry(loaded['name'], loaded['path'], loaded['is_dir'], loaded['stat'])
>>> pseudo.name
'.DS_Store'
>>> pseudo.is_dir()
False
>>> pseudo.stat()
os.stat_result(st_mode=33188, st_ino=8370294, st_dev=16777220, st_nlink=1, st_uid=502, st_gid=20, st_size=8196, st_atime=1478356967, st_mtime=1477601172, st_ctime=1477601172)

我自己已经发现,对于像scandir.DirEntry这样的非标准类的实例,最好的方法是将类成员数据转换为(可能嵌套的)标准对象的组合,如(list, dict等)。

例如,在scandir.DirEntry的特殊情况下,可以这样做:

import scandir, pickle
s = scandir.scandir("D:\PYTHON")
entry = s.next()
# first convert the stat object to st_
st = entry.stat()
st_ = {'st_mode':st.st_mode, 'st_size':st.st_size,
   'st_atime':st.st_atime, 'st_mtime':st.st_mtime,
   'st_ctime':st.st_ctime}
# now convert the entry object to entry_
entry_ = {'name':entry.name, 'is_dir':entry.is_dir(), 
 'path':entry.path, 'stat':st_}
# one may need some other class member data also as necessary
# now pickle the converted entry_
data = pickle.dumps(entry_)

虽然出于我的目的,我只需要数据,但在另一端进行解pickle之后,可能需要重建未pickle的entry_到未pickle的scandir.DirEntry对象'entry'。然而,我还没有弄清楚如何重构类实例并为 is_dir(), stat()等方法的行为设置数据。

最新更新