【Python】不用eval和json.loads将字符串转为python对象(字典、列表、元组、整数、浮点数、字符串)

最近哈里有字符串到字典的需求,本来是用 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
      

以上,谢谢阅读~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值