2009-07-04 4 views
13

stdinstdoutにいくつかの特別な機能を追加するために、組み込みのfileクラスをPythonでサブクラス化しようとしています。ここで私がこれまで持っているコードは次のとおりです。Pythonでどのようにファイルタイプをサブクラス化しますか?

class TeeWithTimestamp(file): 
    """ 
    Class used to tee the output of a stream (such as stdout or stderr) into 
    another stream, and to add a timestamp to each message printed. 
    """ 

    def __init__(self, file1, file2): 
     """Initializes the TeeWithTimestamp""" 
     self.file1 = file1 
     self.file2 = file2 
     self.at_start_of_line = True 

    def write(self, text): 
     """Writes text to both files, prefixed with a timestamp""" 

     if len(text): 
      # Add timestamp if at the start of a line; also add [STDERR] 
      # for stderr 
      if self.at_start_of_line: 
       now = datetime.datetime.now() 
       prefix = now.strftime('[%H:%M:%S] ') 
       if self.file1 == sys.__stderr__: 
        prefix += '[STDERR] ' 
       text = prefix + text 

      self.file1.write(text) 
      self.file2.write(text) 

      self.at_start_of_line = (text[-1] == '\n') 

目的は、各メッセージの先頭にタイムスタンプを追加するために、ログファイルにすべてのログを記録することです。

# log_file has already been opened 
sys.stdout = TeeWithTimestamp(sys.stdout, log_file) 

私はprint 'foo'をしようとするとその後、私はValueError: I/O operation on closed fileを得る:しかし、私はに実行する問題は、私はこれを行う場合ということです。私は__init__()の中に意味のある方法でfile.__init__()を呼び出すことはできません。私は新しいファイルを開きたくないので、読み取り専用の属性なのでself.closed = Falseを割り当てることはできません。

私はprint 'foo'を行うことができるようにこれを変更することができますし、標準のfile属性とメソッドのすべてをサポートするにはどうすればよいですか?後者は、内部で実際の呼び出しを - file.__init__を呼び出す

答えて

12

は、(例えば、「を/ dev/null」上)が、writeのご未遂オーバーライドはprint文の目的で、「撮る」しないので、本当の使用は非常に可能ですfile.writeと表示された場合、sys.stdoutfileの実際のインスタンスです(継承することにより、それを作成しています)。

printは本当にobject代わりのfileからクラスを継承がうまくいく作り、write以外の任意の他の方法を必要としません。

他のファイル方法が必要な場合は(つまり、printではありません)、自分で実装することをおすすめします。

+0

どの機能が必要なのかよく分かりませんが、一般的に使用されている機能を実装したいと思っています。私はちょうど弾を噛んで、必要なものを実装し、ファイルの代わりにオブジェクトから派生させるだろうと思う。 –

+0

書き込み以外のどのメソッドもsys.stdoutでよく使用されますか?たぶん、書き込みライン、クローズ、フラッシュ - かなり簡単です(とにかく自分でそれらを実装する必要があります - どのようにファイルタイプを知っていても、両方のファイルを閉じたり、フラッシュすることができますか? - ) –

+0

私が本当に必要とするのは、書き込み、書き込み線、クローズ、フラッシュだけです。 sys.stdoutやsys.stderrでは実際に呼び出されるべきではありません。 –

2

あなたにもsuperの使用を避けることができます。

class SuperFile(file): 

    def __init__(self, *args, **kwargs): 
     file.__init__(self, *args, **kwargs) 

あなたはそれを書くことができるようになります。

+0

申し訳ありませんが、私はバグがあった、これはうまく動作します。 –