Задать вопрос
@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
  • Вопрос задан
  • 497 просмотров
Подписаться 1 Средний 6 комментариев
Пригласить эксперта
Ответы на вопрос 2
@dim5x
ЗИ, ИБ. Помогли? Поблагодарите. Отметьте ответом.
Используйте loggingс ограничением размера лога параметром maxBytes, чтобы не изобретать велосипед.

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

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

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

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

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

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