python中的延迟函数

python中的延迟函数,python,multithreading,setinterval,Python,Multithreading,Setinterval,在JavaScript中,我习惯于调用稍后执行的函数,如下所示 function foo() { alert('bar'); } setTimeout(foo, 1000); 这不会阻止其他代码的执行 我不知道如何在Python中实现类似的功能。我需要睡眠 import time def foo(): print('bar') time.sleep(1) foo() 但这将阻止其他代码的执行。(实际上,在我的例子中,阻止Python本身不会是一个问题,但我无法对该方法进行

在JavaScript中,我习惯于调用稍后执行的函数,如下所示

function foo() {
    alert('bar');
}

setTimeout(foo, 1000);
这不会阻止其他代码的执行

我不知道如何在Python中实现类似的功能。我需要睡眠

import time
def foo():
    print('bar')

time.sleep(1)
foo()
但这将阻止其他代码的执行。(实际上,在我的例子中,阻止Python本身不会是一个问题,但我无法对该方法进行单元测试。)

我知道线程是为不同步执行而设计的,但我想知道是否存在类似于
setTimeout
setInterval
的更简单的方法。

您想要模块中的对象

如果您想重复,这里有一个简单的解决方案:不要使用
定时器
,只需使用
线程
,而是向其传递一个类似以下的函数:

def call_delay(delay, repetitions, func, *args, **kwargs):             
    for i in range(repetitions):    
        sleep(delay)
        func(*args, *kwargs)

这样做不会产生无限循环,因为如果做得不好,可能会导致线程不会死亡和其他不愉快的行为。更复杂的方法可能使用基于
事件的方法

JavaScript可以做到这一点,因为它在事件循环中运行。这可以在Python中通过使用Twisted之类的事件循环或GLib或Qt之类的工具箱来完成。

像Javascript的
setTimeout
之类的异步回调需要事件驱动的体系结构

Python的异步框架(如流行的Python)可以满足您的需求,但这意味着在应用程序中采用事件驱动的体系结构


另一种选择是使用线程并在线程中休眠。Python提供了一个简化等待部分的方法。但是,当线程唤醒并执行函数时,它位于一个单独的线程中,必须以线程安全的方式执行任何操作。

问题在于普通python脚本没有在框架中运行。脚本被调用并控制主循环。使用JavaScript,页面上运行的所有脚本都在一个框架中运行,当超时时间过去时,框架将调用您的方法


我还没有使用PyQT自己(只有C++ QT),但是可以使用SqrimItter()在任何QObjt上设置定时器。当计时器过期时,将调用方法上的回调。您还可以使用QTimer并将超时信号连接到任意插槽。这是可能的,因为Qt运行一个事件循环,可以在稍后阶段调用您的方法。

要在延迟后执行函数或使用事件循环(无线程)在给定的秒数内重复函数,您可以:

编程
#/usr/bin/env python
从Tkinter导入Tk
def foo():
打印(“计时器关闭!”)
def倒计时(n、bps、根):
如果n==0:
root.destroy()#退出主循环
其他:
打印(n)
root.after(1000/bps,倒计时,n-1,bps,root)#重复呼叫
root=Tk()
root.draw()#不显示GUI窗口
root.after(4000,foo)#在4秒内调用foo()
root.在(0,倒计时,10,2,root)之后#表明我们还活着
root.mainloop()
打印(“完成”)
输出
10
9
8.
7.
6.
5.
4.
3.
计时器响了!
2.
1.
完成
Gtk
#/usr/bin/env python
从gi.repository导入GObject,Gtk
def foo():
打印(“计时器关闭!”)
def倒计时(n):#注意:此处可以使用闭包
如果n[0]==0:
Gtk.main_quit()#退出mainloop
其他:
打印(n[0])
n[0]=1
返回True#重复调用
GObject.timeout_add(4000,foo)#在4秒内调用foo()
GObject.timeout\u add(500,倒计时,[10])
Gtk.main()
打印(“完成”)
输出
10
9
8.
7.
6.
5.
4.
计时器响了!
3.
2.
1.
完成
扭曲的
#/usr/bin/env python
从twisted.internet导入
从twisted.internet.task导入循环调用
def foo():
打印(“计时器关闭!”)
def倒计时(n):
如果n[0]==0:
反应堆停止()#退出主回路
其他:
打印(n[0])
n[0]=1
reactor.callLater(4,foo)#在4秒内调用foo()
循环调用(倒计时[10])。开始(.5)#在.5秒内重复调用
反应堆运行()
打印(“完成”)
输出
10
9
8.
7.
6.
5.
4.
3.
计时器响了!
2.
1.
完成
异步 Python 3.4为异步IO引入了新功能--:

#/usr/bin/env蟒蛇3.4
导入异步
def foo():
打印(“计时器关闭!”)
def倒计时(n):
如果n[0]==0:
循环。停止()#结束循环。永远运行()
其他:
打印(n[0])
n[0]=1
def法兰(启动=0,停止=无,步骤=1):
当停止为无或开始<停止:
产量起点
开始+=步骤#注:随着时间的推移,精度会降低
def call_every(循环,秒,func,*args,now=True):
def repeat(现在=True,时间=frange(loop.time()+秒,无,秒)):
如果现在:
func(*args)
循环。在(下一个(次)呼叫_,重复)
重复(现在=现在)
loop=asyncio.get\u event\u loop()
loop.call_later(4,foo)#在4秒内调用foo()
每(循环,0.5,倒计时,[10])呼叫一次#每.5秒重复一次呼叫
loop.run_forever()
loop.close()
打印(“完成”)
输出
10
9
8.
7.
6.
5.
4.
3.
计时器响了!
2.
1.
完成
注意:这些方法在界面和行为上略有不同。

对不起,我不能发布超过2个链接,因此有关更多信息,请查看PEP 380,最重要的是查看的文档

# asyncio is in standard lib for latest python releases (since 3.3)
import asyncio

# there's only one event loop, let's fetch that
loop = asyncio.get_event_loop()

# this is a simple reminder that we're dealing with a coro
@asyncio.coroutine
def f():
    for x in range(10):
        print(x)
        # we return with a coroutine-object from the function, 
        # saving the state of the execution to return to this point later
        # in this case it's a special sleep
        yield from asyncio.sleep(3)

# one of a few ways to insert one-off function calls into the event loop
loop.call_later(10, print, "ding!")
# we insert the above function to run until the coro-object from f is exhausted and 
# raises a StopIteration (which happens when the function would return normally)
# this also stops the loop and cleans up - keep in mind, it's not DEAD but can be restarted
loop.run_until_complete(f())
# this closes the loop - now it's DEAD
loop.close()
异步IO是解决此类问题的首选方案,除非您坚持使用线程或多处理。它由GvR以“郁金香”的名义设计和实施。它由GvR于上引入,旨在成为一个事件循环,以规范(和标准化)所有事件循环(如twisted、gevent等中的事件循环),并使它们彼此兼容。asyncio之前已经提到过,但是asyncio的真正威力是通过的收益释放出来的

# asyncio is in standard lib for latest python releases (since 3.3)
import asyncio

# there's only one event loop, let's fetch that
loop = asyncio.get_event_loop()

# this is a simple reminder that we're dealing with a coro
@asyncio.coroutine
def f():
    for x in range(10):
        print(x)
        # we return with a coroutine-object from the function, 
        # saving the state of the execution to return to this point later
        # in this case it's a special sleep
        yield from asyncio.sleep(3)

# one of a few ways to insert one-off function calls into the event loop
loop.call_later(10, print, "ding!")
# we insert the above function to run until the coro-object from f is exhausted and 
# raises a StopIteration (which happens when the function would return normally)
# this also stops the loop and cleans up - keep in mind, it's not DEAD but can be restarted
loop.run_until_complete(f())
# this closes the loop - now it's DEAD
loop.close()
================

>>> 
0
1
2
3
ding!
4
5
6
7
8
9
>>>

让我换一种。如果我想像在
setInterval
中那样每隔x秒重复一次呼叫,该怎么办?我可以让函数