функция eval не превращает строку, подобную dict, в dict?

#python #string #dictionary #eval

Вопрос:

Итак, у меня есть несколько строк в столбце фрейма данных, которые выглядят, например, так:

 {'Free to Play': 17555, 'Multiplayer': 10499, 'FPS': 9248, 'Action': 8188, 'Shooter': 7857, 'Class-Based': 6098, 'Team-Based': 5363, 'Funny': 5155, 'First-Person': 4846, 'Trading': 4512, 'Cartoony': 4240, 'Competitive': 4116, 'Online Co-Op': 4016, 'Co-op': 3920, 'Robots': 3112, 'Comedy': 3049, 'Tactical': 2726, 'Crafting': 2491, 'Cartoon': 2450, 'Moddable': 2315}
 

Я пытаюсь получить доступ к ключам dict, но, поскольку это все еще строка, я хотел преобразовать ее в словари и нашел людей, которые говорят, что для этого можно использовать eval. И да, когда я пытаюсь так, это работает нормально, и test_dict имеет тип dict:

 test_str = "{'Early Access': 77, 'RPG': 202}"
test_dict = eval(test_str)
 

Тем не менее, при работе со строками в фрейме данных

 tags = main_data["tags"]

for taglist in tags:
    taglist = """   taglist   """
    tag_dict = eval(taglist)
 

tag_dict всегда остается строкой, и после некоторых строк eval выдает ошибки, подобные этим:

 File "<string>", line 1
    "{'Action': 2681, 'FPS': 2048, 'Multiplayer': 1659, 'Shooter': 1420, 'Classic': 1344, 'Team-Based': 943, 'First-Person': 799, 'Competitive': 790, 'Tactical': 734, "1990's": 564, 'e-sports': 550, 'PvP': 480, 'Military': 367, 'Strategy': 329, 'Score Attack': 200, 'Survival': 192, 'Old School': 164, 'Assassin': 151, '1980s': 144, 'Violent': 40}"
                                                                                                                                                                        ^
SyntaxError: invalid syntax
 

Я обнаружил, что это может быть проблемой с длиной строк, так как при использовании taglist = """"" taglist """"" eval не выдает никаких ошибок, проходит через все строки, но все равно они не преобразуются в dict и остаются str.

Может быть, я совершил какую-то ошибку новичка или есть лучшие подходы к решению моей проблемы?

Комментарии:

1. в сообщении отображается ошибка, строка недопустима. он содержит » … «1990-е годы»: 564 …`

2. Попробуйте удалить """ список тегов вокруг.

3. Почему вы добавили двойные кавычки в строку? Если бы не синтаксическая ошибка, eval() ing просто выдал бы строку.

4. Зачем ты это делаешь """ taglist """ ???

5. Послушайте, лучший подход — не пытайтесь использовать такие строки . В первую очередь, почему они такие струны?

Ответ №1:

Поскольку вы сериализуете свой диктант на какое-то внешнее хранилище, я бы использовал json. Он предназначен для этого, в то время как эвал … хитер. И вы на самом деле запускаете код, поэтому, что бы кто-то ни поместил в базу данных, вы будете его запускать.

Есть одна загвоздка. Json ожидает двойные кавычки. Поскольку он уже записан в базу данных в виде кода python с одинарными кавычками вокруг ключей словаря, вам придется преобразовать их в двойные кавычки, чтобы они были законными json. Я бы предложил исправить это один раз в базе данных, а затем использовать json в дальнейшем.

 import json

data_dict = {'Free to Play': 17555, 'Multiplayer': 10499, 'FPS': 9248, 'Action': 8188, 'Shooter': 7857, 'Class-Based': 6098, 'Team-Based': 5363, 'Funny': 5155, 'First-Person': 4846, 'Trading': 4512, 'Cartoony': 4240, 'Competitive': 4116, 'Online Co-Op': 4016, 'Co-op': 3920, 'Robots': 3112, 'Comedy': 3049, 'Tactical': 2726, 'Crafting': 2491, 'Cartoon': 2450, 'Moddable': 2315}
data_dict.update({'Early Access': 77, 'RPG': 202})
data_string = json.dumps(data_dict)

# write it to a file or database
# read it later, we'll assume that's data_string

data_dict = json.loads(data_string)
print (data_dict['RPG'])

database_string = "{'Free to Play': 17555, 'Multiplayer': 10499, 'FPS': 9248, 'Action': 8188, 'Shooter': 7857, 'Class-Based': 6098, 'Team-Based': 5363, 'Funny': 5155, 'First-Person': 4846, 'Trading': 4512, 'Cartoony': 4240, 'Competitive': 4116, 'Online Co-Op': 4016, 'Co-op': 3920, 'Robots': 3112, 'Comedy': 3049, 'Tactical': 2726, 'Crafting': 2491, 'Cartoon': 2450, 'Moddable': 2315}"

# this isn't a general purpose converter, but works for this case
# just to change the single quotes to double quotes
converted_to_legal_json = database_string.replace("'", '"')
data_dict = json.loads(converted_to_legal_json)
print (data_dict['Multiplayer'])
 

Я, вероятно, могу исправить вашу оценку, если вы хотите, но не могу сделать это прямо сейчас. Но, как я уже сказал, не рекомендуется. И я бы использовал ast.literal_eval вместо того, чтобы фактически выполнять его с помощью eval, по соображениям безопасности.