::-- limodou [DateTime(2005-04-08T16:31:56Z)] TableOfContents

Obj2Ini

类Ini形式的对象序列化模块

说明

参见:[http://www.donews.net/limodou/archive/2005/04/09/328275.aspx 类ini形式的对象序列化模块]

代码

   1 #coding=utf-8
   2 # dump python object to ini format file
   3 # Author: limodou ([email protected])
   4 # Copyleft GPL
   5 # $Id$
   6 
   7 import types
   8 import sys
   9 import locale
  10 
  11 def dump(obj, filename, encoding=None):
  12     if hasattr(filename, "write"):
  13         f = filename
  14     else:
  15         f = file(filename, "w")
  16     
  17     objects = {}
  18     f.write("[=%s.%s]\n" % (obj.__class__.__module__, obj.__class__.__name__))
  19     for key, value in vars(obj).items():
  20         if isinstance(value, types.InstanceType):
  21             objects[key] = value
  22         else:
  23             __write_var(f, key, value, encoding) 
  24     for key, value in objects.items():
  25         __dumpsubobj(value, key, '', f, encoding)    
  26     
  27 class EmptyClass:
  28     pass
  29 
  30 def __getparentobjname(name):
  31     a = name.split('.')
  32     return '.'.join(a[:-1])
  33 
  34 def __getmoduleandclass(name):
  35     a = name.split('.')
  36     return '.'.join(a[:-1]), a[-1]
  37 
  38 def load(obj, filename, encoding=None):
  39     if hasattr(filename, "read"):
  40         f = filename
  41     else:
  42         f = file(filename, "r")
  43 
  44     objects = {}
  45     namespace = {}
  46     currentobj = obj
  47     for line in f:
  48         line = line.strip()
  49         if not line: continue
  50         if line[0] in ('#', ';'): continue
  51         if line.startswith('[') and line.endswith(']'): #sub object
  52             #set original class 
  53             classname, classinfo = line[1:-1].split('=')
  54             module, _class = __getmoduleandclass(classinfo)
  55             __import__(module)
  56             mod = sys.modules[module]
  57             _klass = getattr(mod, _class)
  58             if classname:
  59                 sub = EmptyClass()
  60                 parentname = __getparentobjname(classname)
  61                 setattr(parentobj, classname, sub)
  62             else:
  63                 sub = currentobj
  64                 parentname = ''
  65             sub.__class__ = _klass
  66             if parentname:
  67                 parentobj = objects[parentname]
  68             else:
  69                 parentobj = currentobj
  70             objects[classname] = sub
  71             currentobj = sub
  72         else:
  73             if line.find('='):
  74                 delimeter = '='
  75             else:
  76                 delimeter = ':'
  77             key, value = line.split(delimeter, 1)
  78             key = key.strip()
  79             exec __filter(line, encoding) in namespace
  80             setattr(currentobj, key, namespace[key])
  81 
  82 def __dumpsubobj(obj, objname, parentname, filename, encoding=None):
  83     if hasattr(filename, "write"):
  84         f = filename
  85     else:
  86         f = file(filename, "w")
  87     
  88     if parentname:
  89         f.write("\n[%s.%s=%s.%s]\n" % (parentname, objname, obj.__class__.__module__, obj.__class__.__name__))
  90     else:
  91         f.write("\n[%s=%s.%s]\n" % (objname, obj.__class__.__module__, obj.__class__.__name__))
  92     objects = {}
  93     for key, value in vars(obj).items():
  94         if isinstance(value, types.InstanceType):
  95             objects[key] = value
  96         else:
  97             __write_var(f, key, value, encoding) 
  98     for key, value in objects.items():
  99         __dumpsubobj(value, key, objname, f, encoding)    
 100         
 101 def __write_var(f, key, var, encoding):
 102     f.write("%s=%s\n" % (key, __uni_prt(var, encoding)))
 103         
 104 def __uni_prt(a, encoding=None):
 105     s = []
 106     if not encoding:
 107         encodeing = locale.getdefaultlocale()[1]
 108     if not encoding:
 109         encoding = sys.getfilesystemencoding()
 110     if isinstance(a, (list, tuple)):
 111         if isinstance(a, list):
 112             s.append('[')
 113         else:
 114             s.append('(')
 115         for i, k in enumerate(a):
 116             s.append(__uni_prt(k, encoding))
 117             if i<len(a)-1:
 118                 s.append(', ')
 119         if isinstance(a, list):
 120             s.append(']')
 121         else:
 122             s.append(')')
 123     elif isinstance(a, dict):
 124         s.append('{')
 125         for i, k in enumerate(a.items()):
 126             key, value = k
 127             s.append('%s: %s' % (__uni_prt(key, encoding), __uni_prt(value, encoding)))
 128             if i<len(a.items())-1:
 129                 s.append(', ')
 130         s.append('}')
 131     elif isinstance(a, str):
 132         t = a.replace("\\", "\\\\")
 133         t = t.replace("'", r"\'")
 134         s.append("'%s'" % t)
 135     elif isinstance(a, unicode):
 136         t = a.replace("\\", "\\\\")
 137         t = t.replace("'", r"\'")
 138         s.append("u'%s'" % t.encode(encoding))
 139     else:
 140         s.append(str(a))
 141     return ''.join(s)
 142 
 143 def __filter(s, encoding):
 144     import StringIO
 145     import tokenize
 146     import token
 147     
 148     f = StringIO.StringIO(s)
 149     g = tokenize.generate_tokens(f.readline)
 150     slist = []
 151     namespace = {}
 152     for tokentype, t, start, end, line in g:
 153         if tokentype == token.STRING:
 154             if t[0] == 'u':
 155                 exec "v=" + t[1:] in namespace
 156                 slist.append(repr(unicode(namespace["v"], encoding)))
 157             else:
 158                 slist.append(t)
 159         else:
 160             slist.append(t)
 161     return ''.join(slist)
 162                 
 163 if __name__ == '__main__':
 164     class A:
 165         a = 1
 166         def __init__(self):
 167             self.b = 1
 168             self.c = unicode("'", 'utf-8')
 169             self.d = (self.c, self.b)
 170             self.e = [self.b, self.c, self.d]
 171             self.f = {self.b:self.c, self.d:self.e}
 172     
 173     a = A()
 174     #f = sys.stdout
 175     f = "obj2ini.ini"
 176     b = A()
 177     c = A()
 178     a.obj = b
 179     a.obj.obj = c
 180     dump(a, f)
 181     
 182     s = A()
 183     load(s, f)
 184     print vars(s)
 185     
 186     f = sys.stdout
 187     dump(s, f)