如何将包含dict列表的字符串转换为Python对象?
我想将丑陋的变量转换为真正的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)},
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
notast.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}]