Задать вопрос
@dobrymmaniak

Из-за ошибки текстовый файлик занимает всё свободное место на носителе, как это исправить?

Приветствую. В данный момент я работаю над системой регистрации с тактированием от сигнала GPS-PPS (у меня готова статья на Хабр на эту тему, но мне пока не разрешают ее публиковать...). Для того, чтобы восстановить записанную информацию, я использую логи - обычные текстовые файлики, типа такого:
spoiler
µb 1?h$GPRMC,000031.00,A,5148.65153,N,10304.47868,E,0.073,,060525,,,A*7D
$GPVTG,,T,,M,0.073,N,0.135,K,A*20
$GPGGA,000031.00,5148.65153,N,10304.47868,E,1,09,0.85,665.4,M,-37.2,M,,*7F
0.000000,1746489631.281349,1746489631281
1746489631.281349,1746489631.299559,18
1746489631.299559,1746489631.319586,20
1746489631.319586,1746489631.339577,20
1746489631.339577,1746489631.359557,20
1746489631.359557,1746489631.379577,20
1746489631.379577,1746489631.400497,21
1746489631.400497,1746489631.422767,22
1746489631.422767,1746489631.439803,17
1746489631.439803,1746489631.459574,20
1746489631.459574,1746489631.479847,20
1746489631.479847,1746489631.499534,20
1746489631.499534,1746489631.519562,20
1746489631.519562,1746489631.539536,20
1746489631.539536,1746489631.559530,20
1746489631.559530,1746489631.579534,20
1746489631.579534,1746489631.599536,20
1746489631.599536,1746489631.619520,20
1746489631.619520,1746489631.639515,20
$GPGSA,A,3,13,14,01,02,17,07,30,27,22,,,,1.57,0.85,1.32*0F
$GPGSV,4,1,16,01,20,154,30,02,43,128,25,07,63,199,18,08,64,072,08*7F
$GPGSV,4,2,16,10,04,057,27,13,21,316,38,14,31,280,37,15,03,344,*79
$GPGSV,4,3,16,16,00,094,,17,08,226,34,22,14,276,31,23,06,019,18*7E
$GPGSV,4,4,16,27,25,057,26,30,58,279,26,40,16,235,36,50,27,151,*7B
$GPGLL,5148.65153,N,10304.47868,E,000031.00,A,A*64
$GPRMC,000032.00,A,5148.65181,N,10304.47921,E,0.119,,060525,,,A*70

Т.е. вначале я считываю сообщения с COM-порта, этим я отмечаю секунду до начала измерений, потом записываю временные метки, которые позволяют мне восстановить доли секунды после начала записи, затем снова читаю COM-порт, потому что через сообщение RMC мне проще восстановить дату.
Каждый час создается новый файлик с помощью примерно следующего кода (всё ненужное выбросил):
spoiler
import os
import time
import datetime
import RPi.GPIO as GPIO
import sh
import sys

def get_nmea_datetime(port, msg, cond, res, lname):
    data = ''
    msg_time = ''
    # GPS only
    marker = '$GP'+msg
    while msg_time=='':
        d = port.read(1)
        if d!='\n':
            data = data + d
        else:
            if os.path.getsize(lname)<10000:
                log = open(lname, 'a')
                log.write(data)
                log.close()
            if marker in data:
                sdata = data.split(",")
                if sdata[cond[0]]==cond[1]:
                    continue
                else:
                    msg_time = sdata[res[0]] + '0000'
                    if len(res)>1:
                        msg_time = msg_time + sdata[res[1]]
                    break
            data = ''
    return msg_time

def proper_pps_counter(channel):
    global prev_t, success, gga_raw
    gga_raw = get_nmea_datetime(ser, 'GGA', (6,'0'), (1,), lname)
    pres_t = time.time()
    delta_t = int(round(pres_t-prev_t,3)*1000)
    log = open(lname, 'a')
    text = '{:.6f}'.format(prev_t) + ',' + '{:.6f}'.format(pres_t) + ',' + str(delta_t) + '\n'
    log.write(text)
    log.close()
    if delta_t==20:
        success = success+1
    else:
        success = 0 # reset in case of sequence violation
    prev_t = pres_t

gpio1 = 24

try:
    while True:
        prev_t = 0; success = 0
        gga_raw = 0; rmc_raw = 0
        log_dir = '/media/usb4/LOG/'
        lname = '/media/usb4/log.txt'
        GPIO.add_event_detect(gpio1, GPIO.BOTH, callback=proper_pps_counter)
        while success<10:
           time.sleep(0.001)
        GPIO.remove_event_detect(gpio1)
        rmc_raw = get_nmea_datetime(ser, 'RMC', (2,'V'), (1,9), lname)
        # Further we get datetime-type value rmc
        lname1 = log_former(log_dir, rmc)
        # Copy log information to new file in desired dir
        sh.cp(lname, lname1)
        sh.rm(lname)
        # Code continues...
except KeyboardInterrupt:
    sys.exit()

Последовательность примерная такая: создается лог-файл в корне, в него записывается некоторая информация, а после того, как становится известно точное время начала записи - я переношу информацию в новую директорию, а файл в корне удаляю.

Большую часть времени всё отлично работает, но иногда корневой лог разрастается с 2 КБ до нескольких гигабайт! и занимает весь свободный объем на носителе. Происходит это раз в несколько дней, и один раз мне даже удалось прочитать подобный файл - насколько я понимаю, все последующие навигационные сообщения типа $GPRMC, $GPGGA и т.п. система записывает без символа переноса строки в одну строку, т.е. получается длинная строка на квадриллион символов. Это уже странно, поскольку в каждую строку под запись я включаю символ "\n" в функции get_nmea_datetime.

Второй момент, я вроде поставил простое условие - если размер файла больше 10 КБ, то писать в него не надо, но это не помогает. Скажите, в чем может быть проблема? Что нужно сделать, чтобы не переполнялся носитель? Выглядит это примерно так:
6863a46eb0de7635808947.png
  • Вопрос задан
  • 149 просмотров
Подписаться 1 Средний 5 комментариев
Пригласить эксперта
Ответы на вопрос 2
@dim5x
ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
Используйте loggingс ограничением размера лога параметром maxBytes, чтобы не изобретать велосипед.

я включаю символ "\n" в функции get_nmea_datetime

Где?
Вы накапливаете данные в data, при появлении перевода строки записываете их. Но не добавляете '\n'.

Ну и, вероятно, могут не выполняться условия выше data=''и оно может не обнуляться.

З.Ы. ну и в целом: работайте с файлами через контекстный менеджер with, добавьте логирование и обработку исключений (для себя прежде всего), аннотации и комментарии к коду (для других), тем более, если он будет опубликован.
Ответ написан
@lantonov
выполняй сжатие файла архиватором как только файл достиг определённого размера так будет меньше места заниматься
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы