Python threading.Timer() Examples

The following are 30 code examples of threading.Timer(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module threading , or try the search function .
Example #1
Source File: web.py    From svviz with MIT License 6 votes vote down vote up
def run(port=None):
    import webbrowser, threading

    if port is None:
        port = getRandomPort()

    # load()
    url = "http://127.0.0.1:{}/".format(port)
    logging.info("Starting browser at {}".format(url))
    # webbrowser.open_new(url)

    threading.Timer(1.25, lambda: webbrowser.open(url) ).start()

    app.run(
        port=port#,
        # debug=True
    ) 
Example #2
Source File: buzzer.py    From rainbow-hat with MIT License 6 votes vote down vote up
def note(frequency, duration=1.0):
    """Play a single note.

    :param frequency: Musical frequency in hertz
    :param duration: Optional duration in seconds, use None to sustain note

    """
    global _timeout

    setup()

    if frequency <= 0:
        raise ValueError("Frequency must be > 0")

    if duration is not None and duration <= 0:
        raise ValueError("Duration must be > 0")

    clear_timeout()

    pwm.ChangeFrequency(frequency)
    GPIO.setup(BUZZER, GPIO.OUT)

    if duration is not None and duration > 0:
        _timeout = Timer(duration, stop)
        _timeout.start() 
Example #3
Source File: layer_2_protocol.py    From Faraday-Software with GNU General Public License v3.0 6 votes vote down vote up
def __init__(self, input_channel, serial_physical_obj):
        #Initialize class variables
        self.rx_packet_queue = Queue.Queue()
        self.rx_data_payload_queue = Queue.Queue()
        self.logic_startbyte_received = False
        self.logic_escapebyte_received = False
        self.logic_stopbyte_received = False
        self.receiver_class = Receiver_Datalink_Device_State_Parser_Class(input_channel, serial_physical_obj)
        self.enable_flag = True
        self.max_payload_size = 6
        self.datalink_packet_format = 'c' + str(self.max_payload_size) + 'c' + 'c'
        self.reconstruct_data = ''
        self.timer_interval = 5
        self.timer = threading.Timer(self.timer_interval, self.timer_trip)
        self.datalink_packet_struct = struct.Struct('BBB125s')

        #Start
        threading.Thread.__init__(self)
        self.start()  #Starts the run() function and thread 
Example #4
Source File: client.py    From Jike-Metro with MIT License 6 votes vote down vote up
def __init__(self, sync_unread=False):
        self.auth_token = read_token()
        if self.auth_token is None:
            self.auth_token = login()
            try:
                write_token(self.auth_token)
            except IOError:
                pass
        self.jike_session = JikeSession(self.auth_token)

        self.collection = None
        self.news_feed = None
        self.following_update = None

        self.unread_count = 0
        self.timer = None
        if sync_unread:
            self.timer = Timer(
                CHECK_UNREAD_COUNT_PERIOD,
                check_unread_count_periodically,
                args=(self,)
            ).start()

        self.notified_topics = ['all']
        self.notified_users = ['all'] 
Example #5
Source File: debug_adapter.py    From vscode-esp-idf-extension with Apache License 2.0 6 votes vote down vote up
def poll_target(self, *kwargs):
        log.info("Poll target")
        if self.state.wait_target_state == dbg.TARGET_STATE_STOPPED:
            stopped,rsn_str = self.is_stopped()
            if stopped:
                self.state.wait_target_state = dbg.TARGET_STATE_UNKNOWN
                self.__command_processor.generate_StoppedEvent(reason=rsn_str,
                                                               thread_id=0,
                                                               all_threads_stopped=True)
        elif self.state.wait_target_state == dbg.TARGET_STATE_RUNNING:
            # this is not fully implemented yet, need to define when we need to start waiting for target get running
            try:
                self._gdb.wait_target_state(dbg.TARGET_STATE_RUNNING, 0)
                self.state.wait_target_state = dbg.TARGET_STATE_UNKNOWN
                self.__command_processor.generate_ContinuedEvent(thread_id=0,
                                                                all_threads_continued=True)
            except dbg.DebuggerTargetStateTimeoutError:
                pass
        if self.state.wait_target_state != dbg.TARGET_STATE_UNKNOWN:
            # restart timer if we still need to wait for target state
            self.target_poller = threading.Timer(1.0, self.poll_target, args=[self,])
            self.target_poller.start() 
Example #6
Source File: utils.py    From apt2 with MIT License 6 votes vote down vote up
def execWait(cmd, outfile=None, timeout=0):
        result = ""
        env = os.environ
        proc = subprocess.Popen(cmd, executable='/bin/bash', env=env, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True)

        if timeout:
            timer = threading.Timer(timeout, proc.kill)
            timer.start()
        result = proc.communicate()[0]
        if timeout:
            if timer.is_alive():
                timer.cancel()
        if outfile:
            if Utils.fileExists(outfile):
                print "FILE ALREADY EXISTS!!!!"
            else:
                tmp_result = "\033[0;33m(" + time.strftime(
                    "%Y.%m.%d-%H.%M.%S") + ") <pentest> #\033[0m " + cmd + Utils.newLine() + Utils.newLine() + result
                Utils.writeFile(tmp_result, outfile)
        return result 
Example #7
Source File: test_reloader.py    From sanic with MIT License 6 votes vote down vote up
def test_reloader_live(runargs, mode):
    with TemporaryDirectory() as tmpdir:
        filename = os.path.join(tmpdir, "reloader.py")
        text = write_app(filename, **runargs)
        proc = Popen(argv[mode], cwd=tmpdir, stdout=PIPE, creationflags=flags)
        try:
            timeout = Timer(5, terminate, [proc])
            timeout.start()
            # Python apparently keeps using the old source sometimes if
            # we don't sleep before rewrite (pycache timestamp problem?)
            sleep(1)
            line = scanner(proc)
            assert text in next(line)
            # Edit source code and try again
            text = write_app(filename, **runargs)
            assert text in next(line)
        finally:
            timeout.cancel()
            terminate(proc)
            with suppress(TimeoutExpired):
                proc.wait(timeout=3) 
Example #8
Source File: pynpuzzle.py    From pynpuzzle with MIT License 6 votes vote down vote up
def stop_button_cmd():
    """
    Stop button click handler
    """
    # Do some routines for stopping calculation
    calculation_stop()
    # Stop algorithm's process
    search_process.terminate()
    output_pipe.close()
    # Stop timer thread and stop refreshing status bar
    timer_event.set()
    # Clear status labels
    threading.Timer(0.1, max_ram_var.set, args=('',)).start()
    threading.Timer(0.1, cpu_var.set, args=('',)).start()
    threading.Timer(0.1, ram_var.set, args=('',)).start()


# Action buttons
#
# Output stop widget and it's border frame 
Example #9
Source File: read_sensors_d.py    From openplotter with GNU General Public License v2.0 6 votes vote down vote up
def work_analog():
	threading.Timer(rate_ana, work_analog).start()
	SignalK='{"updates":[{"$source":"OPsensors.SPI.MCP3008","values":[ '
	Erg=''
	send=False
	for i in MCP:
		if i[0]==1:
			send=True
			XValue=read_adc(i[1])
			if i[4]==1:
				XValue = interpolread(i[1],XValue)
			Erg +='{"path": "'+i[2]+'","value":'+str(XValue)+'},'

	if send:
		SignalK +=Erg[0:-1]+']}]}\n'
		sock.sendto(SignalK, ('127.0.0.1', 55557))	
	
# read gpio and GENERATE SK 
Example #10
Source File: price_tracking.py    From BitUtils with MIT License 6 votes vote down vote up
def FoundANewCoinEvent(newCoin):    
    global E_MODE
    global PURCHARSED_COIN_NAME

    print("FoundANewCoinEvent(newCoin)")
    E_MODE = 1    # change mode into TRADING

    onlyEngCoinName = re.sub(r"[^A-Za-z]+", '', newCoin)
    sendTelegramMsg("새로운 코인 상장 발견 : " + newCoin +", [" + onlyEngCoinName +"]로 비트렉스 시장 검색시작.")
    
    # buy 95% of current balance at bittrex
    affordable, savedRate= HowManyCoinYouCanBuyWithMyBalance("BTC", onlyEngCoinName)
    targetCoinName, Quantity_request= BuyLimit_PercentageOfMyBalance("BTC", onlyEngCoinName, affordable, savedRate, 0.95)

    PURCHARSED_COIN_NAME = targetCoinName # save purchased name of coin
    sendTelegramMsg("[" + targetCoinName +"]코인을 " + str(Quantity_request) +"만큼 매수 시도했음.")
    
    t = Timer(600, SellAgain)
    t.start() # after x seconds, sell again 
Example #11
Source File: tele_channel_tracker2.py    From BitUtils with MIT License 6 votes vote down vote up
def FoundLeadingSignal(TargetCoinName):
    global E_MODE
    global PURCHARSED_COIN_NAME
    # buy 95% of current balance at bittrex
    affordable, savedRate= HowManyCoinYouCanBuyWithMyBalance("BTC", TargetCoinName)
    _targetCoinName, Quantity_request, Price_request, err_msg= BuyLimit_PercentageOfMyBalance("BTC", TargetCoinName, affordable, savedRate, 0.95)

    if savedRate == None:
        sendTelegramMsg("[" + _targetCoinName +"]코인을 구매하는데 실패했음. \nbittrex에 없는 코인일 가능성 확인바람.")
    else:
        if Quantity_request == 0:
            sendTelegramMsg("[" + _targetCoinName +"]코인을 구매하는데 실패했음. \n에러명 : " + err_msg + "\n그래도 sell limit 시도는 함.")
        else:
            PURCHARSED_COIN_NAME = _targetCoinName # save purchased name of coin
            sendTelegramMsg("[" + _targetCoinName +"]코인을 " + str(Quantity_request) +"만큼 매수 시도했음. \n매수 시도 가격 : {0:.8f}".format(Price_request))
    
        # normally, 80secs to 100secs go high
        t = Timer(90, SellAgain)
        t.start() # after x seconds, sell again 
Example #12
Source File: timecontrol.py    From picochess with GNU General Public License v3.0 6 votes vote down vote up
def start_internal(self, color, log=True):
        """Start the internal clock."""
        if not self.internal_running():
            if self.mode in (TimeMode.BLITZ, TimeMode.FISCHER):
                self.active_color = color
                self.reset_start_time()

            if log:
                w_hms, b_hms = self._log_time()
                logging.info('start internal time w:%s - b:%s [ign]', w_hms, b_hms)
                logging.info('received clock time w:%s - b:%s [use]',
                             hms_time(self.clock_time[chess.WHITE]), hms_time(self.clock_time[chess.BLACK]))

            self.internal_time[chess.WHITE] = self.clock_time[chess.WHITE]
            self.internal_time[chess.BLACK] = self.clock_time[chess.BLACK]

            # Only start thread if not already started for same color, and the player has not already lost on time
            if self.internal_time[color] > 0 and self.active_color is not None and self.run_color != self.active_color:
                self.timer = threading.Timer(copy.copy(self.internal_time[color]), self._out_of_time,
                                             [copy.copy(self.internal_time[color])])
                self.timer.start()
                logging.debug('internal timer started - color: %s run: %s active: %s',
                              color, self.run_color, self.active_color)
                self.run_color = self.active_color 
Example #13
Source File: util.py    From browserscope with Apache License 2.0 6 votes vote down vote up
def GvizTableData(request):
    """Returns a string formatted for consumption by a Google Viz table."""
    #def throw_deadline():
    #    logging.info('MANUAL THROW!! DeadlineExceededError DeadlineExceededError')
    #    raise DeadlineExceededError
    #t = Timer(15.0, throw_deadline)

    test_set = None
    category = request.GET.get('category')
    if not category:
        return http.HttpResponseBadRequest('Must pass category=something')

    test_set = all_test_sets.GetTestSet(category)
    if not test_set:
        return http.HttpResponseBadRequest(
            'No test set was found for category=%s' % category)

    formatted_gviz_table_data = GetStats(request, test_set, 'gviz_table_data')
    return http.HttpResponse(formatted_gviz_table_data) 
Example #14
Source File: genexercise.py    From genmon with GNU General Public License v2.0 6 votes vote down vote up
def PostWarmup(self):

        # check to see if the generator is running
        status = self.SendCommand("generator: getbase")
        if not status.lower() in ["running", "exercising"]:
            self.LogError("WARNING: generator not running post warmup. Transfer switch not activated.")
            self.SendCommand("generator: setremote=stop")
            return

        self.SendCommand("generator: setremote=starttransfer")
        self.DebugOutput("Starting transfer exercise cycle (post warmup).")
        # set timer to stop
        self.StopTimer = threading.Timer(float(self.ExerciseDuration  * 60.0), self.StopExercise)
        self.StopTimer.start()

    # ---------- GenExercise::ReadyToExercise----------------------------------- 
Example #15
Source File: util.py    From EvalNE with MIT License 6 votes vote down vote up
def run(cmd, timeout, verbose):
    if verbose:
        sto = None
        ste = None
    else:
        devnull = open(os.devnull, 'w')
        sto = devnull
        ste = devnull
    # Alternative without timeout
    # subprocess.run(cmd, shell=True, stdout=sto, stderr=ste)
    proc = Popen(shlex.split(cmd), stdout=sto, stderr=ste)
    timer = Timer(timeout, proc.kill)
    try:
        timer.start()
        proc.communicate()
    finally:
        if proc.poll() != 0:
            raise TimeoutExpired('Command `{}` timed out'.format(cmd))
        timer.cancel() 
Example #16
Source File: excelRTDServer.py    From ironpython2 with Apache License 2.0 6 votes vote down vote up
def Update(self):
    # Get our wake-up thread ready...
    self.ticker = threading.Timer(self.INTERVAL, self.Update)
    try:
      # Check if any of our topics have new info to pass on
      if len(self.topics):     
        refresh = False
        for topic in self.topics.itervalues():
          topic.Update(self)
          if topic.HasChanged():
            refresh = True
          topic.Reset()
            
        if refresh:
          self.SignalExcel()
    finally:
      self.ticker.start() # Make sure we get to run again 
Example #17
Source File: debug_adapter.py    From vscode-esp-idf-extension with Apache License 2.0 5 votes vote down vote up
def start_target_poller(self, state):
        self.state.wait_target_state = state
        self.target_poller = threading.Timer(1.0, self.poll_target, args=[self,])
        self.target_poller.start() 
Example #18
Source File: utilities.py    From picochess with GNU General Public License v3.0 5 votes vote down vote up
def start(self):
        """Start the RepeatedTimer."""
        if not self.timer_running:
            self._timer = Timer(self.interval, self._run)
            self._timer.start()
            self.timer_running = True
        else:
            logging.info('repeated timer already running - strange!') 
Example #19
Source File: board.py    From picochess with GNU General Public License v3.0 5 votes vote down vote up
def run(self):
        """NOT called from threading.Thread instead inside the __init__ function from hw.py."""
        self.incoming_board_thread = Timer(0, self._process_incoming_board_forever)
        self.incoming_board_thread.start() 
Example #20
Source File: board.py    From picochess with GNU General Public License v3.0 5 votes vote down vote up
def start_field_timer(self):
        """Start the field timer waiting for a stable board position."""
        if self.low_time:
            wait = (0.2 if self.channel == 'BT' else 0.10) + 0.06 * self.field_factor  # bullet => allow more sliding
        else:
            wait = (0.5 if self.channel == 'BT' else 0.25) + 0.03 * self.field_factor  # BT's scanning in half speed
        logging.debug('board position changed => wait %.2fsecs for a stable result low_time: %s', wait, self.low_time)
        self.field_timer = Timer(wait, self.expired_field_timer)
        self.field_timer.start()
        self.field_timer_running = True 
Example #21
Source File: util.py    From OpenMTC with Eclipse Public License 1.0 5 votes vote down vote up
def __updateExpTime(self, instance, future=None, fields=[], restore=None,
                        send_update=None):
        """ Updates a resource instance's expirationTime to future.

            @note: Starts a new Timer.
            @param instance: resource instance to update
            @param future: new expirationTime value (optional)
            @param fields: additional fields mandatory during update
            @param restore: function that will restore the instance, if it has
                            expired accidentally. Has to restart the refresher.
        """
        self.logger.debug("__updateExpTime: %s" % instance )
        if self.__shutdown:
            return

        interval = self.interval
        offset = self.offset
        future = datetime_the_future(interval + offset)

        instance.expirationTime = future

        if send_update:
            send_update(instance)
        else:
            return

        # NOTE: expirationTime might have been changed by CSE at this point.
        # update could/should return the updated instance in this case,
        #   but does it?
        # => additional GET to confirm expirationTime ?
        kwargs = {"instance": instance, "fields": fields, "restore": restore,
                  "send_update": send_update}
        t = Timer(interval, self.__updateExpTime, kwargs=kwargs)
        t.start()
        self.timers[instance.path] = t
        # hopefully, GC will delete the old timer 
Example #22
Source File: util.py    From OpenMTC with Eclipse Public License 1.0 5 votes vote down vote up
def start(self, instance, fields=None, restore=None, send_update=None):
        """ Starts a threading.Timer chain,
            to repeatedly update a resource instances's expirationTime.

            @param instance: resource instance
            @param fields: additional fields mandatory during update
            @param restore: function that will restore the instance, if it has
                            expired accidentally. Has to restart the refresher.
            @param send_update:
        """
        self.logger.debug("starting expTimeUpdater: %s %s" % (instance,
                                                              fields))
        self.__shutdown = False
        interval = (time.mktime(instance.expirationTime.timetuple()) -
                    (time.time() + time.timezone))
        if interval > self.offset:
            interval -= self.offset
        else:
            interval -= (interval/10)

        send_update = send_update or self.send_update or None

        kwargs = {"instance": instance, "fields": fields, "restore": restore,
                  "send_update": send_update}
        t = Timer(interval, self.__updateExpTime, kwargs=kwargs)
        t.start()

        self.timers[instance.path] = t 
Example #23
Source File: pi.py    From picochess with GNU General Public License v3.0 5 votes vote down vote up
def __init__(self, dgtboard: DgtBoard):
        super(DgtPi, self).__init__(dgtboard)

        self.lib_lock = Lock()
        self.lib = cdll.LoadLibrary('etc/dgtpicom.x86.so' if machine() == 'x86_64' else 'etc/dgtpicom.so')

        # keep the last time to find out errorous DGT_MSG_BWTIME messages (error: current time > last time)
        self.r_time = 3600 * 10  # max value cause 10h cant be reached by clock
        self.l_time = 3600 * 10  # max value cause 10h cant be reached by clock

        self.in_settime = False  # this is true between set_clock and clock_start => use set values instead of clock

        self._startup_i2c_clock()
        incoming_clock_thread = Timer(0, self._process_incoming_clock_forever)
        incoming_clock_thread.start() 
Example #24
Source File: websockets.py    From python-binance with MIT License 5 votes vote down vote up
def _start_socket_timer(self, socket_type):
        callback = self._keepalive_account_socket

        self._timers[socket_type] = threading.Timer(self._user_timeout, callback, [socket_type])
        self._timers[socket_type].setDaemon(True)
        self._timers[socket_type].start() 
Example #25
Source File: balancer.py    From python-mysql-pool with MIT License 5 votes vote down vote up
def start(self):
        if not self.is_running:
            self._timer = threading.Timer(self.interval, self._run)
            self._timer.daemon = True
            self._timer.start()
            self.is_running = True 
Example #26
Source File: Agent.py    From pcocc with GNU General Public License v3.0 5 votes vote down vote up
def intr_handler_th(cls, stop_sig_r, intr_r):
        logging.info("Starting intr thread")
        while True:
            try:
                rdr, _, _ = select.select([stop_sig_r, intr_r], [], [])
            except select.error  as e:
                logging.info("Ignoring interrupt in select")
                if e.args[0] == 4:
                    continue
                else:
                    logging.info("Abandonning interrupt monitoring due to error")
                    break
            if cls._intr_r in rdr:
                logging.info("Interrupt received")
                os.read(cls._intr_r, 1)
                cls._lock.acquire()
                for cluster, indices, eid, ctx in cls._registered_execs:
                    logging.info("Interrupt received, sending kill to %d", eid)
                    cls.kill(cluster, indices, exec_id=eid)
                    timer = threading.Timer(10, ctx.cancel)
                    ctx.add_callback(timer.cancel)
                    timer.start()
                cls._lock.release()
                return
            elif cls._stop_sig_r in rdr:
                os.read(cls._stop_sig_r, 1)
                logging.debug("Interrupt handler thread was asked to stop")
                return 
Example #27
Source File: genexercise.py    From genmon with GNU General Public License v2.0 5 votes vote down vote up
def StartExercise(self):

        if self.ExerciseActive:
            # already active
            return

        # Start generator
        if self.ExerciseType.lower() == "normal" and self.ReadyToExercise():
            self.SendCommand("generator: setremote=start")
            self.DebugOutput("Starting normal exercise cycle.")
            self.StopTimer = threading.Timer(float(self.ExerciseDuration  * 60.0), self.StopExercise)
            self.StopTimer.start()
        elif self.ExerciseType.lower() == "quiet" and self.ReadyToExercise():
            self.SendCommand("generator: setremote=startexercise")
            self.DebugOutput("Starting quiet exercise cycle.")
            self.StopTimer = threading.Timer(float(self.ExerciseDuration  * 60.0), self.StopExercise)
            self.StopTimer.start()
        elif self.ExerciseType.lower() == "transfer" and self.ReadyToExercise():
            if self.ExerciseWarmup == 0:
                self.SendCommand("generator: setremote=starttransfer")
                self.DebugOutput("Starting transfer exercise cycle.")
                self.StopTimer = threading.Timer(float(self.ExerciseDuration  * 60.0), self.StopExercise)
                self.StopTimer.start()
            else:
                self.SendCommand("generator: setremote=start")
                self.DebugOutput("Starting warmup for transfer exercise cycle.")
                # start timer for post warmup transition to starttransfer command
                self.WarmupTimer = threading.Timer(float(self.ExerciseWarmup  * 60.0), self.PostWarmup)
                self.WarmupTimer.start()
        else:
            self.LogError("Invalid mode in StartExercise: " + str(self.ExerciseType))
            return
        self.WriteLastExerciseTime()
        self.ExerciseActive = True

    # ---------- GenExercise::StopExercise-------------------------------------- 
Example #28
Source File: orchestrator.py    From pyDcop with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def __init__(self, algo: AlgorithmDef, cg: ComputationGraph,
                 agent_mapping: Distribution,
                 comm: CommunicationLayer,
                 dcop: DCOP,
                 infinity=float('inf'),
                 collector: Queue=None,
                 collect_moment: str='value_change',
                 collect_period: float=None,
                 ui_port: int = None):
        self._own_agt = Agent(ORCHESTRATOR, comm, ui_port=ui_port)
        self.directory = Directory(self._own_agt.discovery)
        self._own_agt.add_computation(self.directory.directory_computation)
        self._own_agt.discovery.use_directory(ORCHESTRATOR,
                                              self._own_agt.address)
        self.discovery = self._own_agt.discovery
        self.messaging = comm.messaging

        self.logger = self._own_agt.logger
        self.dcop = dcop

        self.status = 'OK'

        # For scenario execution
        self._events_iterator = None
        self._event_timer = None  # type: threading.Timer
        self._timeout_timer = None

        self._stopping = threading.Event()

        self.mgt = AgentsMgt(algo, cg, agent_mapping, dcop,
                             self._own_agt, self, infinity, collector=collector,
                             collect_moment=collect_moment,
                             collect_period=collect_period) 
Example #29
Source File: orchestrator.py    From pyDcop with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def _process_event(self):

        # FIXME: hack too avoid overlapping events
        waited = [a for a, state in self.mgt._agts_state.items()
                  if state != 'running']
        if waited:
            self.logger.warning(f"Event while agents {waited} are still processing"
                                f" previous event, wait 20 s ")
            self._event_timer = threading.Timer(20, self._process_event)
            self._event_timer.start()
            return

        try:
            evt = next(self._events_iterator)
        except StopIteration:
            self.logger.info("All events processed for scenario")
            self._events_iterator = None
            return

        if evt.is_delay:
            self.logger.info('Delay: wait %s s for next event', evt.delay)
            self._event_timer = threading.Timer(evt.delay, self._process_event)
            self._event_timer.start()

        else:
            self.logger.info('posting event to mgt %s', evt)
            self._mgt_method('_orchestrator_scenario_event', evt)
            self._process_event() 
Example #30
Source File: logger.py    From dialogbot with Apache License 2.0 5 votes vote down vote up
def start_heartbeat(interval=60 * 10, logger=None):
    import time
    import threading

    def print_time():
        t = time.strftime('%Y-%m-%d %H:%M:%S - heartbeat', time.localtime(time.time()))
        print(t)
        if logger:
            logger.info(t)
        timer = threading.Timer(interval, print_time)
        timer.start()

    timer = threading.Timer(interval, print_time)
    timer.start()