После просмотра кода Pandas для записи CSV лучшее, что я могу предложить, - это использовать модуль gzip
напрямую. таким образом, вы можете установить атрибут mtime
напрямую, что, как вам кажется:
import pandas as pd
from gzip import GzipFile
from io import TextIOWrapper
def to_gzip_csv_no_timestamp(df, f, *kwargs):
# Write pandas DataFrame to a .csv.gz file, without a timestamp in the archive
# header, using GzipFile and TextIOWrapper.
#
# Args:
# df: pandas DataFrame.
# f: Filename string ending in .csv (not .csv.gz).
# *kwargs: Other arguments passed to to_csv().
#
# Returns:
# Nothing.
with TextIOWrapper(GzipFile(f, 'w', mtime=0), encoding='utf-8') as fd:
df.to_csv(fd, *kwargs)
to_gzip_csv_no_timestamp(df, 'df.csv.gz')
to_gzip_csv_no_timestamp(df, 'df2.csv.gz')
filecmp.cmp('df.csv.gz', 'df2.csv.gz')
# True
Это превосходит двухэтапный подход subprocess
ниже для этого крошечного набора данных:
%timeit to_gzip_csv_no_timestamp(df, 'df.csv')
693 us +- 14.6 us per loop (mean +- std. dev. of 7 runs, 1000 loops each)
%timeit to_gzip_csv_no_timestamp_subprocess(df, 'df.csv')
10.2 ms +- 167 us per loop (mean +- std. dev. of 7 runs, 100 loops each)
Я использую TextIOWrapper()
для обработки преобразования строк в байты, как Pandas делает , но вы также можете сделать это, если знаете, что не собираетесь сохранять много данных:
with GzipFile('df.csv.gz', 'w', mtime=0) as fd:
fd.write(df.to_csv().encode('utf-8'))
Обратите внимание, что gzip -lv df.csv.gz
по-прежнему показывает "текущее время", но оно просто извлекает его из mtime inode. дамп с hexdump -C
показывает, что значение сохранено в файле, а при изменении файлов mtime (с touch -mt 0711171533 df.csv.gz
) gzip
отображает другое значение
Также обратите внимание, что исходное «имя файла» также является частью файла gzipped, поэтому вам нужно записать его под тем же именем (или переопределить это), чтобы сделать его детерминированным.