Eval на хитрых строковых формах defaultdict

Каким-то образом я передал текстовые файлы defaultdict, сохраненные с помощью str() Метод и строка utf8 читает:

defaultdict(<class 'set'>, {'protection': {'1058c_204062v_00:39:16->00:39:18_ko'}, 'protect': {'50c_45523v_00:01:22->00:01:24_ko', '5457c_150765v_00:08:34->00:08:37_ko', '5457c_144739v_00:34:25->00:34:28_ko', '1058c_204062v_00:39:36->00:39:39_ko', '504c_68856v_00:15:47->00:15:49_ko'}})

Когда я использую eval()Кидает:

Traceback (most recent call last):
  File "consolidate.py", line 9, in <module>
    print (eval(translation_counter), ast.literal_eval(location))
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ast.py", line 46, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    defaultdict(<class 'set'>, {'protection': {'1058c_204062v_00:39:16->00:39:18_ko'}, 'protect': {'50c_45523v_00:01:22->00:01:24_ko', '5457c_150765v_00:08:34->00:08:37_ko', '5457c_144739v_00:34:25->00:34:28_ko', '1058c_204062v_00:39:36->00:39:39_ko', '504c_68856v_00:15:47->00:15:49_ko'}})
                ^
SyntaxError: invalid syntax

Согласно /questions/46358750/obrabotka-escape-posledovatelnostej-v-stroke-v-python/46358762#46358762, я также пытался ast.literal_eval() и он выдает ту же ошибку, что и выше.

Затем я попытался каким-то образом избежать его, используя `.replace('_', '_'), и он бросил это:

Traceback (most recent call last):
  File "consolidate.py", line 9, in <module>
    print (eval(translation_counter), ast.literal_eval(location.replace('_', r'\_')))
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ast.py", line 46, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    defaultdict(<class 'set'>, {'protection': {'1058c\_204062v\_00:39:16->00:39:18\_ko'}, 'protect': {'50c\_45523v\_00:01:22->00:01:24\_ko', '5457c\_150765v\_00:08:34->00:08:37\_ko', '5457c\_144739v\_00:34:25->00:34:28\_ko', '1058c\_204062v\_00:39:36->00:39:39\_ko', '504c\_68856v\_00:15:47->00:15:49\_ko'}})
                ^
SyntaxError: invalid syntax

Полный код:

# -*- coding: utf-8 -*-

from collections import defaultdict, Counter
import ast

with open('related.txt', 'r', encoding='utf8') as fin:
    for line in fin:
        location = line.strip()
        print (eval(location))

И head -n1 related.txt выглядит так:

defaultdict(<class 'set'>, {'protection': {'1058c_204062v_00:39:16->00:39:18_ko'}, 'protect': {'50c_45523v_00:01:22->00:01:24_ko', '5457c_150765v_00:08:34->00:08:37_ko', '5457c_144739v_00:34:25->00:34:28_ko', '1058c_204062v_00:39:36->00:39:39_ko', '504c_68856v_00:15:47->00:15:49_ko'}})

1 ответ

Решение

Это потому что <class 'set'> не может быть eval'd. Вам нужно будет извлечь класс из него

p = re.compile(r"^defaultdict\(<class '(\w+)'>")
c = p.findall(s)[0]

а затем заменить его именем класса

new_s = s.replace("<class '%s'>"% c, c)

Эта строка должна быть в состоянии eval с этим результатом

defaultdict(set,
        {'protect': {'1058c_204062v_00:39:36->00:39:39_ko',
          '504c_68856v_00:15:47->00:15:49_ko',
          '50c_45523v_00:01:22->00:01:24_ko',
          '5457c_144739v_00:34:25->00:34:28_ko',
          '5457c_150765v_00:08:34->00:08:37_ko'},
         'protection': {'1058c_204062v_00:39:16->00:39:18_ko'}})
Другие вопросы по тегам