Python 定期或在触发事件时执行函数

Python 定期或在触发事件时执行函数,python,flask,Python,Flask,我正在编写Python的Flask服务器端代码,其中有一个定期运行并执行函数的后台任务(请注意,“定期”并不是那么强硬,执行一次,然后在x秒后也可以运行)。但我还需要它在服务器收到请求时立即执行相同的功能(然后恢复后台任务) 这让我想起了C中的SELECT系统调用,系统等待超时或直到数据包到达 以下是我在查阅了大量答案后得出的结论 from flask import Flask, request import threading, os, time POOL_TIME = 2 myThrea

我正在编写Python的Flask服务器端代码,其中有一个定期运行并执行函数的后台任务(请注意,“定期”并不是那么强硬,执行一次,然后在x秒后也可以运行)。但我还需要它在服务器收到请求时立即执行相同的功能(然后恢复后台任务)

这让我想起了C中的SELECT系统调用,系统等待超时或直到数据包到达

以下是我在查阅了大量答案后得出的结论

from flask import Flask, request
import threading, os, time

POOL_TIME = 2

myThread = threading.Thread()

def pollAndExecute(a='|'):
    time.sleep(1)
    print(time.time(), a)
    # time.sleep(1)
    myThread = threading.Timer(POOL_TIME, pollAndExecute)
    myThread.start() 

def startWork():
    global myThread
    myThread = threading.Timer(POOL_TIME, pollAndExecute)
    myThread.start()

app = Flask(__name__)

@app.route('/ping', methods=['POST'])
def ping():
    global myThread
    myThread.cancel()
    pollAndExecute("@")
    return "Hello"

if __name__ == '__main__':
    app.secret_key = os.urandom(12)
    startWork()
    app.run(port=5001)
输出:

但是输出清楚地表明,在出现请求(使用
curl-xpost发送)后,它的行为不正常http://localhost:5001/ping


请指导我如何纠正这一点,或者是否有其他方法可以做到这一点。仅供参考,在原始代码中,pollAndExecute()中也有各种数据库更新,我需要注意轮询和ping之间没有竞争条件。不用说,在特定的时间只应该执行函数的一个副本(最好是在单个线程中)

这是我为你的问题制定的解决方案。我使用了一个优先级队列,它接收要使用
printTime
函数运行的数据。后台和flask函数是两个不同的线程,它们将数据推送到优先级队列中,这将使flask调用优先于后台调用。请注意,它现在是如何等待当前线程完成,然后再执行另一个线程的

from flask import Flask, request
import threading, os, time

from threading import Thread, Lock
from queue import PriorityQueue

POOL_TIME = 2

lock = Lock()

def printTime(a='|'):
    time.sleep(1) # Simulate process taking 1 sec
    print(time.time(), a)

jobs = PriorityQueue()

class Queue(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.daemon = True
        self.start()
    def run(self):
        while True:
            _, data = jobs.get()
            printTime(data)


class backGroundProcess(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.daemon = True
        self.start()
    def run(self):
        while True:
            time.sleep(2) # Background process enqueues a job every 2 secs
            jobs.put((0,"|"))

class flaskProcess(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.start()
    def run(self):
        jobs.put((1,"@"))


app = Flask(__name__)

@app.route('/ping', methods=['POST'])
def ping():
    flaskThread = flaskProcess()
    return "Hello"

if __name__ == '__main__':
    backGroundProcess()
    Queue()
    app.secret_key = os.urandom(12)
    app.run(port=5001)

上面的代码片段可能有点冗长,因为我使用了类,但这应该让您开始学习。

您能解释一下输出是如何出错的吗?在我看来这很好。@gkhnavarro The pollAndExecute()至少需要1秒才能运行。因此,函数连续执行之间的时间间隔至少应为1秒。但请查看请求后的连续时间。它们相隔约0.5秒。