2017-02-23 117 views
0

У меня есть скрипт, который постоянно обновляет кадр данных и сохраняет его на диск (перезаписывая старый CSV-файл). Я узнал, что если прервать программу прямо при вызове сохранения, df.to_csv("df.csv"), все данные будут загружены, а df.csv пуст, содержащий только индекс столбца.Pandas to_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 
+0

Возможно, вы могли бы попробовать добавить результаты к старым, например: 'd.to_csv (" out.csv ", index = False, mode = 'a')'. Это предотвращает их перезапись. –

+0

Затем данные будут дублированы ... И что произойдет, если я прерву его прямо при вызове сохранения? Возможно, нет потерь, но я думаю, что будут проблемы ... – user1506145

ответ

1

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

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 

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

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

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

1

Лучшее, что вы можете сделать, это реализовать обработчик сигнала (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)