ฉันจะลบออกจากไฟล์ที่อ่านอย่างต่อเนื่องใน 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' ดูเหมือนว่า

ไอบีคอนสแกน ...

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 อย่างน้อย (เช่นเกือบทุกอย่างยกเว้น windows) ตราบใดที่กระบวนการใด ๆ มีตัวจัดการไฟล์แบบเปิด - โดยพื้นฐานแล้วไฟล์นั้นยังคงมีอยู่บนดิสก์ (จนกระทั่ง) ตัวจัดการไฟล์ที่เปิดอยู่ทั้งหมดจะถูกปิด

ดังนั้น หากคุณมีสองกระบวนการ หนึ่งการเขียน และอีกการอ่านและตัดแต่ง - กระบวนการเขียนจะต้องรับรู้ว่าไฟล์ถูกตัดทอน (หรือถูกลบ) และเปิดไฟล์ปลายทางอีกครั้งทุกครั้ง

นั่นเป็นวิธีที่น่าเกลียดอย่างน่าขันในการดำเนินการ โดยต้องมีการสื่อสารระหว่างผู้ผลิตและผู้บริโภค และโดยพื้นฐานแล้วไม่จำเป็นเลย

เงินอัจฉริยะจะใช้บางอย่างเช่น logrotate ซึ่งมีกลไกในตัวเพื่อรันคำสั่ง 'HUP' หรือ 'restart' เพื่อแจ้งให้ผู้ผลิตทราบว่าไฟล์ถูกตัดทอน

หากคุณต้องการข้อมูลแบบ Round-robin จริงๆ ทำไมไม่ใช้ sqlite กับสคีมาที่ 'ล้อมรอบ' เมื่อคุณถึงจำนวนบรรทัดสูงสุดที่คุณต้องการใช้

ตัวอย่างนี้แสดงตารางที่จะลบระเบียนที่เก่าที่สุดออก และแทรกระเบียนใหม่เมื่อคุณมีถึงจำนวนสูงสุด 20 ระเบียน ขึ้นอยู่กับปริมาณข้อมูลที่ปั่นป่วน นี่อาจเป็นความหรูหราที่คุณไม่สามารถจ่ายได้ แต่ถ้าคุณเพียงต้องการการวัดโหลด CPU 1,000 ครั้งล่าสุดก่อนที่ระบบจะพัง.. มันจะทำงานได้ดี ในความเป็นจริง มันสามารถทำอะไรบางอย่างที่สวยงามกว่านี้ได้ เช่น สร้างค่าเฉลี่ยที่ทำงานอยู่ ฯลฯ ผ่านทริกเกอร์โดยใช้ 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