class FReader(object): """ """ NORMAL = 1 SSH = 2 def __init__(self, path): """ :param path: :return: """ self.path = path self.abs_path = os.path.abspath(path) {True: self.connect_remote_file, False: self.connect_local_file}[path.find(":") != -1](path) self._buffer = "" self.queue = Queue.Queue() self.line = [] def connect_remote_file(self, path): host, remote_file = path.split(':', 1) self.basename = os.path.basename(remote_file) self.fd = Popen(["ssh", "-o BatchMode=yes", host, "tail", "-f", remote_file], stdin=PIPE, stdout=PIPE, close_fds=True) self._t = self.SSH def connect_local_file(self, path): self._t = self.NORMAL self.fd = open(path) self.basename = os.path.basename(path) @property def file_name(self): return self.basename def __hash__(self): return self.fd.__hash__() def read_line(self): self._buffer = "" fd = self.fd.fileno() fl = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) try: self._buffer += self.fd.read(1) while self._buffer[-1] != '\n': self._buffer += self.fd.read(1) return True except IOError: return False finally: fcntl.fcntl(fd, fcntl.F_SETFL, fl) def read(self): if self.is_ssh_file: self.fd.poll() if self.read_line(): return self._buffer else: return "" @property def is_ssh_file(self): return self._t == self.SSH