【问题标题】:Thread cannot get the item in queue线程无法获取队列中的项目
【发布时间】:2016-07-17 00:24:34
【问题描述】:

有两个相关文件: backend_service.py 和 web_handler.py

在 backend_service.py 中

job_queue = Queue.Queue(5)

def submit_job(job):

    job_queue.put(job)
    logger.info("Enqueue new Job: JobID:%d,queue size:%d" %(job.order_id,job_queue.qsize()))

def handle_photos():
     while True:
       if not job_queue.empty():

            job = job_queue.get_nowait()
            logger.info("---------got job:%d" %job.order_id)

            print "======================I am a task================"
            job_queue.task_done()

        else:
            logger.info("the queue is empty. will sleep 20 seconds:%d..." %job_queue.qsize())

            time.sleep(20)

worker_thread = threading.Thread(target=handle_photos)
worker_thread.setDaemon(True)
worker_thread.start()

在web_handler.py(基于web.py处理http请求的web app,web服务器为uwsgi)

def GET():
    job = Job()
    backend_service.submit_job(job) 

将被调用并且job_queue.qsize 可以在submit_job 函数中返回正确的值。但是线程总是说队列是空的。

看起来线程在web服务状态下无法获取队列的正确状态。虽然我已经使用 unit test 测试了逻辑。它可以正常工作。 你能帮忙看看我哪里错了吗?

【问题讨论】:

  • 传入 web_handler 命名空间的 job_queue 对象在哪里?
  • 这里有一个很好的例子,调用线程时需要传递队列对象。 pymotw.com/2/Queue
  • @dodell , web_handler.py 只依赖 submit_job 函数。并且在函数 submit_job 本身中访问队列。

标签: python multithreading queue


【解决方案1】:

我认为您的问题是您的脚本在线程有机会从队列中收集任何项目之前完成。

backend_service.py 中,您的线程在将任何内容添加到队列之前启动,因此您第一次得到“队列为空...”

web-handler.py 中,我认为发生了什么(尽管我无法确定没有更多代码),导入启动线程和队列的backend_service,调用submit_job(),然后脚本结束,在线程有机会再次查看队列之前结束线程。

如果您在调用 job_submit 后添加延迟,您将看到 handle_photos() 成功从队列中取出项目。我已将您的代码编辑为 MCVE,包括作业提交后的延迟(并且在循环之间仅休眠 2 秒),一切正常:

backend_service.py:

import Queue
import threading
import time

job_queue = Queue.Queue(5)

def submit_job(job):

    job_queue.put(job)
    print("Enqueue new Job: JobID:%d,queue size:%d" %(job.order_id,job_queue.qsize()))

def handle_photos():
    while True:
        if not job_queue.empty():

            job = job_queue.get_nowait()
            print("---------got job:%d" %job.order_id)

            print "======================I am a task================"
            job_queue.task_done()
        else:
            print("the queue is empty. will sleep 20 seconds:%d..." %job_queue.qsize())

            time.sleep(2)

worker_thread = threading.Thread(target=handle_photos)
worker_thread.setDaemon(True)
worker_thread.start()

web_handler.py:

import backend_service
import time

class a():
    def __init__(self,order_id):
        self.order_id = order_id

for i in range(3):
    job = a(i)
    backend_service.submit_job(job)

time.sleep(20)

输出:

C:\TestScripts>python web_handler.py
the queue is empty. will sleep 20 seconds:0...Enqueue new Job: JobID:2,queue size:1

Enqueue new Job: JobID:2,queue size:2
Enqueue new Job: JobID:2,queue size:3
---------got job:2
======================I am a task================
---------got job:2
======================I am a task================
---------got job:2
======================I am a task================
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...
the queue is empty. will sleep 20 seconds:0...

【讨论】:

  • 感谢 SiHa 的详细帮助。至于 web_handler.py,我只是简化了它。它是一个基于 web.py 的 Web 请求处理程序。当它收到一个 HttpRequest 时,它会触发 submit_job 函数。此时,您知道线程正在运行并且线程应该结束,只有我们整个 Web 应用程序都关闭了。至于你的测试结果,我也得到了同样的结果。所以我的问题是正在运行的线程总是说队列是空的,而 submit_job 函数可以获得队列的正确状态。
  • 抱歉,问题出现在web uswgi环境下。在像您这样的单元测试脚本中,它们运行良好。我很困惑。
  • 哦。希望你能找到答案。
  • WenJ,问题中提到web uswgi环境!
【解决方案2】:

这是由于新的消费者线程与生产者线程不在同一进程中。

我不确定根本原因,也许是由于 uwsgi?

【讨论】:

    猜你喜欢
    • 2010-09-14
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多