Простое сравнение файлов Python xlsx без метаданных - PullRequest
0 голосов
/ 01 октября 2018

Есть ли простой способ сравнить два файла xlsx в python, которые игнорируют метаданные?Пытаюсь проверить, что выходные данные скрипта соответствуют ожидаемому файлу xlsx.

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

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

РЕДАКТИРОВАТЬ: Указав engine = 'xlsxwriter' в моем вызове writer = pd.ExcelWriter (...), я могу использовать метод set_properties xlsxwriter для writer.book:

writer.book.set_properties ({'созданный ': datetime.date (1936, 10, 31)}).Это позволяет мне каждый раз записывать файл с одной и той же датой, и простой filecmp.cmp () проходит.Я все еще хотел бы услышать, есть ли способ избежать этого, потому что это довольно забавно, но эй ... это работает ...

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Файлы Xlsx - это набор файлов XML в контейнере Zip.Чтобы два xlsx-файла были бинарным эквивалентом:

  1. XML-файлы должны быть в точности одинаковыми.
  2. ZIP должен выполняться одинаково.

Для файлов XlsxWriter и, вероятно, для большинства программ zip будет таким же.Однако, это может не совпадать в программном обеспечении.

Скорее всего, XML-часть будет одинаковой.

Первым различием метаданных могут быть системные временные метки файлов перед их сжатием.(так как эти данные хранятся в zip).Для версий XlsxWriter> = 1.0.4 эта метка времени всегда «1980-01-01 00:00:00», как в Excel, поэтому она будет одинаковой.

Excel также добавляет в файл метаданные об авторе и времени создания / изменения, поэтому любые два файла, за исключением доли секунды, будут различаться.

Эти метаданные хранятся в 'docPropsФайл /core.xml 'в коллекции XML:

$ xmllint --format example/docProps/core.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cp:coreProperties xmlns:cp="...">
  <dc:creator>John</dc:creator>
  <cp:lastModifiedBy>John</cp:lastModifiedBy>
  <dcterms:created xsi:type="dcterms:W3CDTF">2018-02-23T21:20:58Z</dcterms:created>
  <dcterms:modified xsi:type="dcterms:W3CDTF">2018-02-25T02:13:23Z</dcterms:modified>
</cp:coreProperties>

Чтобы сделать их согласованными в XlsxWriter, вы можете установить свойство документа created :

workbook.set_properties({'created':  datetime.date(2018, 1, 1))

Это «хакерский» метод, на который вы ссылаетесь, но он действительно действителен.Он допускает двоичное сравнение в стиле cmp.

XlsxWriter пытается обеспечить очень высокий уровень совместимости с Excel, поэтому он имеет ~ 700 тестов, в которых он сравнивает свои результаты с файлами, созданными в Excel.Для этого используется тестовая функция с именем compare_xlsx_files().Это игнорирует метаданные стиля даты при выполнении сравнения, а также порядок некоторых элементов в других файлах метаданных "rel", которые могут различаться.Это также позволяет игнорировать определенные файлы или элементы с файлами при проведении сравнения.Модуль не экспортируется, но доступен, если вам это нужно.

0 голосов
/ 01 октября 2018

Если у вас есть два файла, подобных этому

value1   value2   value3
0.456   3.456    0.4325436
6.24654 0.235435 6.376546
4.26545 4.264543 7.2564523

и

value1   value2  value3
0.456   3.456    0.4325436
6.24654 0.23546  6.376546
4.26545 4.264543 7.2564523

Вы можете попробовать что-то вроде этого ...

from itertools import izip_longest
import xlrd

rb1 = xlrd.open_workbook('file1.xlsx')
rb2 = xlrd.open_workbook('file2.xlsx')

sheet1 = rb1.sheet_by_index(0)
sheet2 = rb2.sheet_by_index(0)

for rownum in range(max(sheet1.nrows, sheet2.nrows)):
    if rownum < sheet1.nrows:
        row_rb1 = sheet1.row_values(rownum)
        row_rb2 = sheet2.row_values(rownum)

        for colnum, (c1, c2) in enumerate(izip_longest(row_rb1, row_rb2)):
            if c1 != c2:
                print "Row {} Col {} - {} != {}".format(rownum+1, colnum+1, c1, c2)
    else:
        print "Row {} missing".format(rownum+1)

Это будет отображатьсялюбые ячейки, которые отличаются между двумя файлами.Для заданных вами двух файлов будет отображаться:

Строка 3 Кол 2 - 0,235435! = 0,23546

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...