class BasicWatcher(object):
    """Base class for watching the output of commands

    Works like the UNIX-command 'tail -f <file>': the last lines of the file are output.
    If the file grows then these lines are output as they arrive"""
    def __init__(self,
                 filename,
                 silent=False,
                 tailLength=1000,
                 sleep=0.1,
                 follow=True):
        """:param filename: name of the logfile to watch
        :param silent: if True no output is sent to stdout
        :param tailLength: number of bytes at the end of the fail that should be output.
        :param follow: if the end of the file is reached wait for further input
        Because data is output on a per-line-basis
        :param sleep: interval to sleep if no line is returned"""

        self.filename = filename
        self.silent = silent
        self.tail = tailLength
        self.sleep = sleep
        self.follow = follow
        self.isTailing = False

        if not path.exists(self.filename):
            print_("Error: Logfile ", self.filename, "does not exist")

        self.reader = LineReader(config().getboolean("SolverOutput",
                                                     "stripSpaces"))

    def getSize(self):
        """:return: the current size (in bytes) of the file"""
        return os.stat(self.filename)[stat.ST_SIZE]

    def start(self):
        """Reads the file and does the processing"""

        currSize = self.getSize()

        fn, ext = path.splitext(self.filename)
        if ext == '.gz':
            fh = gzip.open(self.filename)
        else:
            fh = open(self.filename)

        self.startHandle()

        while self.follow or currSize > self.reader.bytesRead():
            try:
                status = self.reader.read(fh)
                if status:
                    line = self.reader.line
                    if (currSize - self.reader.bytesRead()) <= self.tail:
                        if not self.isTailing:
                            self.isTailing = True
                            self.timeHandle()
                            self.tailingHandle()

                        if not self.silent:
                            print_(line)

                    self.lineHandle(line)
                else:
                    if self.reader.userSaidStop():
                        break
                    sleep(self.sleep)
            except KeyboardInterrupt:
                print_("Watcher: Keyboard interrupt")
                break

        self.stopHandle()

        fh.close()

    def startHandle(self):
        """to be called before the program is started"""
        pass

    def stopHandle(self):
        """called after the program has stopped"""
        pass

    def tailingHandle(self):
        """called when the first line is output"""
        pass

    def lineHandle(self, line):
        """called every time a new line is read"""
        pass
class BasicWatcher(object):
    """Base class for watching the output of commands

    Works like the UNIX-command 'tail -f <file>': the last lines of the file are output.
    If the file grows then these lines are output as they arrive"""

    def __init__(self,filenames,
                 silent=False,
                 tailLength=1000,
                 sleep=0.1,
                 follow=True):
        """:param filename: name of the logfile to watch
        :param silent: if True no output is sent to stdout
        :param tailLength: number of bytes at the end of the fail that should be output.
        :param follow: if the end of the file is reached wait for further input
        Because data is output on a per-line-basis
        :param sleep: interval to sleep if no line is returned"""

        if type(filenames) is list:
            meshTimes=[]
            createMesh="Create mesh for time = "
            for fName in filenames:
                meshTime=None
                with open(fName) as f:
                    for l in f.readlines()[:100]:
                        if l.find(createMesh)==0:
                            meshTime=float(l[len(createMesh):])
                            break
                meshTimes.append((fName,meshTime))
            meshTimes.sort(key=lambda x:1e50 if x[1] is None else x[1])
            filenames=[m[0] for m in meshTimes]
            self.filename=filenames[0]
            self.nextFiles=filenames[1:]
            self.changeTimes=[m[1] for m in meshTimes[1:]]
        else:
            self.filename=filenames
            self.nextFiles=[]
            self.changeTimes=[]

        self._changeFileHooks=[]

        self.silent=silent
        self.tail=tailLength
        self.sleep=sleep
        self.follow=follow
        self.isTailing=False

        if not path.exists(self.filename):
            print_("Error: Logfile ",self.filename,"does not exist")

        self.reader=LineReader(config().getboolean("SolverOutput","stripSpaces"))

    def getSize(self,filename):
        """:return: the current size (in bytes) of the file"""
        return os.stat(filename)[stat.ST_SIZE]

    def addChangeFileHook(self,func):
        self._changeFileHooks.append(func)

    def changeFile(self,filename):
        currSize=self.getSize(filename)

        fn,ext=path.splitext(filename)
        if ext=='.gz':
            fh=gzip.open(filename)
        else:
            fh=open(filename)

        for f in self._changeFileHooks:
            f()

        return fh,currSize

    def start(self):
        """Reads the file and does the processing"""

        fh,currSize=self.changeFile(self.filename)
        switchTime=None if len(self.changeTimes)==0 else self.changeTimes[0]
        self.changeTimes=self.changeTimes[1:]

        self.startHandle()

        while self.follow or currSize>self.reader.bytesRead() or len(self.nextFiles)>0:
            if not currSize>self.reader.bytesRead() or self.analyzer.isPastTime(switchTime):
                if len(self.nextFiles)>0:
                    print_("\n\nSwitching from logfile",self.filename,
                           "to",self.nextFiles[0],"\n\n")
                    self.filename=self.nextFiles[0]
                    self.nextFiles=self.nextFiles[1:]
                    fh,currSize=self.changeFile(self.filename)
                    switchTime=None if len(self.changeTimes)==0 else self.changeTimes[0]
                    self.changeTimes=self.changeTimes[1:]
                    self.reader.reset()
                    self.analyzer.resetFile()
                    if currSize==0:
                        continue
                else:
                    if not self.follow:
                        break
            try:
                status=self.reader.read(fh)
                if status:
                    line=self.reader.line
                    if (currSize-self.reader.bytesRead())<=self.tail:
                        if not self.isTailing:
                            self.isTailing=True
                            self.timeHandle()
                            self.tailingHandle()

                        if not self.silent:
                            print_(line)

                    self.lineHandle(line)
                else:
                    if self.reader.userSaidStop():
                        break
                    sleep(self.sleep)
            except KeyboardInterrupt:
                print_("Watcher: Keyboard interrupt")
                break

        self.stopHandle()

        fh.close()

    def startHandle(self):
        """to be called before the program is started"""
        pass

    def stopHandle(self):
        """called after the program has stopped"""
        pass

    def tailingHandle(self):
        """called when the first line is output"""
        pass

    def lineHandle(self,line):
        """called every time a new line is read"""
        pass
Exemple #3
0
class BasicWatcher(object):
    """Base class for watching the output of commands

    Works like the UNIX-command 'tail -f <file>': the last lines of the file are output.
    If the file grows then these lines are output as they arrive"""

    def __init__(self,filename,
                 silent=False,
                 tailLength=1000,
                 sleep=0.1,
                 follow=True):
        """@param filename: name of the logfile to watch
        @param silent: if True no output is sent to stdout
        @param tailLength: number of bytes at the end of the fail that should be output.
        @param follow: if the end of the file is reached wait for further input
        Because data is output on a per-line-basis
        @param sleep: interval to sleep if no line is returned"""

        self.filename=filename
        self.silent=silent
        self.tail=tailLength
        self.sleep=sleep
        self.follow=follow
        self.isTailing=False

        if not path.exists(self.filename):
            print_("Error: Logfile ",self.filename,"does not exist")

        self.reader=LineReader()

    def getSize(self):
        """@return: the current size (in bytes) of the file"""
        return os.stat(self.filename)[stat.ST_SIZE]

    def start(self):
        """Reads the file and does the processing"""

        currSize=self.getSize()

        fn,ext=path.splitext(self.filename)
        if ext=='.gz':
            fh=gzip.open(self.filename)
        else:
            fh=open(self.filename)

        self.startHandle()

        while self.follow or currSize>self.reader.bytesRead():
            try:
                status=self.reader.read(fh)
                if status:
                    line=self.reader.line
                    if (currSize-self.reader.bytesRead())<=self.tail:
                        if not self.isTailing:
                            self.isTailing=True
                            self.timeHandle()
                            self.tailingHandle()

                        if not self.silent:
                            print_(line)

                    self.lineHandle(line)
                else:
                    if self.reader.userSaidStop():
                        break
                    sleep(self.sleep)
            except KeyboardInterrupt:
                print_("Watcher: Keyboard interrupt")
                break

        self.stopHandle()

        fh.close()

    def startHandle(self):
        """to be called before the program is started"""
        pass

    def stopHandle(self):
        """called after the program has stopped"""
        pass

    def tailingHandle(self):
        """called when the first line is output"""
        pass

    def lineHandle(self,line):
        """called every time a new line is read"""
        pass