【问题标题】:Python call a function every second?Python每秒调用一个函数?
【发布时间】:2014-12-24 08:10:55
【问题描述】:

我有一个为我的第一个项目编写的游戏,我想要一个可以玩和暂停游戏的系统。当您单击取消暂停按钮时,我希望它每 1 秒调用一个函数来提前日期。 Time.sleep 停止了整个程序,所以它对我没有用,而且我似乎无法在启动线程后重新启动线程。这是提前一天的功能。

def time():
    global timer
    timer = threading.Timer(1.0, time)
    timer.start()
    thirtyonemonths = [1, 3, 5, 7, 8, 10, 12]
    thirtymonths = [4, 6, 9, 11]
    globalvars.day = globalvars.day + 1
    for self in thirtyonemonths:
        if self == globalvars.month:
            print "hi"
            if globalvars.day == 32:
                globalvars.day = 1
                globalvars.month = globalvars.month + 1
    for self in thirtymonths:
        if self == globalvars.month:
            print "hi"
            if globalvars.day == 31:
                globalvars.day = 1
                globalvars.month = globalvars.month + 1
    if globalvars.month == 2:
        print "hi"
        if globalvars.day == 29:
            globalvars.day = 1
            globalvars.month = globalvars.month + 1
    if globalvars.month == 13:
        globalvars.month = 1
        globalvars.year = globalvars.year + 1
    threading.Thread.time(self)
timer = threading.Timer(1.0, time)

稍后我有当按钮被点击时检查它是否被暂停的代码

if b.collidepoint(pos):
    if globalvars.ispaused == 1:
        globalvars.ispaused = 0
        timer.start()
        break
    if globalvars.ispaused == 0:
        globalvars.ispaused = 1
        timer.cancel()
        break

在我第三次按下按钮之前,一切正常。有谁知道我可以重新启动线程或者使用不同的方法来做我想做的事情?

【问题讨论】:

标签: python multithreading timer


【解决方案1】:

在你的函数开始时,你已经设置了一个新的全局每次和一个计时器:

global timer
timer = threading.Timer(1.0, time)
timer.start()

然后在函数的末尾你有 threading.Thread.time(self) 不需要并且需要删除。然后在函数声明之后你有timer = threading.Timer(1.0, time) 这可能是一个错误,因为当它第一次被调用时,全局计时器可能还没有创建。将最后一行代码替换为time(),以便第一次立即调用该函数。更改这两行可能会很好地修复您的代码。

另外,你的 for 循环是这样的:

for self in thirtyonemonths:

问题在于使用关键字 self 。如果这个函数是在一个类中定义的,那么self 的这种使用可能会被解释为对该对象的引用。通常最好不要使用诸如self 之类的关键字作为迭代器。将 self 的所有用法替换为其他内容,例如 m 以改进您的代码。

【讨论】:

  • 啊,好的,谢谢。我最后去掉了那段代码,还修复了“self”的使用。我最终只是停止了 time() 函数的内容,除非 unpaused 变量等于 1。这样我就不需要启动和停止线程。
【解决方案2】:

没有看到你的其余代码,很难确定问题出在哪里,但我猜有时,当你点击按钮时,ispaused1,但 timer 是过期的计时器而不是暂停的计时器。在过期的计时器上调用 start 无效。

虽然这可以解决,但有更简单的方法可以做到这一点。

一方面,您似乎在这里使用了某种 GUI 或游戏框架。我不知道您使用的是哪一个,但几乎每个人都有一个计时器功能(在主事件循环中,而不是在单独的线程中,但这不是这里的关键)更多比threading.Thread 更强大——特别是,它可以每秒自动重复一次,直到被取消。这显然会让你的生活更轻松。

如果没有,很容易编写自己的重复 Timer,或者只是 find one on PyPI。请注意,threading 文档以指向the source code 的链接开头。这是因为,就像 stdlib 中的许多模块一样,threading 的编写简单易懂,除了本身有用之外,还可以用作示例代码。特别是,Timer 非常简单,如何扩展它应该很明显:只需在 run 方法周围放置一个循环即可。

【讨论】:

  • 非常感谢您的回复。当另一个人提供更简单的解决方案时,我正在扩展 Timer。我最终只是停止了 time() 函数的内容,除非 unpaused 变量等于 1。这样我就不需要启动和停止线程。
  • 虽然是为了将来参考,但当您说“扩展计时器”时,您的意思是获取线程库中原始类的源代码并对其进行编辑?我会复制课程并将其粘贴到我的源代码中吗?我从来没有真正编辑过 python 附带的库。我假设我会重命名它并导入线程库,对吗?除非你的意思完全不同。我是菜鸟:p
  • 那个或者你可以extend the class。所以像class MyTimer(threading.Timer): def run(self): while (True): threading.Timer.run(self)。但不太可能。
  • @Taegis:通常你会称你的建议为“分叉类”,有时它是完全可行的。但是,虽然“扩展”无疑是一个模糊的术语,但我认为它通常意味着尽可能地进行子类化(如 Poil 所述),如果类的设计方式不可行,则退回到分叉或猴子补丁。跨度>
猜你喜欢
  • 2019-08-29
  • 2012-06-04
  • 2017-10-28
  • 1970-01-01
  • 2011-11-06
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 2015-06-26
相关资源
最近更新 更多