在 Python 中用闹钟实现时钟的最有效方法

Posted

技术标签:

【中文标题】在 Python 中用闹钟实现时钟的最有效方法【英文标题】:most efficient way to implement clock with alarm clock in Python 【发布时间】:2014-12-18 00:29:32 【问题描述】:

我正在尝试用 Python 实现一个带闹钟的数字时钟。现在我想知道实现闹钟功能的最佳方法是什么。我找到了几个类似的项目,主要集中在闹钟功能上。他们通常只计算下一个唤醒广告进入睡眠的时间,直到计算出的秒数。 见here和here:

我的问题是,我还实现了一个普通时钟并显示时间。出于这个原因,我必须每秒更新时钟。在这个循环中,我检查是否不应该关闭警报。出于这个原因,我正在寻找简单有效的闹钟功能实现。

受第一个示例的启发,我最终得到了这个:

#!/usr/bin/python

import time
import datetime

class Clock:

    def __init__(self):

        # set the initial time
        self.hour = 0
        self.minute = 0
        self.second = 0
        # the update interval in seconds
        self.update_interval = 1
        self.keep_running = True
        # the instance of the alarm
        self.alarm = AlarmClock()

    def run(self):
        while self.keep_running:
            # update the clock time
            now = datetime.datetime.now()
            self.hour = now.hour
            self.minute = now.minute
            self.second = now.second

            # now check if the alarm should not be started
            if self.alarm.is_active():
                if self.alarm.time_till_next_alarm() < 1:
                    # has to be done in separate thread
                    self.alarm.on_wake_up()

            time.sleep(self.update_interval)

    def get_alarm(self):
        return self.alarm


class AlarmClock:
    def __init__(self, hour=8, minute=0):
        # We start with predefined alarm at 8:00 which is not active
        self.hour = hour
        self.minute = minute
        self.active = False
        # the alarm should be stopped after some time (1h 00min)
        self.duration = datetime.timedelta(hours=1, minutes=0)

    def time_till_next_alarm(self):
        now = datetime.datetime.now()  # get current date & time

        # separate date and time from each other:
        currdate = datetime.date(now.year, now.month, now.day)
        currtime = datetime.time(now.hour, now.minute)
        alarmtime = self.get_wake_up_time()
        # add today's date onto the alarm time entered
        alarmdatetime = datetime.datetime.combine(currdate, alarmtime)
        if alarmtime <= currtime:  # if the alarm time is less than the current time set clock for tomorrow
            alarmdatetime += datetime.timedelta(hours=24)

        return alarmdatetime - now

    def set_time(self, hour, minute):
        self.hour = hour
        self.minute = minute

    def activate(self):
        self.active = True

    def deactivate(self):
        self.active = False

    def is_active(self):
        return self.active

    def on_wake_up(self):
        # start the wake up
        print 'Wake up!'


#Execution starts here
if __name__ == '__main__':

    clock = Clock()
    clock.get_alarm().activate()
    clock.get_alarm().set_time(8,0)
    clock.run()

有没有更好或更少计算要求的实现?

编辑:

我想在 7 段 LCD 显示屏上显示时间,here are some details about the part. 为此,我在 run() 方法中写入 LCD 显示屏每次更新时的数字 p>

# set the tens and ones of hours and minutes
self.display.set_digit(0, int(self.hour / 10))     # Tens
self.display.set_digit(1, self.hour % 10)          # Ones
self.display.set_digit(2, int(self.minute / 10))   # Tens
self.display.set_digit(3, self.minute % 10)        # Ones

编辑2:

虽然 Adafruit 提供的 python 库允许您设置整个显示器的闪烁率,但我想以 1Hz 的频率闪烁冒号 - 以暗示秒数。

 # Toggle colon at 1Hz
 self.display.set_colon(self.second % 2)

【问题讨论】:

我认为很多代码可以被删除,但你没有显示你显示时间的位置,所以很难猜测一些细节。例如,为什么要保留Clock.hour, Clock.minute, Clock.second...它已经在datetime.datetime.now() 中。至于闹钟,你可以使用threading.Timer。 【参考方案1】:

查看sched 模块。包含在 Python 标准库中!

文档:https://docs.python.org/2/library/sched.html

【讨论】:

【参考方案2】:

您可以完全消除 AlarmClock 类,只使用threading.Timer。大多数其他类似乎也是多余的 - datetime 对象已经有小时、分钟、秒,所以不需要保留你自己的版本。

import datetime
import threading
import sys

def ring_ring():
    sys.stdout.write('ring ring\n')
    sys.stdout.flush()

class Clock:

    def __init__(self):
        self.alarm_time = None
        self._alarm_thread = None
        self.update_interval = 1
        self.event = threading.Event()

    def run(self):
        while True:
            self.event.wait(self.update_interval)
            if self.event.isSet():
                break
            now = datetime.datetime.now()
            if self._alarm_thread and self._alarm_thread.is_alive():
                alarm_symbol = '+'
            else:
                alarm_symbol = ' '
            sys.stdout.write("\r%02d:%02d:%02d %s" 
                % (now.hour, now.minute, now.second, alarm_symbol))
            sys.stdout.flush()

    def set_alarm(self, hour, minute):
        now = datetime.datetime.now()
        alarm = now.replace(hour=int(hour), minute=int(minute))
        delta = int((alarm - now).total_seconds())
        if delta <= 0:
            alarm = alarm.replace(day=alarm.day + 1)
            delta = int((alarm - now).total_seconds())
        if self._alarm_thread:
            self._alarm_thread.cancel()
        self._alarm_thread = threading.Timer(delta, ring_ring)
        self._alarm_thread.daemon = True
        self._alarm_thread.start()

clock = Clock()
clock.set_alarm(sys.argv[1], sys.argv[2])
clock.run()

【讨论】:

非常感谢您的回答。你可能是关于我班的冗余。我可能对时间显示含糊其辞。我用 i2c 总线连接了一个 LED 7 段显示器,我想在上面显示电流。我用相关代码更新了我的第一篇文章。有关显示和提供的库的一些信息可以在这里找到:bit.ly/1DQ6OXl

以上是关于在 Python 中用闹钟实现时钟的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章

关于闹钟的AlarmManager的type选择??到底该用哪个啊?

在 Python 3 中用啥替代 xreadlines()?

python中用requests库实现Windows认证登录

VB中用SetParent函数让应用程序在指定窗体中运行

python中用代码实现99乘法表

java中用print函数的输出问题。