Ошибка в создании XML через Python

Была задача создать генератор XML-чека на Python с рандомными значениями каждый раз.

Я написал следующий код, но при открытии получившегося файла выдаётся ошибка error on line 1 at column 1: Encoding error

import xml.etree.ElementTree as ET
import random
import string
 
# Читаем содержимое файлов EAN.txt и INN.txt
with open("EAN.txt", "r") as f_ean:
    ean_list = [line.strip() for line in f_ean]
 
with open("INN.txt", "r") as f_inn:
    inn_list = [line.strip() for line in f_inn]
 
# Создаем корневой элемент
cheque = ET.Element("Cheque")
 
ean = random.choice(ean_list)
inn = random.choice(inn_list)
 
# Создаём функцию генератор рандомных зачений
 
def generate_random_value(data_type, min_value, max_value, step=None):
    if data_type == "int":
        return random.randint(min_value, max_value)
    elif data_type == "float":
        if step is None:
            return random.uniform(min_value, max_value)
        else:
            return round(random.uniform(min_value, max_value), step)
    elif data_type == "str_rus":
        return ''.join(random.choice(string.ascii_letters + "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ") for _ in range(random.randint(10, 20)))
    elif data_type == "str_lat":
        return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(random.randint(6, 12)))
    elif data_type == "barcode":
        return "22N" + "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(12)) + "MM66T0HVF311220130003476539219152175585956302712947101"
    elif data_type == "datetime":
        return f"{random.randint(1, 31)}{random.randint(1, 12)}{random.randint(2000, 2024)}{random.randint(0, 23)}{random.randint(0, 59)}{random.randint(0, 59)}"
    else:
        raise ValueError(f"Неизвестный тип данных: {data_type}")
 
 
 
# Добавляем атрибуты корневому элементу
cheque.set("inn", inn)
# случайное в соответствие с типом
cheque.set("kpp", generate_random_value("str_lat", 9, 10))
# случайный набор русских букв и 2ух пробелов, общая длина от 20 до 100
cheque.set("address", generate_random_value("str_rus", 20, 100))
# случайный набор русских букв длиной от 10 до 20
cheque.set("name", generate_random_value("str_rus", 10, 20))
# случайный набор латинских букв и цифр длиной от 6 до 12
cheque.set("kassa", generate_random_value("str_lat", 6, 12))
# случайное в соответствие с типом
cheque.set("shift", generate_random_value("int", 1, 10))
# случайное в соответствие с типом
cheque.set("number", generate_random_value("int", 1, 10))
# случайное в соответствие с типом
cheque.set("datetime", "0101150000")
 
# Создаем элемент "Bottle"
bottle = ET.Element("Bottle")
 
# Добавляем атрибуты элементу "Bottle"
 
# случайное от 100.00 до 1000.00
bottle.set("price", "10.00")
# случайное в соответствии с типом
bottle.set("barcode", "22N00000XOPN13MM66T0HVF311220130003476539219152175585956302712947101")
bottle.set("ean", ean)
# случайное от 0.1000 до 3.0000 с шагом 0.05
bottle.set("volume", "1.0000")
 
# Добавляем элемент "Bottle" к корневому элементу
cheque.append(bottle)
 
# Создаем XML строку
xml_string = ET.tostring(cheque, encoding="utf-8")
 
# Записываем XML строку в файл
with open("cheque.xml", "w") as f:
    f.write(xml_string.decode("utf-8"))

Подскажите, пожалуйста, в чём проблема? Есть ли какая-то ошибка в коде или это неправильное отображение?

Также, если не затруднит, оцените, пожалуйста, сам код. Впервые выполняю такого рода задачу


Ответы (1 шт):

Автор решения: CrazyElf

Скорее всего указание кодировки нужно добавить в открытие файла на запись, а decode вам не нужно, если использовать параметр encoding="unicode" в ET.tostring (этот совет подсмотрен на английском СО):

# Создаем XML строку
xml_string = ET.tostring(cheque, encoding="unicode")

# Записываем XML строку в файл
with open("cheque.xml", "w", encoding="utf-8") as f:
    f.write(xml_string)
→ Ссылка