Панды переписывают to_csv, предотвращают потерю данных

У меня есть скрипт, который постоянно обновляет фрейм данных и сохраняет его на диск (перезаписывая старый csv-файл). Я обнаружил, что если прервать программу прямо при сохранении вызова, df.to_csv("df.csv")все данные будут потеряны, а df.csv пусто, только содержит столбец-индекс.

Я могу, возможно, сделать обходной путь, временно сохранив данные в df.temp.csv, а затем заменить df.csv, Но есть ли питон, короткий способ сделать сохранение "Atomary" и предотвратить потерю данных? Это трассировка стека, которую я получаю, прерывая прямо при сохранении вызова.

Traceback (most recent call last):
  File "/opt/homebrew-cask/Caskroom/pycharm/2016.1.3/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1531, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
  File "/opt/homebrew-cask/Caskroom/pycharm/2016.1.3/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 938, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/Users/user/test.py", line 49, in <module>
    d.to_csv("out.csv", index=False)
  File "/usr/local/lib/python2.7/site-packages/pandas/core/frame.py", line 1344, in to_csv
    formatter.save()
  File "/usr/local/lib/python2.7/site-packages/pandas/formats/format.py", line 1551, in save
    self._save()
  File "/usr/local/lib/python2.7/site-packages/pandas/formats/format.py", line 1652, in _save
    self._save_chunk(start_i, end_i)
  File "/usr/local/lib/python2.7/site-packages/pandas/formats/format.py", line 1666, in _save_chunk
    quoting=self.quoting)
  File "/usr/local/lib/python2.7/site-packages/pandas/core/internals.py", line 1443, in to_native_types
    return formatter.get_result_as_array()
  File "/usr/local/lib/python2.7/site-packages/pandas/formats/format.py", line 2171, in get_result_as_array
    formatted_values = format_values_with(float_format)
  File "/usr/local/lib/python2.7/site-packages/pandas/formats/format.py", line 2157, in format_values_with
    for val in values.ravel()[imask]])
  File "/usr/local/lib/python2.7/site-packages/pandas/formats/format.py", line 2108, in base_formatter
    return str(v) if notnull(v) else self.na_rep
  File "/usr/local/lib/python2.7/site-packages/pandas/core/common.py", line 250, in notnull
    res = isnull(obj)
  File "/usr/local/lib/python2.7/site-packages/pandas/core/common.py", line 73, in isnull
    def isnull(obj):
  File "_pydevd_bundle/pydevd_cython.pyx", line 937, in _pydevd_bundle.pydevd_cython.ThreadTracer.__call__ (_pydevd_bundle/pydevd_cython.c:15522)
  File "/opt/homebrew-cask/Caskroom/pycharm/2016.1.3/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_is_thread_alive.py", line 14, in is_thread_alive
    def is_thread_alive(t):
KeyboardInterrupt

2 ответа

Решение

Вы можете создать менеджер контекста, чтобы обрабатывать ваши атомарные перезаписи:

import os
import contextlib

@contextlib.contextmanager
def atomic_overwrite(filename):
    temp = filename + '~'
    with open(temp, "w") as f:
        yield f
    os.rename(temp, filename) # this will only happen if no exception was raised

to_csv метод на панд DataFrame примет файловый объект вместо пути, поэтому вы можете использовать:

with atomic_overwrite("df.csv") as f:
    df.to_csv(f)

Временное имя файла, которое я выбрал, является запрошенным именем файла с тильдой в конце. Конечно, вы можете изменить код, чтобы использовать что-то еще, если хотите. Я также не совсем уверен, в каком режиме файл должен быть открыт, вам может понадобиться "wb" вместо просто "w",

Лучшее, что вы можете сделать, это реализовать обработчик сигнала (signal модуль), который ожидает завершения программы до завершения последней операции записи.

Нечто подобное (псевдокод):

import signal
import sys
import time
import pandas as pd

lock = threading.Lock()

def handler(signum, frame):
    # ensure that latest data is written
    sys.exit(1)

signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGINT, handler)

while True:
    # might exit any time.
    pd.to_csv(...)
    time.sleep(1)
Другие вопросы по тегам