我正在处理 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)
Run Code Online (Sandbox Code Playgroud)
输出:
但是输出清楚地表明它在有请求(使用 发送curl -X POST 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)
Run Code Online (Sandbox Code Playgroud)
上面的代码片段可能有点冗长,因为我使用了类,但这应该可以帮助您入门。
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |