简体   繁体   English

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

[英]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.loadsast.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM