У меня есть огромный файл, содержащий данные, который выглядит следующим образом:
H|Column1|Column2|Column3|
T|2022-07-01|00001|TEST 1|
T|2022-07-01|00002|TEST 2|
F | Record count | 2| |
Как мне создать следующее в формате YAML через Python?
Я новичок в этом, поэтому, если кто-то будет так любезен и предоставит мне пример для выполнения вышеизложенного, я буду очень благодарен.
Это должно выглядеть так:
H: T
Column1: 2022-07-01
Column2: 00001
Column3: TEST 1
-
H: T
Column1: 2022-07-01
Column2: 00002
Column3: TEST 2
Это больше похоже на файл значений, разделенных символами (CSV), чем на текстовый файл (TXT).
Ваш «желаемый результат» не является допустимым YAML.
@triplee, как я уже сказал, я новичок в этом и прошу сообщество о помощи.
Вы можете использовать библиотеки csv
и PyYAML
для импорта значений, разделенных знаком «|», а затем выгрузить их в YAML.
Программы чтения CSV (DictReader и Reader) могут использовать любой символ в качестве разделителя. Это может быть запятая, табуляция или символ входных данных, трубка |
.
DictReader считывает каждую строку CSV/TSV в объект словаря, где ключами являются имена столбцов, указанные в заголовке. Во входном файле есть пустое поле (|
в конце), которое можно удалить. В значениях полей есть некоторые начальные/конечные пробелы, которые, возможно, не нужны, и их можно удалить.
С помощью объекта словаря можно сгенерировать YAML. PyYAML может выгружать поток словарей в один вывод YAML. Поэтому, если это большой файл, вы можете прочитать входной файл, обработать его и передать выходные данные в выходной файл построчно.
import csv
import io
import yaml
input_data = ''' H|Column1|Column2|Column3|
T|2022-07-01|00001|TEST 1|
T|2022-07-01|00002|TEST 2|
F | Record count | 2| |
'''
def read_tsv(input_data):
with io.StringIO(input_data) as f:
cr = csv.DictReader(f, delimiter='|', skipinitialspace=True)
for row in cr:
del row['']
for key, value in row.items():
row[key] = value.strip()
yield row
print(yaml.dump_all(read_tsv(input_data), sort_keys=False))
Вывод выглядит следующим образом:
H: T
Column1: '2022-07-01'
Column2: '00001'
Column3: TEST 1
---
H: T
Column1: '2022-07-01'
Column2: '00002'
Column3: TEST 2
---
H: F
Column1: Record count
Column2: '2'
Column3: ''
Немного отстойно, что PyYAML всегда записывает записи в алфавитном порядке. Некоторые другие библиотеки YAML предлагают большую гибкость.
@tripleee когда я проверил help(yaml), там есть параметр sort_keys
для метода dump_all
Спасибо, давно мне не нужна была эта информация; приятно видеть, что все наконец изменилось!
Использование собственного Python без внешних библиотек,
def convert_to_yaml(data):
lines = data.strip().split('\n')
headers = lines[0].split('|')[:-1]
rows = [line.split('|') for line in lines[1:]]
yaml_text = ""
for row in rows:
for i, col_name in enumerate(headers):
yaml_text += f"{col_name}: {row[i]}\n"
yaml_text += "-\n"
return yaml_text.strip('-\n')
data = """H|Column1|Column2|Column3|
T|2022-07-01|00001|TEST 1|
T|2022-07-01|00002|TEST 2|
F | Record count | 2| |"""
print(convert_to_yaml(data))
Ч: Т
Колонка 1: 01.07.2022
Столбец 2: 00001
Столбец 3: ТЕСТ 1
-
Ч: Т
Колонка 1: 01.07.2022
Столбец2: 00002
Столбец 3: ТЕСТ 2
-
Ч: Ф
Столбец 1: количество записей
Столбец2: 2
Столбец 3:
Одна из опасностей самостоятельного анализа заключается в том, что ваши результаты могут где-то вызвать нестандартный случай. Например, ведущие нули проблематичны; вы, вероятно, захотите поместить их в кавычки. YAML довольно громоздок и имеет множество подобных особенностей. Кроме того, одиночное тире в качестве разделителя неверно (хотя я думаю, что ОП виноват в предоставлении нежелательного желаемого результата).
Реальный вопрос: почему yaml? Кажется странным. Формат, который он хочет, неэффективен. Имена столбцов повторяются n-1 раз (где n — количество строк). Я бы предпочел использовать pandas для чтения файла и передачи "|" в качестве разделителя/разделителя. Чего бы он ни хотел добиться, я уверен, что преобразование в yaml в этом формате — не лучший способ.
@tripleee Я согласен, что в целом для дампа файлов лучше использовать библиотеку YAML, поскольку она проверяет необходимость кавычек (путем считывания выгруженного узла и проверки, является ли тип по-прежнему строкой). Но ведущие нули (множественные) создают проблемы только при работе с устаревшими библиотеками, поскольку YAML 1.2 ожидает 0o
для восьмеричных чисел. Так что, по крайней мере, 00001
(без кавычек) в желаемом выводе ОП не имеет ничего плохого (другие вещи есть).
Приведите пример того, каким должен быть выходной формат YAML.