2012-06-12 5 views
2

Я сбрасывал несколько defaultdict с помощью простой команды печати, например:Анализировать defaultdict строка

defaultdict(<type 'list'>, {'actual': [20000.0, 19484.0, 19420.0], 'gold': [20000.0, 19484.0, 19464.0]}) 

Есть ли какой-нибудь стандартный парсер я мог бы использовать, чтобы получить их? Я понимаю, что я должен был использовать pickle, но код, который генерировал эти defaultdict, очень медленный, и я бы хотел избежать его повторного запуска.

ответ

2

Полностью некрасиво, но работает:

s = """ 
defaultdict(<type 'list'>, {'actual': [20000.0, 19484.0, 19420.0], 'gold': [20000.0, 19484.0, 19464.0]}) 
""" 

import re, ast 

s = re.sub('^[^{]+', '', s) 
s = re.sub('[^}]+$', '', s) 

print ast.literal_eval(s) 

Обратите внимание, что это создает простой dict, не defaultdict.

+0

Предположительно, вы также можете использовать встроенный анализатор JSON. –

+0

+1 для использования 'ast'. –

5

Если тип вашего defaultdict всегда <type 'list'>, вы можете использовать следующее:

from collections import defaultdict 

s = """ 
defaultdict(<type 'list'>, {'actual': [20000.0, 19484.0, 19420.0], 'gold': [20000.0, 19484.0, 19464.0]}) 
""" 
data = eval(s.replace("<type 'list'>", 'list')) 

Люди скажут вам, что eval() небезопасно и зло, но если кто-то пытался внедрить вредоносный код в данных что вы сбросили, они, возможно, так же легко отредактировали ваш исходный код. Если текстовые файлы, которые вы извлекаете из этих данных, более доступны, чем исходный код, вы можете не использовать этот метод.

Если существует несколько типов для ваших defaultdicts, но они все встроенных типов (или легко переводить между repr и названием типа), то вы можете все еще использовать этот метод с несколькими заменами, например:

for rep, typ in ((repr(list), 'list'), (repr(dict), 'dict')): 
    s = s.replace(rep, typ) 
data = eval(s) 
+0

+1 для использования 'eval';) – georg

0

Вы можете сделать свой собственный подкласс:

from collections import defaultdict 

class mydefdict(defaultdict): 
    def __repr__(self): 
     return "mydefdict(%s, %s)" % (repr(self.default_factory()) + ".__class__", repr(dict(self))) 

, а затем использовать его как и другие типы с eval:

>>> d = mydefdict(list) 
>>> d['foo'] = [1,2,3] 
>>> d['bar'] 
[] 
>>> print d 
mydefdict([].__class__, {'foo': [1, 2, 3], 'bar': []}) 
>>> reprstring = repr(d) 
>>> d2 = eval(reprstring) 
>>> d2 
mydefdict([].__class__, {'foo': [1, 2, 3], 'bar': []}) 

Обратите внимание, что с помощью этого способа для каждой ссылки на объекты в вашей структуре будет создана отдельная копия, даже если некоторые из них являются ссылками на один и тот же объект.

Смежные вопросы