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