我有通过网络套接字相互通信的服务器和客户端程序。
我想通过套接字发送从scandir.scandir()
获得的目录条目(scandir.DirEntry
)。
目前我正在使用pickle
和cPickle
模块,并提出了以下(仅摘录):
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
我怎样才能消除这个错误?
我听说使用marshall
或JSON
。UPDATE: 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()
等方法的行为设置数据。