如何将包含dict列表的字符串转换为Python对象?

如何将包含dict列表的字符串转换为Python对象?,python,Python,我想将丑陋的变量转换为真正的Python对象。 我尝试了json.loads()和ast.literal\u eval(),但它只适用于一个dict 这就是为什么在此之前,我试图将此字符串拆分为几个字典,但split()方法只有一个分隔符,因此我似乎需要一个正则表达式来完成此操作 最简单的方法是什么?谢谢。您可以使用eval ugly = "[{'ride': 1, 'pickup_time': datetime(2016, 3, 17, 15, 36, 35, 976202)},

我想将丑陋的变量转换为真正的Python对象。 我尝试了
json.loads()
ast.literal\u eval()
,但它只适用于一个dict

这就是为什么在此之前,我试图将此字符串拆分为几个字典,但
split()
方法只有一个分隔符,因此我似乎需要一个正则表达式来完成此操作

最简单的方法是什么?谢谢。

您可以使用eval

ugly = "[{'ride': 1, 'pickup_time': datetime(2016, 3, 17, 15, 36, 35, 976202)},
         {'ride': 2, 'pickup_time': datetime.datetime(2016, 3, 17, 15, 41, 35, 976202)}]"
# The actual variable contains a lot more dictionnaries...`

此时,a是一个字典列表,我相信您是从那里得到的。

首先,您应该在调用
datetime
方法时保持一致。在第一个dict中使用
datetime
,在第二个dict中使用
datetime.datetime

无论您试图以何种方式让Python对字符串求值,都不能同时让函数(第一个dict)和模块(第二个)成为日期时间。一旦你解决了这个问题,你将被迫使用邪恶的
eval
函数,因为
json.loads
not
ast.literal\u eval
都不会接受函数。它们通常被精确地用于避免调用任何函数的求值

但是,如果这是您想要做的(并且您确信
丑陋的
不包含有害的代码),那么这是可行的:

a = eval(ugly)

您可以使用
eval
获取字典数组(在修复
datetime
问题后),然后使用
setattr
将字典转换为真实的类对象:

>>> ugly = "[{'ride': 1, 'pickup_time': datetime.datetime(2016, 3, 17, 15, 36, 35, 976202)},{'ride': 2, 'pickup_time': datetime.datetime(2016, 3, 17, 15, 41, 35, 976202)}]"
>>> import datetime
>>> dlist = eval(ugly)
>>> dlist
[{'ride': 1, 'pickup_time': datetime.datetime(2016, 3, 17, 15, 36, 35, 976202)}, {'ride': 2, 'pickup_time': datetime.datetime(2016, 3, 17, 15, 41, 35, 976202)}]

根据您想要导入日期时间的方式:

from datetime import datetime

ugly = "[{'ride': 1, 'pickup_time': datetime(2016, 3, 17, 15, 36, 35, 976202)}, {'ride': 2, 'pickup_time': datetime(2016, 3, 17, 15, 41, 35, 976202)}]"
array = eval(ugly)

class Ride(object):
    pass

rides = []
for record in array:
    ride = Ride()
    for k, v in record.iteritems():
        setattr(ride, k, v)
    rides.append(ride)

for ride in rides:
    print "ride: {0}: pickup_time: {1}".format(ride.ride, ride.pickup_time)


这两种方法都可以工作,而无需事先清理
丑陋的

您可以使用正则表达式,通过提取
日期时间
及其键,仅对这些配对调用eval:

from datetime import datetime

ugly = "[{'ride': 1, 'pickup_time': datetime(2016, 3, 17, 15, 36, 35, 976202)},{'ride': 2, 'pickup_time': datetime.datetime(2016, 3, 17, 15, 41, 35, 976202)}]"
ugly = ugly.replace("datetime.", "")
ugly = eval(ugly)
将对列表进行排序,以便将正确的配对放回正确的目录中:

from datetime import datetime
from ast import literal_eval
import re


def parse(ug):
    ug = ug.replace("datetime.", "")
    pairs = ("{{{}}}".format(p) for p in re.findall("('\w+':\s+datetime\(.*\))", ug))
    _parsed = literal_eval(re.sub("datetime\(.*\)","''", ug))
    for d in _parsed:
        d.update(eval(next(pairs)))
    return _parsed

你的字典列表最初是如何变成一个字符串的?请注意,
ast.literal\u eval
可以与dict列表配合使用;它不喜欢
datetime
调用。@在我的公司里,有人喜欢以字符串形式而不是结构化方式存储对象,因为我们没有时间…@DavidD。是的,好的。有意义-类型错误的排序:“模块”对象不可调用请注意
eval
是危险的。使用时要小心。请参见@david。一条记录中有一个
datetime
,另一条记录中有一个
datetime.datetime
。你需要使它们保持一致。糟糕,没有datetime似乎是个问题。在取货时间上没有datetime。。。就像马丁很快指出的那样。
eval(丑陋的.replace('datetime(','datetime.datetime('))
谢谢!(其他人也感谢他们的回答)
from datetime import datetime
from ast import literal_eval
import re


def parse(ug):
    ug = ug.replace("datetime.", "")
    pairs = ("{{{}}}".format(p) for p in re.findall("('\w+':\s+datetime\(.*\))", ug))
    _parsed = literal_eval(re.sub("datetime\(.*\)","''", ug))
    for d in _parsed:
        d.update(eval(next(pairs)))
    return _parsed
In [4]: parse(ugly)
Out[4]: 
[{'pickup_time': datetime.datetime(2016, 3, 17, 15, 36, 35, 976202),
  'ride': 1},
 {'pickup_time': datetime.datetime(2016, 3, 17, 15, 41, 35, 976202),
  'ride': 2}]