::-- limodou [2005-04-08 16:31:56]

1. Obj2Ini

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

1.1. 说明

参见:[WWW] 类ini形式的对象序列化模块

1.2. 代码

   1 #coding=utf-8
   2 # dump python object to ini format file
   3 # Author: limodou ([email protected])
   4 # Copyleft GPL
   5 # $Id: obj2ini.py,v 1.2 2005/04/21 15:42:39 limodou Exp $
   6 #
   7 # 2005/07/31 
   8 #            1. 增加变量的支持。
   9 #            2. 修改输出的ini格式为第一行为#obj表示是对象,#var表示是变量。
  10 #            同时为了兼容性,当第一行不是#var或#obj时默认为#obj。
  11 #            3. 修改load方法的调用参数
  12 
  13 import types
  14 import sys
  15 import locale
  16 import types
  17 
  18 def dump(obj, filename, encoding=None):
  19     encoding = __getdefaultencoding(encoding)
  20 
  21     if hasattr(filename, "write"):
  22         f = filename
  23     else:
  24         f = file(filename, "w")
  25 
  26     if isinstance(obj, types.InstanceType):
  27         objects = {}
  28         f.write("#obj\n")
  29         f.write("[=%s.%s]\n" % (obj.__class__.__module__, obj.__class__.__name__))
  30         for key, value in vars(obj).items():
  31             if isinstance(value, types.InstanceType):
  32                 objects[key] = value
  33             else:
  34                 __write_var(f, key, value, encoding)
  35         for key, value in objects.items():
  36             __dumpsubobj(value, key, '', f, encoding)
  37     else:
  38         f.write("#var\n")
  39         f.write(__uni_prt(obj, encoding))
  40 
  41 class EmptyClass:
  42     pass
  43 
  44 def __getparentobjname(name):
  45     a = name.split('.')
  46     return '.'.join(a[:-1])
  47 
  48 def __getmoduleandclass(name):
  49     a = name.split('.')
  50     return '.'.join(a[:-1]), a[-1]
  51 
  52 def load(filename, obj=None, encoding=None):
  53     encoding = __getdefaultencoding(encoding)
  54 
  55     if hasattr(filename, "read"):
  56         f = filename
  57     else:
  58         f = file(filename, "r")
  59 
  60     firstline = f.readline()
  61     if firstline.startswith('#obj') or not firstline.startswith('#var'):
  62         if not firstline.startswith('#obj'):
  63             f.seek(0)
  64         objects = {}
  65         namespace = {}
  66         if not obj:
  67             obj = EmptyClass()
  68         currentobj = obj
  69         parentobj = obj
  70         for line in f:
  71             line = line.strip()
  72             if not line: continue
  73             if line[0] in ('#', ';'): continue
  74             if line.startswith('[') and line.endswith(']'): #sub object
  75                 #set original class 
  76                 classname, classinfo = line[1:-1].split('=')
  77                 module, _class = __getmoduleandclass(classinfo)
  78                 __import__(module)
  79                 mod = sys.modules[module]
  80                 _klass = getattr(mod, _class)
  81                 if classname:
  82                     sub = EmptyClass()
  83                     parentname = __getparentobjname(classname)
  84                     setattr(parentobj, classname, sub)
  85                 else:
  86                     sub = currentobj
  87                     parentname = ''
  88                 sub.__class__ = _klass
  89                 if parentname:
  90                     parentobj = objects[parentname]
  91                 else:
  92                     parentobj = currentobj
  93                 objects[classname] = sub
  94                 currentobj = sub
  95             else:
  96                 if line.find('='):
  97                     delimeter = '='
  98                 else:
  99                     delimeter = ':'
 100                 key, value = line.split(delimeter, 1)
 101                 key = key.strip()
 102                 exec __filter(line, encoding) in namespace
 103                 setattr(currentobj, key, namespace[key])
 104         return obj
 105     else:
 106         line = f.readline()
 107         namespace = {}
 108         exec __filter('var='+line, encoding) in namespace
 109         return namespace['var']
 110 
 111 def __dumpsubobj(obj, objname, parentname, filename, encoding=None):
 112     if hasattr(filename, "write"):
 113         f = filename
 114     else:
 115         f = file(filename, "w")
 116 
 117     if parentname:
 118         f.write("\n[%s.%s=%s.%s]\n" % (parentname, objname, obj.__class__.__module__, obj.__class__.__name__))
 119     else:
 120         f.write("\n[%s=%s.%s]\n" % (objname, obj.__class__.__module__, obj.__class__.__name__))
 121     objects = {}
 122     for key, value in vars(obj).items():
 123         if isinstance(value, types.InstanceType):
 124             objects[key] = value
 125         else:
 126             __write_var(f, key, value, encoding)
 127     for key, value in objects.items():
 128         __dumpsubobj(value, key, objname, f, encoding)
 129 
 130 def __write_var(f, key, var, encoding):
 131     f.write("%s=%s\n" % (key, __uni_prt(var, encoding)))
 132 
 133 def __getdefaultencoding(encoding):
 134     if not encoding:
 135         encoding = locale.getdefaultlocale()[1]
 136     if not encoding:
 137         encoding = sys.getfilesystemencoding()
 138     return encoding
 139 
 140 def __uni_prt(a, encoding=None):
 141     escapechars = [("\\", "\\\\"), ("'", r"\'"), ('\"', r'\"'), ('\b', r'\b'),
 142         ('\t', r"\t"), ('\r', r"\r"), ('\n', r"\n")]
 143     s = []
 144     encoding = __getdefaultencoding(encoding)
 145     if isinstance(a, (list, tuple)):
 146         if isinstance(a, list):
 147             s.append('[')
 148         else:
 149             s.append('(')
 150         for i, k in enumerate(a):
 151             s.append(__uni_prt(k, encoding))
 152             if i<len(a)-1:
 153                 s.append(', ')
 154         if isinstance(a, list):
 155             s.append(']')
 156         else:
 157             s.append(')')
 158     elif isinstance(a, dict):
 159         s.append('{')
 160         for i, k in enumerate(a.items()):
 161             key, value = k
 162             s.append('%s: %s' % (__uni_prt(key, encoding), __uni_prt(value, encoding)))
 163             if i<len(a.items())-1:
 164                 s.append(', ')
 165         s.append('}')
 166     elif isinstance(a, str):
 167         t = a
 168         for i in escapechars:
 169             t = t.replace(i[0], i[1])
 170         s.append("'%s'" % t)
 171     elif isinstance(a, unicode):
 172         t = a
 173         for i in escapechars:
 174             t = t.replace(i[0], i[1])
 175         s.append("u'%s'" % t.encode(encoding))
 176     else:
 177         s.append(str(a))
 178     return ''.join(s)
 179 
 180 def __filter(s, encoding):
 181     import StringIO
 182     import tokenize
 183     import token
 184 
 185     f = StringIO.StringIO(s)
 186     g = tokenize.generate_tokens(f.readline)
 187     slist = []
 188     namespace = {}
 189     for tokentype, t, start, end, line in g:
 190         if tokentype == token.STRING:
 191             if t[0] == 'u':
 192                 exec "v=" + t[1:] in namespace
 193                 slist.append(repr(unicode(namespace["v"], encoding)))
 194             else:
 195                 slist.append(t)
 196         else:
 197             slist.append(t)
 198     return ''.join(slist)
 199 
 200 if __name__ == '__main__':
 201     class A:
 202         a = 1
 203         def __init__(self):
 204             self.b = 1
 205             self.c = unicode("中\\'国", 'utf-8')
 206             self.d = (self.c, self.b)
 207             self.e = [self.b, self.c, self.d]
 208             self.f = {self.b:self.c, self.d:self.e}
 209 
 210     a = A()
 211     #f = sys.stdout
 212     f = "test1.ini"
 213     b = A()
 214     b.s = "aa\ba\"a\ns'ss\tsdd\r"
 215     c = A()
 216     a.obj = b
 217     a.obj.obj = c
 218     dump(a, f)
 219 
 220     s = load(f)
 221     print vars(s)
 222     print s.__class__.__name__
 223 
 224 #    f = sys.stdout
 225 #    dump(s, f)
 226 
 227     a = ['a', 'b',(1,2), '中文', {'a':[1,2,3]}]
 228     dump(a, 'test2.ini')
 229     b = load('test2.ini')
 230     print b

last edited 2005-07-31 09:38:07 by limodou