Soru Sık güncellenen bir dosyadan okuma


Şu anda bir Linux sisteminde python'da bir program yazıyorum. Amaç, bir günlük dosyasını okumak ve belirli bir dizgeyi bulmak için bir bash komutunu yürütmektir. Günlük dosyası sürekli olarak başka bir program tarafından yazılmaktadır. Sorum şu:

Dosyayı open () yöntemini kullanarak açarsam, Python dosyam nesnesinin gerçek dosya diğer program tarafından yazıldığı gibi güncellenir mi yoksa dosyayı zamanlanmış aralıklarla yeniden açmak zorunda mıyım?

Teşekkürler

Jim

GÜNCELLEŞTİRME: Şimdiye kadar cevaplar için teşekkürler. Belki de dosyanın bir Java EE uygulaması tarafından yazıldığı bilgisini vermeliydim, böylece veri yazıldığında üzerinde hiçbir kontrolüm yok. Şu anda her 10 saniyede bir dosyayı yeniden açan ve en son okunan dosyadaki bayt konumundan okumaya çalışan bir programım var. Şimdilik sadece döndüğü dizeyi basıyor. Dosyanın yeniden açılmasının gerekmediğini, ancak okuma komutunun bir şekilde Java uygulaması tarafından dosyaya yazılan verilere erişebileceğini umuyordum.

#!/usr/bin/python
import time

fileBytePos = 0
while True:
    inFile = open('./server.log','r')
    inFile.seek(fileBytePos)
    data = inFile.read()
    print data
    fileBytePos = inFile.tell()
    print fileBytePos
    inFile.close()
    time.sleep(10)

Pyinotify ve jeneratörler hakkında ipuçları için teşekkürler. Daha güzel bir çözüm için bunlara bir bakacağım.


35
2018-03-24 13:24


Menşei




Cevaplar:


David Beazley'e bakmanızı tavsiye ederim Python için Jeneratör Püf Noktaları, özellikle Bölüm 5: Sonsuz Veri İşleme. Bir Python eşdeğerini ele alacak tail -f logfile gerçek zamanlı komut.

# follow.py
#
# Follow a file like tail -f.

import time
def follow(thefile):
    thefile.seek(0,2)
    while True:
        line = thefile.readline()
        if not line:
            time.sleep(0.1)
            continue
        yield line

if __name__ == '__main__':
    logfile = open("run/foo/access-log","r")
    loglines = follow(logfile)
    for line in loglines:
        print line,

61
2018-03-24 13:42



Bu cevap kabul edilmeli - Quinma
Cevabın, OP'nin kodu açısından bir kod örneği içermesi durumunda tekrardan verecektim. - Chiel ten Brinke
@ Chiel92: David Beazley sitesinden kod örneği eklendi - Jeff Bauer
Bu cevap yanlıştır, yazar iki ayrı satırda bir satır yazarsa, iki kez okunacak. Ama gerçekten sadece tek bir satır geri dönmek istiyorsun. - Fabian
İşe yaramaz. Belki Python 3'te farklı mıdır? - Jason


"Etkileşimli bir oturum 1000 kelimeye bedeldir"

>>> f1 = open("bla.txt", "wt")
>>> f2 = open("bla.txt", "rt")
>>> f1.write("bleh")
>>> f2.read()
''
>>> f1.flush()
>>> f2.read()
'bleh'
>>> f1.write("blargh")
>>> f1.flush()
>>> f2.read()
'blargh'

Başka bir deyişle - evet, tek bir "açık" yapacak.


13
2018-03-24 14:11



Bu bilmek ilginç! - Adam Pointer


İşte biraz değiştirilmiş bir versiyonu Jeff Bauer Dosya kesilmesine karşı dayanıklı olan cevap. Dosyanız tarafından işleniyorsa çok kullanışlıdır logrotate.

import os
import time

def follow(name):
    current = open(name, "r")
    curino = os.fstat(current.fileno()).st_ino
    while True:
        while True:
            line = current.readline()
            if not line:
                break
            yield line

        try:
            if os.stat(name).st_ino != curino:
                new = open(name, "r")
                current.close()
                current = new
                curino = os.fstat(current.fileno()).st_ino
                continue
        except IOError:
            pass
        time.sleep(1)


if __name__ == '__main__':
    fname = "test.log"
    for l in follow(fname):
        print "LINE: {}".format(l)

4
2017-08-29 19:33



Görmeyi korkutuyor while True: while True: - Pedro Lobito


Bir Linux sistemini hedeflediğiniz için kullanabilirsiniz pyinotify dosya değiştiğinde sizi bilgilendirmek için.

Ayrıca var bu hile, sizin için iyi olabilir. Kullanır file.seek ne yapacağını tail -f yapar.


3
2018-03-24 13:36





Burada uzman değilim ama dosyayı pasif olarak izlemek için bir çeşit gözlemci deseni kullanmanız ve bir değişiklik olduğunda dosyayı yeniden açan bir olayı tetiklemeniz gerektiğini düşünüyorum. Bunu gerçekte nasıl uygulayacağımıza dair hiçbir fikrim yok.

Ben önermek gibi open () dosyayı gerçek zamanlı olarak açacağını sanmıyorum.


1
2018-03-24 13:32





Bir süre döngüsünde çalışan dosyayı okuyan kodunuz varsa:

f = open('/tmp/workfile', 'r')
while(1):
    line = f.readline()
    if line.find("ONE") != -1:
        print "Got it"

ve aynı dosyaya (ek modda) başka bir programdan yazıyorsunuz. Dosyaya "ONE" eklendiğinde, baskıyı alacaksınız. Almak istediğiniz eylemi yapabilirsiniz. Kısaca, dosyayı düzenli aralıklarla yeniden açmanız gerekmez.

>>> f = open('/tmp/workfile', 'a')
>>> f.write("One\n")
>>> f.close()
>>> f = open('/tmp/workfile', 'a')
>>> f.write("ONE\n")
>>> f.close()

1
2018-03-24 14:06



Bu cevap da yanlıştır, yazma 'ON' ve 'E \ n' olarak bölünebilir, bu da iki eşleşmeyle sonuçlanır. - Fabian