替代python的time.sleep()

时间:2013-03-01 21:40:37

标签: python matplotlib timer real-time

我正在进行实时数据处理+显示,每60秒就会点击一次数据库。我不想每隔60秒使用time.sleep(),因为它取消了对我的控制(即REPL访问变量,这不是必要但很好)并冻结了matplotlib图表。

还有其他选择吗?理想情况下,最初可以控制用户的东西,60秒后,取消控制,运行一些代码,更新绘图,然后将控制权交还给用户。 (当我说控制时,我指的是REPL控制)。

有什么想法吗?

1 个答案:

答案 0 :(得分:7)

如果您不需要取消用户控制,可以使用以下方法:创建threading.Timer

你想要做的是接受函数的“延续” - 即time.sleep之后的所有内容 - 并将其移动到单独的函数my_function中,然后将其安排为这样:

threading.Timer(60, my_function).start()

my_function的末尾,它会使用完全相同的代码行安排新的Timer

Timer是一个非常笨重的接口和实现,但它内置于stdlib中。您可以在ActiveState上找到配方,在PyPI上找到模块,提供更好的类,例如,在一个线程上运行多个计时器而不是每个计时器的一个线程,让您安排定期调用,这样您就不必自己重新安排等等。但是对于每60秒运行一次的东西,我认为你可以使用Timer

要记住的一件事:如果后台作业需要处理用户在REPL中处理的任何相同数据,则可能存在竞争条件。通常在交互式环境中(特别是在Python中,感谢GIL),您可以将责任放在用户身上,以免造成任何比赛。如果没有,你需要某种同步。

要记住的另一件事:如果你正在尝试进行GUI工作,取决于你正在使用的GUI(我相信matplotlib是可配置的,但默认为tkinter?),你可能无法从后台线程更新GUI。

但无论如何,在这种情况下实际上有一个更好的解决方案。 GUI程序有一个在某个线程或其他线程中运行的事件循环,几乎每个事件循环设计都有一种方法来在该线程中安排一个计时器。对于tkinter,如果你有root对象的句柄,只需调用root.after(60000, my_function)而不是threading.Timer(60, my_function).start(),它将在与GUI相同的线程上运行,没有浪费任何不必要的资源。