最近哈里有字符串到字典的需求,本来是用 eval() 函数。但是因为这个函数可以执行除转换外的其它功能…然后这个脚本的字符串数据是来自有风险的源。
因此,用eval()感觉不是很安全,于是自己写了几个函数来做字符串到字典或列表的转换。
使用方法:
import stod as std
s="{'type':'get','count':1,'version':[1,2,3]}"
d=std.GetVarType(s)
print(d)
# 打印结果:{'type': 'get', 'count': 1, 'version': [1, 2, 3]}
print(type(d))
# 打印结果:<class 'dict'>
文件名“stod.py”,代码如下:(基于py2.7,py3注意修改一下语法)
# coding=utf-8
import re
def GetVarType(string):
# type: (str) -> any
func = GetVarFunc(string)
if func is not None:
return func(string)
for cid in xrange(len(string)):
c = string[cid]
typeInfo = GetTypeInfo(c)
if typeInfo is None:
continue
endId = typeInfo.RIndexString(string)
return typeInfo.func(string[cid + 1: endId])
print '[warn]GetVarType=', string
def GetInt(string):
# type: (str) -> any
return int(string)
def GetLongInt(string):
# type: (str) -> any
return int(string[:-1])
def GetFloat(string):
# type: (str) -> any
return float(string)
def GetBool(string):
# type: (str) -> any
return string == 'True'
def GetNone(string):
# type: (str) -> any
return None
class KeyValue(object):
def __init__(self, k, v=None):
self.key = k
self.value = v
def GetDict(string):
# type: (str) -> any
"""
找到key,value对
字符串内不算、元组内不算、字典内不算->数据类型中不算
"""
if string == '':
return {}
typeWord = []
isKey = True
keyValueTable = []
varString = ''
varNameString = ''
keyAdd = False
valueAdd = False
for cid in xrange(len(string)):
c = string[cid]
if len(typeWord) < 1:
# 绝对的最外层
nowTypeWord = GetTypeInfo(c)
if nowTypeWord is not None:
# 开始某种嵌套
typeWord.append(nowTypeWord)
varString = c
else:
# 最外层就是变量或者关键字
if re.findall(r'\S', c):
varNameString += c
if c == ':':
isKey = False
if not keyAdd:
keyValueTable.append(KeyValue(GetVarType(varNameString[:-1])))
varNameString = ''
varString = ''
keyAdd = False
elif c == ',':
isKey = True
if not valueAdd:
keyValueTable[-1].value = GetVarType(varNameString[:-1])
varNameString = ''
varString = ''
valueAdd = False
else:
# 开始内层嵌套
varString += c
nowTypeWord = GetTypeInfo(c)
if typeWord[-1].IsEnd(c):
# 同类嵌套解除
typeWord.pop(-1)
if len(typeWord) < 1:
# 如果是最外层则生效
if isKey:
keyValueTable.append(KeyValue(GetVarType(varString)))
keyAdd = True
else:
keyValueTable[-1].value = GetVarType(varString)
valueAdd = True
varString = ''
elif nowTypeWord == typeWord[-1]:
# 同类内嵌套
typeWord.append(nowTypeWord)
if not valueAdd:
keyValueTable[-1].value = GetVarType(varNameString)
return {kv.key: kv.value for kv in keyValueTable}
def GetList(string):
# type: (str) -> any
if string == '':
return []
typeWord = []
valueTable = []
varString = ''
varNameString = ''
valueAdd = False
for cid in xrange(len(string)):
c = string[cid]
if len(typeWord) < 1:
# 绝对的最外层
nowTypeWord = GetTypeInfo(c)
if nowTypeWord is not None:
# 开始某种嵌套
typeWord.append(nowTypeWord)
varString = c
else:
# 最外层就是变量或者关键字
if re.findall(r'\S', c):
varNameString += c
if c == ',':
if not valueAdd:
valueTable.append(GetVarType(varNameString[:-1]))
varNameString = ''
varString = ''
valueAdd = False
else:
# 开始内层嵌套
varString += c
nowTypeWord = GetTypeInfo(c)
if typeWord[-1].IsEnd(c):
# 同类嵌套解除
typeWord.pop(-1)
if len(typeWord) < 1:
# 如果是最外层则生效
valueTable.append(GetVarType(varString))
valueAdd = True
varString = ''
elif nowTypeWord == typeWord[-1]:
# 同类内嵌套
typeWord.append(nowTypeWord)
if not valueAdd:
valueTable.append(GetVarType(varNameString))
return valueTable
def GetTuple(string):
# type: (str) -> any
if string == '':
return ()
typeWord = []
valueTable = []
varString = ''
varNameString = ''
valueAdd = False
for cid in xrange(len(string)):
c = string[cid]
if len(typeWord) < 1:
# 绝对的最外层
nowTypeWord = GetTypeInfo(c)
if nowTypeWord is not None:
# 开始某种嵌套
typeWord.append(nowTypeWord)
varString = c
else:
# 最外层就是变量或者关键字
if re.findall(r'\S', c):
varNameString += c
if c == ',':
if not valueAdd:
valueTable.append(GetVarType(varNameString[:-1]))
varNameString = ''
varString = ''
valueAdd = False
else:
# 开始内层嵌套
varString += c
nowTypeWord = GetTypeInfo(c)
if typeWord[-1].IsEnd(c):
# 同类嵌套解除
typeWord.pop(-1)
if len(typeWord) < 1:
# 如果是最外层则生效
valueTable.append(GetVarType(varString))
valueAdd = True
varString = ''
elif nowTypeWord == typeWord[-1]:
# 同类内嵌套
typeWord.append(nowTypeWord)
if not valueAdd:
valueTable.append(GetVarType(varNameString))
return tuple(valueTable)
def GetString(string):
# type: (str) -> any
# return string.decode('utf8')
return string.decode('string-escape')
class TypeInfo(object):
def __init__(self, func, endWord):
self.func = func
self.endWord = endWord
def IsEnd(self, c):
return self.endWord == c[-1]
def RIndexString(self, string):
for cid in xrange(len(string) - 1, -1, -1):
c = string[cid]
if self.IsEnd(c):
return cid
return len(string)
wordTypeIndex = {
"'": TypeInfo(GetString, "'"),
'"': TypeInfo(GetString, '"'),
'{': TypeInfo(GetDict, '}'),
'[': TypeInfo(GetList, ']'),
'(': TypeInfo(GetTuple, ')'),
}
varIndex = {
r'^[-]{0,1}\d+$': GetInt,
r'^[-]{0,1}\d+L$': GetLongInt,
r'^[-]{0,1}\d*\.\d*[e]{0,1}[-\d]*$': GetFloat,
r'^False$': GetBool,
r'^True$': GetBool,
r'^None': GetNone,
}
def GetTypeInfo(c):
# type: (str) -> TypeInfo
try:
for k, v in wordTypeIndex.items():
if c[0] == k:
return v
except Exception as e:
print '[error]GetTypeInfo.e=', e, ',c=', c, ',len=', len(c)
def GetVarFunc(string):
for k, v in varIndex.items():
if re.findall(k, string):
return v
以上,谢谢阅读~