Как удалить из постоянно читаемого файла в Python?

Я создал скрипт Python для чтения из постоянно обновляемого файла («out.txt») и записи в другой файл («received.txt») каждые 10 секунд. Теперь мне нужно выяснить, как удалить уже прочитанные данные из файла «out.txt». Вот код, который у меня есть до сих пор.

#!/usr/bin/python

import sys
import time

num_lines = sum(1 for line in open('out.txt')) #find the last line
print num_lines

sys.stdout = open('received.txt', 'w')  #write to the received.txt file
print

f = open('out.txt', 'r') #open ‘out.txt’ with read permissions
f.readline(num_lines)    #read the last line of ’out.txt’
while True:              #start loop to print remaining lines in out.txt
   for line in f:
      print line
   time.sleep(10)        #sleep for 10 seconds

Я удаляю данные в «out.txt» после цикла или внутри цикла? Должен ли я использовать f.write для этого? Для этого я использую Raspbian на Raspberry Pi. Данные для «out.txt» выглядят так:

iBeacon сканирование...

3F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 1 1 -71 -66

3F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 1 1 -71 -66

3F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 1 1 -71 -66

... постоянно обновляется.

Любой совет будет чрезвычайно полезен. Спасибо!


person Thomas Hall    schedule 31.07.2014    source источник
comment
Проверьте stackoverflow.com/q/10349781/1860929.   -  person Anshul Goyal    schedule 31.07.2014
comment
Можно ли использовать именованный канал для out.txt?   -  person Raul Andres    schedule 31.07.2014
comment
Попробуйте вместо этого использовать именованный канал, использование простого текстового файла звучит очень неудобно.   -  person roippi    schedule 31.07.2014
comment
Неизвестная правда в том, что вы никогда не удаляете какие-то строки из файла, вы всегда перезаписываете весь файл (все приложения делают это за кулисами). Почему бы вам не использовать канал вместо файла?   -  person Paulo Scardine    schedule 31.07.2014
comment
Если вы откроете файл в режиме записи/чтения (w+), он обрежет (удалит все содержимое) файла.   -  person okoboko    schedule 31.07.2014
comment
Будьте осторожны с именованным каналом. Если он открыт в режиме блокировки (по умолчанию), процесс-производитель может заблокироваться, ожидая, пока потребитель откроет/прочитает из канала. Это может стать проблемой для производителя, если он этого не ожидает.   -  person mhawke    schedule 31.07.2014


Ответы (1)


С этим подходом есть проблема - по крайней мере, на posix (т. Е. Почти во всем, кроме окон), если у любого процесса есть дескриптор открытого файла - этот файл все еще в основном существует на диске (ПОКА) все открытые дескрипторы файлов закрыты.

Итак, если у вас есть два процесса, один записывающий, а другой читающий и обрезающий, процесс записи должен будет знать, что файл был усечен (или удален), и каждый раз заново открывать целевой файл.

Это смехотворно уродливый способ сделать это - он требует общения между производителем и потребителем и в принципе не нужен.

Умные деньги просто использовали бы что-то вроде logrotate, где у него есть встроенные механизмы для запуска команды «HUP» или «перезагрузка», чтобы уведомить производителя о том, что файл был усечен.

Если вам действительно нужны циклические данные, почему бы не использовать sqlite со схемой, которая «оборачивает» по мере того, как вы достигаете максимального количества строк, которые хотите использовать?

В этом примере представлена ​​таблица, которая удалит самую старую запись и вставит новую, когда будет достигнуто не более 20 записей. В зависимости от объема передаваемых данных это может быть роскошью, которую вы не можете себе позволить. Но если вам просто нужны последние 1000 измерений загрузки процессора перед сбоем системы... это будет работать нормально. На самом деле, он мог бы делать гораздо более элегантные вещи, такие как генерация средних значений и т. д., с помощью триггеров с использованием SQL, а не написания кода.

CREATE TABLE activity_t (
  id        INTEGER PRIMARY KEY AUTOINCREMENT,
  seq       INTEGER UNIQUE,
  ts        TEXT DEFAULT CURRENT_TIMESTAMP,
  bin       TEXT NOT NULL,
  path      TEXT NOT NULL);

-- sqlite_sequence table:
INSERT INTO activity_t ( seq, bin, path ) VALUES ( -1, 'init', 'init' );
DELETE FROM activity_t WHERE seq = -1;

-- view
CREATE VIEW activity AS SELECT id, seq, ts, bin, path FROM activity_t;

-- trigger to snipe inserts and handle the 'wrap around' limitation
CREATE TRIGGER activity_trg
  INSTEAD OF INSERT ON activity
  FOR EACH ROW
  BEGIN
    INSERT OR REPLACE INTO activity_t ( seq, bin, path ) VALUES (
      ( SELECT seq + 1 FROM sqlite_sequence WHERE name = 'activity_t' ) %
    20,
    NEW.bin,
    NEW.path);
  END;
person synthesizerpatel    schedule 31.07.2014