Как исправить ошибку с более чем 3 кавычками при сохранении в базу
При сохранении данных в базу у меня возникает ошибка:
SyntaxError: EOF while scanning triple-quoted string literal
Данные, которые пытаюсь сохранить:
Остров гоага '''
1000 символов и одна святая ложка ''""
Полностью:
products_dict = {('category', 'key:15', 'title:PYTHON'): {'#677': {'title': 'Остров гоага '''', 'description': '1000 символов и одна святая ложка ''""', 'price': '19'}}}
Мой sql-запрос для сохранения (sqlite3):
sql.execute(f'''UPDATE products SET products = "{products_dict}"''')
save.commit()
Какие есть способы решения этой проблемы с сохранением и извлечением?
Для чего это нужно? - я должен иметь возможность сохранять любой текст в базу, с разными кавычками и разным количеством кавычек.
Ответы (2 шт):
Странный словарь и странное использование базы данных :)
Странный словарь потому что выглядит очень подозрительно строка 'title': 'Остров гоага '''', почему тройные одинарные кавычки закрывают только справа, а слева их нет? Т.е., у вас просто синтаксически неправильный код, наверняка, в этом месте ошибка скрипта
Исправил словарь, чтобы не было проблем:
products_dict = {
('category', 'key:15', 'title:PYTHON'): {
'#677': {
'title': 'Остров гоага',
'description': '1000 символов и одна святая ложка',
'price': '19'
}
}
}
UPD. Варианты исправления синтаксиса с сохранением кавычек в строках:
products_dict = {('category', 'key:15', 'title:PYTHON'): {'#677': {'title': 'Остров гоага \'\'\'', 'description': '1000 символов и одна святая ложка ''""', 'price': '19'}}}
products_dict = {('category', 'key:15', 'title:PYTHON'): {'#677': {'title': "Остров гоага '''", 'description': '1000 символов и одна святая ложка ''""', 'price': '19'}}}
products_dict = {('category', 'key:15', 'title:PYTHON'): {'#677': {'title': """Остров гоага '''""", 'description': '1000 символов и одна святая ложка ''""', 'price': '19'}}}
Насчет базы данных... Первое, что бросается в глаза - вы словарь помещаете в запрос как есть, а синтаксис словаря не поддерживается SQL, поэтому будет такая ошибка:
sqlite3.OperationalError: near "products": syntax error
И не нужно вручную формировать запрос с параметрами, нужно использовать биндинга, вот так:
sql.execute('UPDATE products SET products=?', [products_dict])
Но это полбеды, т.к. sqlite3 не поддерживает тип словаря, будет такая ошибка:
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
Можно попробовать сохранить словарь в строку, например через JSON, но и тут будет фигня, т.к. у вас словарь специфичный, его ключ составной, поэтому при сохранении в JSON будет ошибка, т.к. в ключах словаря лучше использовать простые типы:
TypeError: keys must be str, int, float, bool or None, not tuple
Это можно обойти, но это будет костылями. Получить строковое представление словаря через str(products_dict), но возникнет проблем парсинга, если понадобится получить обратно, придется парсить чем-то вроде ast.literal_eval из модуля ast:
sql.execute('UPDATE products SET products=?', [str(products_dict)])
Думаю, правильным решением будет создание нескольких таблиц в базе и заполнения их от этого словаря.
Например, таблицы:
Product(поля id, title, description, price). От вашего словаря это будут значения:id=677, title='Остров гоага', description='1000 символов и одна святая ложка', price=19Category(поля key, title). Значения:key=15 и title=PYTHON
Если у одного продукта одна категория, то можно в Product хранить категорию в category_id, если категорий несколько, то создать связанную таблицу Product2Category с полями product_id и category_id
У вас тут комбинация двух проблем
- неправильное задание строковых литералов
- использование подстановок параметров в строку в sql запросе
Что касается строковых литералов, то для того чтобы задавать абсолюно произвольный стороковый литерал пользуйтесь простым правилом: экранируйте все символы того типа кавычек, который используете для обозначения начала и конца литерала. Вот примеры строк и то как их нужно задавать в виде строкового литерала в коде (я тут использую одинарную кавычку, но то же самое применимо и к двойным):
+----------------------------------------+----------------------------------------
Строка | Литерал
-----------------------------------------+----------------------------------------
abc | 'abc'
Остров гоага ''' | 'Остров гоага \'\'\''
1000 символов и одна святая ложка ''"" | '1000 символов и одна святая ложка \'\'""'
Простой способ увидеть этот литерал это заставить питон конвертировать строку с помощью input() (способ годится если нет переводов строки). То есть исполнить в терминале:
>>> x=input()
Потом ввести или вставить текст:
1000 символов и одна святая ложка ''""
В переменной х теперь строка и если вывести ее представление, то она будет в экранированном виде (в таком какой нужно использовать для задания литерала):
>>> print(repr(x))
'1000 символов и одна святая ложка \'\'""'
Для сохранения в БД dict-а, как строки, нужно его сначала сериализовать. Можно делать по разному. Простой споcоб это использовать str:
products_dict_str = str(products_dict)
При загрузке из БД нужно будет строку десериализовать с помощью literal_eval:
products_dict = ast.literal_eval(products_dict_str)
Во-вторых, нужно использовать связываемые переменные, а не манипуляции со строками:
sql.execute('UPDATE products SET products=?', [products_dict_str])