2011-03-24 15 views
29

मैं वर्तमान में लिनक्स सिस्टम पर पायथन में एक प्रोग्राम लिख रहा हूं। उद्देश्य एक लॉग फ़ाइल को पढ़ने और एक विशेष स्ट्रिंग खोजने पर एक बैश कमांड निष्पादित करना है। लॉग फ़ाइल को लगातार दूसरे प्रोग्राम द्वारा लिखा जा रहा है। मेरा सवाल है:अक्सर अद्यतन फ़ाइल से पढ़ना

यदि मैं खुली() विधि का उपयोग कर फ़ाइल खोलता हूं तो मेरी पायथन फ़ाइल ऑब्जेक्ट को अपडेट किया जाएगा क्योंकि वास्तविक फ़ाइल को अन्य प्रोग्राम द्वारा लिखा जाता है या क्या मुझे समय अंतराल पर फ़ाइल को फिर से खोलना होगा?

धन्यवाद

जिम

अद्यतन: जवाब अब तक के लिए धन्यवाद। मुझे शायद यह उल्लेख करना चाहिए था कि फ़ाइल जावा ईई ऐप द्वारा लिखी जा रही है, इसलिए जब डेटा को लिखा जाता है तो मेरा कोई नियंत्रण नहीं होता है। मुझे वर्तमान में एक प्रोग्राम मिला है जो हर 10 सेकंड में फ़ाइल को फिर से खोलता है और उस फ़ाइल में बाइट स्थिति से पढ़ने की कोशिश करता है जिसे वह पिछली बार पढ़ता है। फिलहाल यह वापस लौटने वाली स्ट्रिंग को प्रिंट करता है। मैं उम्मीद कर रहा था कि फ़ाइल को फिर से खोलने की आवश्यकता नहीं है लेकिन रीड कमांड को किसी भी तरह जावा ऐप द्वारा फ़ाइल में लिखे गए डेटा तक पहुंच होगी।

#!/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) 

पायनोटीफाइफ़ और जेनरेटर पर युक्तियों के लिए धन्यवाद। मैं इन्हें एक अच्छे समाधान के लिए देख रहा हूं।

उत्तर

47

मैं डेविड बीज़ले के Generator Tricks for Python, विशेष रूप से भाग 5: प्रोसेसिंग अनंत डेटा पर देखने की अनुशंसा करता हूं। यह रीयल-टाइम में tail -f logfile कमांड के पाइथन समकक्ष को संभालेगा।

# 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, 
+2

इस उत्तर – Quinma

+0

अगर जवाब ओपी के कोड के मामले में एक कोड उदाहरण निहित मैं वोट दें जाएगा स्वीकार किया जाना चाहिए। –

+0

@ Chiel92: डेविड बीज़ले की साइट –

1

मैं यहां कोई विशेषज्ञ नहीं हूं लेकिन मुझे लगता है कि आपको फ़ाइल को निष्क्रिय रूप से देखने के लिए किसी प्रकार के पर्यवेक्षक पैटर्न का उपयोग करना होगा और फिर एक ईवेंट को आग लगाना होगा जब परिवर्तन होने पर फ़ाइल को फिर से खोल दिया जाए। वास्तव में इसे कैसे कार्यान्वित करने के लिए, मुझे कोई जानकारी नहीं है।

मुझे नहीं लगता कि खुले() आपके द्वारा सुझाए गए रीयलटाइम में फ़ाइल खोलेंगे।

3

चूंकि आप एक लिनक्स सिस्टम को लक्षित कर रहे हैं, इसलिए आप फ़ाइल परिवर्तन करते समय आपको सूचित करने के लिए pyinotify का उपयोग कर सकते हैं।

this चाल भी है, जो आपके लिए ठीक काम कर सकती है। यह tail -f करता है करने के लिए file.seek का उपयोग करता है।

1

आप कोड फ़ाइल थोड़ी देर के पाश में चल रहा है, तो पढ़ने:

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

और आप किसी अन्य कार्यक्रम से (संलग्न मोड में) है कि एक ही फाइल करने के लिए लिख रहे हैं। जैसे ही फ़ाइल में "ONE" संलग्न किया गया है, आपको प्रिंट मिलेगा। आप जो भी कार्रवाई करना चाहते हैं वह ले सकते हैं। संक्षेप में, आपको नियमित अंतराल पर फ़ाइल को फिर से खोलना नहीं है। हाँ, एक भी "खुला" क्या करेंगे -

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

यह उत्तर भी गलत है, लेखन में विभाजित हो सकता है 'चालू' और 'ई \ n' जिसके परिणामस्वरूप दो पंक्तियां होंगी जहां न तो मेल खाता है। – Fabian

12

>>> 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' 

दूसरे शब्दों में "एक इंटरैक्टिव सत्र 1000 शब्दों के बराबर है।"

+0

यह जानना दिलचस्प है! –

2

यहां Jeff Bauer उत्तर का थोड़ा संशोधित संस्करण है जो फ़ाइल छंटनी के लिए प्रतिरोधी है। यदि आपकी फ़ाइल 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) 
संबंधित मुद्दे