[英]How to convert a string containing a list of dict into Python object?
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...`
I'd like to convert the ugly variable as a real Python object. 我想将丑陋的变量转换为真正的Python对象。 I tried
json.loads()
and ast.literal_eval()
but it's for one dict only. 我尝试过
json.loads()
和ast.literal_eval()
但它只适用于一个dict。
That's why, before that, I tried to split this string into several dictionnaries, but the split()
method has only one delimiter, so it seems I could need a REGEX to do this. 这就是为什么在此之前,我试图将这个字符串拆分成几个字典,但
split()
方法只有一个分隔符,所以看起来我需要一个REGEX才能做到这一点。
What is the simplest way to do it? 最简单的方法是什么? Thanks.
谢谢。
Well first you should be consistent in you calls to datetime
method. 首先,你应该在调用
datetime
方法时保持一致。 In first dict, you use datetime
and in second datetime.datetime
. 在第一个dict中,您使用
datetime
和第二个datetime.datetime
。
Whatever way you try to have Python eval the string, you cannot have at the same time datetime
be a function (first dict) and a module (second). 无论你尝试使用Python eval字符串,你都不能同时将
datetime
作为一个函数(第一个字典)和一个模块(第二个)。 Once you fix that, you will be forced to use the evil eval
function, because neither json.loads
not ast.litteral_eval
will accept a function. 一旦你解决这个问题,你将被迫使用邪恶
eval
函数,因为无论json.loads
不ast.litteral_eval
将接受一个函数。 They are normally used precisely to avoid the evaluation to call any function... 它们通常用于精确地避免评估调用任何函数...
But if this is what you want to do (and you are sure that ugly
contains no harmful code), this works: 但如果这是你想要做的(并且你确定
ugly
包含有害代码),这可行:
>>> 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)}]
You can use eval 你可以使用eval
a = eval(ugly)
At this point a is a list of dictionaries and I am sure you got it from there. 在这一点上,a是一个词典列表,我相信你从那里得到它。
You can use eval
to get the array of dictionaries (after fixing the datetime
issue), and then use setattr
to turn the dictionaries into real class objects: 您可以使用
eval
来获取字典数组(在修复datetime
问题之后),然后使用setattr
将字典转换为实际的类对象:
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)
Depending on how you want to import datetime
: 根据您要导入
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(", " datetime.datetime(")
ugly = eval(ugly)
or 要么
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)
Both work without prior cleaning of ugly
两者都没有预先清理
ugly
You could do it with a regex by extracting the datetimes
and their keys only calling eval on those pairings: 你可以通过提取
datetimes
和它们的键只对这些配对调用eval来使用正则表达式:
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
The lists are going to be ordered so the correct pairing will be put back in the correct dicts: 列表将被订购,因此正确的配对将被放回正确的序列中:
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}]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.