替代python的time.sleep()

Cam*_*lon 5 python real-time timer matplotlib

我正在进行实时数据处理+显示,我每隔60秒就打到一次数据库.我不想time.sleep()每隔60秒使用一次,因为它会从我身上移除控制(即REPL访问变量,这不是必需但很好)并冻结matplotlib图表.

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

有任何想法吗?

aba*_*ert 8

如果您不需要取消用户控制,那么有一种非常简单的方法:创建一个threading.Timer.

你想要做的是接受函数的"延续" - 也就是说time.sleep,将它移动到一个单独的函数之后的所有内容my_function,然后像这样安排它:

threading.Timer(60, my_function).start()
Run Code Online (Sandbox Code Playgroud)

最后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相同的线程上运行,而不会浪费任何不必要的资源.