如何在 Python 中实现非阻塞无限循环
How to implement non-blocking infinite loop in Python
我有一个从网络摄像头读取视频帧的无限循环,每一帧都会经过一个需要高计算能力的复杂函数。因此,当显示帧时,程序会因为阻塞代码而感觉有点滞后。
我现在打算做的是,
- 只收集目标对象出现时的前几帧
- 将它们放在一个单独的线程中以避免代码阻塞。
我测量了网络摄像头每秒捕获的帧数,即约 28 帧。所以每秒while循环只会收集前5帧并在另一个线程中处理所有帧,并且return所有5个函数完成后的结果。
我已经尝试使用 'Pool' 和 'Queue' 但无法正常工作,循环仍然被阻塞。下面的代码模糊地代表了我的程序现在的样子,我回家后会编辑它,现在使用 phone 到 post。
def detect(frame):
# detect target object from images
pass
def nn(frame):
# some heavy processing code
pass
count = 0
stack = []
while True:
frame = cv2.imread(0)
detected = detect(frame)
# stop collecting images when collected 5
if detected and count <= 5:
stack.append(frame)
count += 1
# start processing
if len(stack) == 5:
p = Pool(4)
results = p.map(nn, frame)
p.close()
p.join()
# reset
stack = []
count = 0
我的概念正确吗?或者我需要做其他事情,比如协程?
我使用 rq.
解决了这个问题
python 的简单消息队列。
首先,你需要运行异步执行方法。
它将 运行 你的 nn
功能,在这种情况下,
然后,为消息队列设置一个简单的配置,
我使用 redis 包中的 connectionPool。
基本上,您将整个任务发送到由 rq worker 执行的并行进程。
def nn(frame):
# some heavy processing code
pass
def asynch_call(frame):
p = Pool(4)
results = p.map(nn, frame)
p.close()
p.join()
pool = redis.ConnectionPool(
host=HOST,
port=PORT,
password=PASS,
db=0)
r = redis.Redis(connection_pool=pool)
q = Queue('nn_queue', connection=r)
count = 0
stack = []
while True:
frame = cv2.imread(0)
detected = detect(frame)
# stop collecting images when collected 5
if detected and count <= 5:
stack.append(frame)
count += 1
# start processing
if len(stack) == 5:
job = q.enqueue(asynch_call, frame, timeout=any_long_timeout )
if job.status=='queued':
print("Job submission ok")
# reset
stack = []
count = 0
为了启动一个处理异步调用的 worker,您有几个选择,为 Worker 创建您自己的代码,或者只是 运行 在单独的终端中执行以下命令:
rq worker nn_queue
查看带有上面用于发送作业的队列名称的命令。
希望对你有帮助。
我有一个从网络摄像头读取视频帧的无限循环,每一帧都会经过一个需要高计算能力的复杂函数。因此,当显示帧时,程序会因为阻塞代码而感觉有点滞后。
我现在打算做的是,
- 只收集目标对象出现时的前几帧
- 将它们放在一个单独的线程中以避免代码阻塞。
我测量了网络摄像头每秒捕获的帧数,即约 28 帧。所以每秒while循环只会收集前5帧并在另一个线程中处理所有帧,并且return所有5个函数完成后的结果。
我已经尝试使用 'Pool' 和 'Queue' 但无法正常工作,循环仍然被阻塞。下面的代码模糊地代表了我的程序现在的样子,我回家后会编辑它,现在使用 phone 到 post。
def detect(frame):
# detect target object from images
pass
def nn(frame):
# some heavy processing code
pass
count = 0
stack = []
while True:
frame = cv2.imread(0)
detected = detect(frame)
# stop collecting images when collected 5
if detected and count <= 5:
stack.append(frame)
count += 1
# start processing
if len(stack) == 5:
p = Pool(4)
results = p.map(nn, frame)
p.close()
p.join()
# reset
stack = []
count = 0
我的概念正确吗?或者我需要做其他事情,比如协程?
我使用 rq.
解决了这个问题
python 的简单消息队列。
首先,你需要运行异步执行方法。
它将 运行 你的 nn
功能,在这种情况下,
然后,为消息队列设置一个简单的配置,
我使用 redis 包中的 connectionPool。
基本上,您将整个任务发送到由 rq worker 执行的并行进程。
def nn(frame):
# some heavy processing code
pass
def asynch_call(frame):
p = Pool(4)
results = p.map(nn, frame)
p.close()
p.join()
pool = redis.ConnectionPool(
host=HOST,
port=PORT,
password=PASS,
db=0)
r = redis.Redis(connection_pool=pool)
q = Queue('nn_queue', connection=r)
count = 0
stack = []
while True:
frame = cv2.imread(0)
detected = detect(frame)
# stop collecting images when collected 5
if detected and count <= 5:
stack.append(frame)
count += 1
# start processing
if len(stack) == 5:
job = q.enqueue(asynch_call, frame, timeout=any_long_timeout )
if job.status=='queued':
print("Job submission ok")
# reset
stack = []
count = 0
为了启动一个处理异步调用的 worker,您有几个选择,为 Worker 创建您自己的代码,或者只是 运行 在单独的终端中执行以下命令:
rq worker nn_queue
查看带有上面用于发送作业的队列名称的命令。
希望对你有帮助。