我正在执行实时数据处理+显示,并且每隔60秒就会访问我们的数据库。我不想使用time.sleep()每隔60秒等待一次,因为它取消了对我的控制(即REPL访问变量,这不是必须的,但很好),并冻结matplotlib图表。
有没有别的选择?理想情况下,最初将控制权交给用户,60秒后,取消控制权,运行一些代码,更新绘图,然后将控制权交还给用户。(当我说控制时,我是指REPL控制)。
有什么想法吗?
发布于 2013-03-02 05:43:26
如果不需要取消用户控制,有一种非常简单的方法:创建一个threading.Timer。
您想要做的是获取函数的“延续”-即,在time.sleep-and之后的所有内容都将其移动到一个单独的函数my_function中,然后像这样调度它:
threading.Timer(60, my_function).start()在my_function的末尾,它使用完全相同的代码行调度一个新的Timer。
Timer是一个相当笨重的接口和实现,但它内置于stdlib中。你可以在ActiveState上找到食谱,在PyPI上找到模块,它们提供了更好的类,例如,在一个线程上运行多个计时器而不是每个计时器一个线程,让你计划循环调用,这样你就不必一直重新安排自己,等等。但是对于每60秒运行一次的东西,我认为你可以使用Timer。
要记住的一件事是:如果后台作业需要处理用户在REPL中处理的任何相同数据,则存在竞争条件的可能性。通常在交互式环境中(多亏了GIL,尤其是在Python中),您只需将责任放在用户身上,就不会引起任何竞争。如果没有,您将需要某种类型的同步。
另一件要记住的事情是:如果你正在尝试做图形用户界面的工作,取决于你正在使用的图形用户界面(我相信matplotlib是可配置的,但是默认是tkinter?),你可能无法从后台线程更新图形用户界面。
但在这种情况下,实际上有一个更好的解决方案。GUI程序有一个在某个线程或其他线程中运行的事件循环,并且几乎每个设计过的事件循环都有一种在该线程中调度计时器的方法。对于tkinter,如果您有root对象的句柄,只需调用root.after(60000, my_function)而不是threading.Timer(60, my_function).start(),它将在与图形用户界面相同的线程上运行,并且不会浪费任何不必要的资源。
https://stackoverflow.com/questions/15167334
复制相似问题