Как лучше преобразовать словарь Pickled Python с помощью библиотеки полки Python (bsddb) в файл JSON, содержащий значения кортежа для ключей словаря

У меня есть приложение, в котором мне нужно преобразовать файлы словаря с маринованными полками Python в файлы JSON.

import ujson, shelve

with open("shelveFile", "r") as sfile:
    shelve_dict=shelve.open(sfile)
    py_dict= dict(shelve_dict)
    with open("jsonfile.json","w") as jsonfile:
        ujson.dump(py_dict, jsonfile)
    with open("jsonfile.json",'r') as readJSONfile:
        ujson.loads(readJSONfile.read())

Примечание. Если я использую ujson.load(jsonfile2), я получаю ошибку сериализации.

У меня есть проблема: файл полки использует типы данных кортежа Python для некоторых ключей словаря. Я могу использовать ujson.dump для сохранения в формате JSON, но когда я пытаюсь использовать ujson.load(jsonfile), ключи загружаются в виде строк, а не кортежей. Если не считать использования понимания словаря для преобразования ключей (неуверенный в этом точном синтаксисе), существует ли библиотека, которая преобразовала бы файл полки в файл JSON, который я мог бы загрузить обратно в объект словаря Python?

При загрузке методом ujson.loads(fileobj.read()):

{"('tuplekey1','tuplekey2')": value,}

Должно быть:

{('tuplekey1','tuplekey2'): value,} 

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


person Mark    schedule 19.12.2018    source источник
comment
Один из способов — использовать ast.literal_eval и оценить результирующие ключи dict, как в этом примере: {ast.literal_eval(k): v for k, v in my_dict.items()}   -  person Chiheb Nexus    schedule 19.12.2018


Ответы (1)


Кортежи нельзя использовать в качестве ключей словаря, если вы хотите сохранить данные с помощью shelve или json. Итак, в вашем случае вместо фактических кортежей использовалось строковое представление кортежей - repr(('tuplekey1', 'tuplekey2')) дает "('tuplekey1', 'tuplekey2')".

Поэтому вам нужен дополнительный шаг для разбора строк в кортежи. Например, eval("('tuplekey1', 'tuplekey2')") или tuple(val.strip("()' ") for val in a.split(',')). Конечно, вам нужно знать (или распознавать), какие строки следует разбирать на кортежи.

Проблемы можно избежать - данные должны храниться другим способом - другое представление кортежей или другая структура данных.

person Poolka    schedule 19.12.2018
comment
Я согласен с тем, что данные должны были храниться другим способом, не используя кортежи для ключей, но пока я просто пытаюсь отказаться от использования полки. Должен ли я анализировать JSON вручную? Я пытался избежать этого. - person Mark; 19.12.2018
comment
Единственное ограничение для ключей словаря Python заключается в том, что вы должны использовать неизменяемые объекты. Таким образом, как в Python 2.7.15, так и в Python 3.7 это будет допустимо: d = {('testkey1','testkey2'): "myvalune"} >>> d {('testkey1', 'testkey2'): 'myvalune'}. - person Mark; 19.12.2018
comment
Кроме того, хотя и не рекомендуется, вы можете сохранять данные в файле полки с кортежами, но вы должны передать полный словарь (с ключами кортежа) в качестве значения для ключа в словаре полки: shelve_dict['dict_one'] = {('tkey1', 'tkey2') : "myvalue" }` - person Mark; 19.12.2018
comment
@Марк Только что попробовал. Кортежи действительно могут использоваться в значениях shelve. Почему бы и нет, если их можно мариновать, да? Спасибо за замечание. Что касается ваших данных, они содержат строки, а не кортежи. Таким образом, вы просто не можете избежать синтаксического анализа. Проблема не выглядит очень сложной - я думаю, несколько строк кода. Более того, любой инструмент для синтаксического анализа потребует от вас его настройки. И это может быть сложнее, чем этот разбор. - person Poolka; 19.12.2018
comment
Да, я отметил ваш ответ как ответ. После безуспешного поиска библиотеки, в которой это встроено, я просто снова проанализировал словарь после его загрузки и использовал eval для приведения строкового представления кортежа к фактическому кортежу. Это было не очень элегантно, потому что я знаю, что все ключи в моем конкретном исходном файле JSON являются кортежами и имеют только один уровень глубины. Он не применял логику рекурсивно и не проверял сначала строку, чтобы увидеть, действительно ли это кортеж. Спасибо за публикацию решения. - person Mark; 20.12.2018