::-- 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)