import math import os import sys import collections from datetime import datetime def spawn_daemon(fun): # do the UNIX double-fork magic, see Stevens' "Advanced # Programming in the UNIX Environment" for details (ISBN 0201563177) try: pid = os.fork() if pid > 0: # parent process, return and keep running return except OSError as e: print("fork #1 failed: {0} ({1})".format(e.errno, e.strerror), file=sys.stderr) sys.exit(1) os.setsid() # do second fork try: pid = os.fork() if pid > 0: # exit from second parent print("[{0}] server running".format(pid)) sys.exit(0) except OSError as e: print("fork #2 failed: {0} ({1})".format(e.errno, e.strerror), file=sys.stderr) sys.exit(1) fun() # all done os._exit(os.EX_OK) def split_host(host, default_port=0): address, _, port = host.partition(":") if not port: port = default_port return (address, port) class Progress: def __init__(self, n, i0=0): self._n = n self._i0 = i0 self._i = i0 self._last = "" self._past = collections.deque() def p(self, i): i0 = self._i0 n = self._n now = datetime.now() assert i0<=i1: self._past.append((now, i)) if res!=self._last or (now-self._past[0][0]).total_seconds()>5: eta = format_seconds(self.eta(i)) self._print("{0} (ETA {1})".format(res, eta)) self._last = res while (now-self._past[0][0]).total_seconds()>5: self._past.popleft() def done(self): self._print("100%", end="\n") def eta(self, i2): t2 = datetime.now() (t1, i1) = self._past[0] if i2==i1: return float("nan") return (self._n-i2)/(i2-i1)*(t2-t1).total_seconds() @staticmethod def _p(i, n, i0): _1=1 if n>=i0 else -1 return 100*(i+_1-i0)//(n-i0) def _print(self, s, end=""): print("\r"+" "*80, end="") print("\r"+s, end=end) def format_seconds(secs): if math.isnan(secs): return "?" secs = round(secs) if secs<60: return "{0}s".format(secs) mins = secs//60 secs %= 60 if mins<60: return "{0:02}:{1:02}".format(mins, secs) hours = mins//60 mins %= 60 return "{0:02}:{1:02}:{2:02}".format(hours, mins, secs) if __name__=="__main__": import random import time progress = Progress(100) for i in range(1, 100): progress.p(i) time.sleep(random.random()*2) progress.done()