pythonはtail-f機能を実現します。

7696 ワード

tail fはtail-fと類似しています。ファイルが成長しない時はファイルにアクセスしません。
tail-f:ファイルの内容だけを追跡します。
tail-F:ファイルの内容とファイル名は全部追跡します。
この文章は最初にrebootの群の中で面接に行く人がいます。筆記試験問題はこの問題があります。どうすればいいか分かりません。どんな考えですか?
私は考えてみました。簡単に私の考えを話してください。もちろん、使いやすいpyinotifyモジュールはファイルの変化を監督しています。でも、もっと紹介したいのは解決の考え方です。やはり面接官として問題を解決する考えを見たいです。そして、この問題の難点は監視ファイルの増量ではなく、一番後ろの10行をどのように印刷するかです。
この文章を読む前に、pythonの基礎、文書を処理して、モジュールを常用することに対して簡単な理解があって、次のいくつかの名詞は何ですか?

open('a.txt')
file.seek
file.tell
time.sleep()
下の考えは私個人の知識に限られています。間違いや考えがなくてはいけません。もっといい方法で提出してください。いつでもコードを最適化します。問題の感じはそんなに多くないです。
どのようにpythonで実現しますか?
実は考え方も難しくないです。
  • このファイルを開けて、最後の
  • にポインタを移動します。
  • は一秒ごとにreadlineを試してみます。内容があればプリントアウトします。内容がないならsleep
  • です。
  • とは大体このような意味です。
    ファイルを傍受する
    考えは以下の通りです
  • オープンファイル
  • はseekファイルの針を使って、おじいさんにファイルの一番後ろの
  • にジャンプします。
  • while Trueを循環します。
  • 継続的なreadlineは、コンテンツを読むことができますが、印刷することができます。
    コードが出そうとします
    
    with open('test.txt') as f:
      f.seek(0,2)
      while True:
        last_pos = f.tell()
        line = f.readline()
        if line:
          print line
    コード説明
  • seekの第二のパラメータ2とは、文書の末尾からseekを開始し、より標準的な書き方はosモジュールの下のSEEK_を使用するという意味です。END、可読性がより良い
  • は簡単なロジックを書いただけで、コードが簡単で乱暴です。このテーマが10点なら、せいぜい4点を取ります。これ以上はできません。
    最適化ポイント
  • printは欠陥があります。毎回新しい一行です。sys.stdout.writeに換えてもっと調和が取れています。
  • ファイル名を参考にしてください。
  • を書き殺すことはできません。
  • 直接印刷はデフォルトの行為として使えます。具体的には何をすればいいですか?関数として処理できます。このように、私達は新しい行を他の処理にすることができます。例えば、ブラウザに展示されている
  • にフォールトトレランス処理を加えると、ファイルが存在しないとエラーが発生します。
  • while Trueはずっとファイルで、比較的に性能を消耗して、一回読むごとに、一秒間隔でスペクトル
  • を比較します。
  • 呼び出しtime.sleep(1)
  • クラスでコードを組織する
  • 実例コードは以下の通りです
    
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import sys
    import time
    class Tail():
      def __init__(self,file_name,callback=sys.stdout.write):
        self.file_name = file_name
        self.callback = callback
      def follow(self):
        try:
          with open(self.file_name) as f:
            f.seek(0,2)
            while True:
              line = f.readline()
              if line:
                self.callback(line)
              time.sleep(1)
        except Exception,e:
          print '      ,           ,       '
          print e
    使用方法:
    
    #      sys.stdout.write     
    py_tail = Tail('test.txt')
    py_tail.follow()
    #         
    def test_tail(line):
      print 'xx'+line+'xx'
    py_tail1 = Tail('test.txt', test_tail)
    py_tail1.follow()
    えっと、tail-fはデフォルトではまた最後の10行をプリントします。これこそこのテーマの難しいところです。ご存知のように、pythonでファイルポインタを読んで、固定位置に移動するしかないです。どの行かは判断できません。
    最後の10行をデフォルトで印刷します。
    今このコードは大体6点を取ることができます。もう一つの機能はしていません。つまり、最後のn行を印刷します。標準は10行です。今はこの機能を加えて、関数を追加すればいいです。
    ファイルが小さい時
    私達は知っています。readlinesはすべての内容を取得できます。そして、支店、コードが出てきます。リストの最後の10行を取得するのは簡単です。大丈夫です。
    
    #     ,      ,       
    last_lines = f.readlines()[-10:]
    for line in last_lines:
      self.callback(line)
    この時コードはこうなりました。
    
    import sys
    import time
    class Tail():
      def __init__(self,file_name,callback=sys.stdout.write):
        self.file_name = file_name
        self.callback = callback
      def follow(self,n=10):
        try:
          with open(self.file_name) as f:
            self._file = f
            self.showLastLine(n)
            self._file.seek(0,2)
            while True:
              line = self._file.readline()
              if line:
                self.callback(line)
        except Exception,e:
          print '      ,           ,       '
          print e
      def showLastLine(self, n):
        last_lines = self._file.readlines()[-10:]
        for line in last_lines:
          self.callback(line)
    さらに、大きな日誌はどうすればいいですか?
    この時のコードは7点がありますが、ファイルがとても大きいなら、特にログファイルはいくつかのGが簡単です。最後の数行しか必要ないので、全部読んでメモリがたまりません。だから、私達は引き続きショーラントリンク関数を最適化したいです。これはこの問題の難しい点だと思います。
    大体の考えは次の通りです。
    まず、ログの一行は大体100文字だと思います。注意してください。大体のところを見積もってもいいです。多くなっても大丈夫です。初期値が必要です。後で修正します。
    10行読みたいので、最初からseekから末尾1000までの位置seek(-1000,2)まで、最後の1000文字を読んで判断します。
    この1000文字の長さがファイルの長さより大きい場合は、レベル1の場合はそのままreadし、split
    1000文字の中の改行が10より大きいと、1000文字のうち、10行より大きいと説明されても、処理が簡単です。考え方は同じレベルです。直接splitは後10個を取ります。
    問題は10以下ならどうするかです。
    例えば、1000個の中で、4つの改行だけがあります。1行は大体1000/4=250文字です。私達はまだ6行足りないので、250*5=1500を読みます。全部で2500の大体の比較スペクトルがあります。そして、2500の文字に対して同じ論理判断を行います。
    論理がはっきりしたら、コードが出てきます。
    注釈をつけたバージョン
    
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import sys
    import time
    class Tail():
      def __init__(self,file_name,callback=sys.stdout.write):
        self.file_name = file_name
        self.callback = callback
      def follow(self,n=10):
        try:
          #     
          with open(self.file_name) as f:
            self._file = f
            self._file.seek(0,2)
            #          
            self.file_length = self._file.tell()
            #     10 
            self.showLastLine(n)
            #           
            while True:
              line = self._file.readline()
              if line:
                self.callback(line)
              time.sleep(1)
        except Exception,e:
          print '      ,           ,       '
          print e
      def showLastLine(self, n):
        #     100        1  1000  
        len_line = 100
        # n   10,   follow      
        read_len = len_line*n
        #  last_lines          
        while True:
          #       1000   ,           
          #     ,  break
          if read_len>self.file_length:
            self._file.seek(0)
            last_lines = self._file.read().split('
    ')[-n:] break # 1000 1000 self._file.seek(-read_len, 2) last_words = self._file.read(read_len) # count count = last_words.count('
    ') if count>=n: # 10 , last_lines = last_words.split('
    ')[-n:] break # 10 else: # break # # , 100 if count==0: len_perline = read_len # 4 , 250 else: len_perline = read_len/count # 2500, read_len = len_perline * n for line in last_lines: self.callback(line+'
    ') if __name__ == '__main__': py_tail = Tail('test.txt') py_tail.follow(20)
    効果は以下の通りです。最後の何行かを印刷できます。試してみてもいいです。ログの行に1つしかないか、それとも1行に300文字があるかに関わらず、最後の10行を印刷することができます。
    このようにすることができます。普通の面接官は直接にあなたに解決されました。このコードは大体8分です。もっと進めたいなら、もっと最適化できるところがあります。コードはgithubに置いてあります。興味がある人は研究に持って行ってもいいです。
    最適化待ち:拡張としてみんなに残してください。
  • もしあなたがtail-fの過程でログがバックアップされてクリアされたり切断されたら、どう処理しますか?
  • は実は簡単です。ポインタの位置を維持します。もし次のループでファイルポインタの位置が変わったら、最新のポインタ位置から読めばいいです。
  • 具体的に各エラーのタイプ
  • ここは簡単なtryです。関数を書いてもいいです。ファイルは存在しません。ファイルにはこれらのエラーメッセージがありません。
    性能は小さくて最適化して、たとえば私は初めて1000を読みました。4行しかないです。大体250行の文字が必要です。全部で2500行が必要です。今度は直接2500本を読む必要がないです。1500行を読んで前の1000行とつづればいいです。
    最後にこれを書いたら、基本面接官が直接に
    あなたを殺します
    
    import os
    def tail(file_name):
      os.system('tail -f '+file_name)
    tail('log.log')
    締め括りをつける
    以上述べたのは小编が皆さんに绍介したpythonがtail-f机能を実现するので、皆さんに助けがあることを望んでいます。ここでも私たちのサイトを応援してくれてありがとうございます。
    本文があなたのためになると思ったら、転載を歓迎します。出所を明記してください。ありがとうございます。