原实现方案
在task.py
设计一个类Reservation_Queue
负责管理任务队列,类成员self.queue
是存放任务的队列,self.nowtask
是存放正在执行任务。类方法有self.addsearchtask()
用于产生一个搜索任务到self.queue
队列内,self.__loop()
用于监视queue队列内的内容,self.main()
负责启动self.__loop()
的线程。
# file: task.py
class Reservation_Queue(object):
def __init__(self, maxsize):
self.queue = Queue(maxsize=maxsize) #存放任务的队列
self.nowtask = None #存放正在执行的任务
self.Lock_addtask = threading.Lock()
def addsearchtask(self, queryset): #产生一个任务到queue
result = (False, 'None')
try:
self.Lock_addtask.acquire()
self.queue.put(('search', queryset))
result = (True, '已添加到任务队列!')
except Exception as e:
result = (False, json.dumps(e.args, indent=4))
finally:
print('addsearchtask', self.queue.queue, id(self.queue))
self.Lock_addtask.release()
return result
def __loop(self): #死循环监视self.queue队列里的内容
while True:
print(time.time(), 'task_looping...', self.queue.queue, id(self.queue))
if not self.queue.empty() and self.nowtask is None:
self.nowtask = self.queue.get()
if self.nowtask[0] == 'search':
print('task_search')
time.sleep(0.1)
def main(self): #开启self.__loop线程,实时监视队列任务。
print('task_thread_start')
threading.Thread(daemon=True, target=self.__loop).start()
task_reservation = Reservation_Queue(0)
task_reservation.main()
使用uwsgi部署到服务器
[uwsgi]
chdir = /www/wwwroot/ihgmiddleman/ihgmiddleman
wsgi-file = ihgmiddleman/wsgi.py
processes = 1
threads = 1
pidfile = myuwsgi.pid
master = true #注意这个master=true,就是由它引发的血案
socket = 127.0.0.1:8003
由master=true引发的奇怪现象
先通过执行self.addsearchtask()
后让self.queue
任务队列产生一个任务,并且打印出来addsearchtask deque([('search', <QuerySet [<Reservation: 22247819>]>)]) 140290378282176
,
后面的140290378282176
为self.queue
的地址,通过打印内容,可以看出任务已经成功的put入到self.queue
里面。
!!但是奇怪的事情发生了,在
self.__loop()
死循环内,监视到的self.queue
内容居然是空的,但是打印出来的id(self.queue)
是一致的,也是地址相同140290378282176
,但为什么会出现这一个奇怪的现象。
尝试解决问题
由于我在admin.py
与views.py
开头都同时写上了from reservation.task import task_reservation
,在猜想是否由于两个文件同时import
,导致task_reservation
指向的地址是不同的,于是我对这两个文件分别加入了print('admin.py', id(task_reservation))
和print('views.py', id(task_reservation))
。
# file: admin.py片段
...
from reservation.task import task_reservation
print('admin.py', id(task_reservation))
...
# file: views.py片段
...
from reservation.task import task_reservation
print('views.py', id(task_reservation))
...
但是事实告诉我,这样的写法是没有错误的,
from reservation.task import task_reservation
并不会为task_reservation
重新分配一个新地址,而会直接指向task.py
内task_reservation
的地址:140080990537808
。
"死马当活马"解决问题
排除以上地址问题以后,我把矛头指向了uwsgi的配置文件,随手把master=true
改成master=false
,以上问题竟完美解决!
可以看到执行
self.addsearchtask()
后,跟着后面的task_looping...
的队列内容也被正常的打印出来并且能输出打印task_search
。
问题与疑惑总结
这个问题就这样抱着疑惑解决了,但是为什么
master=true
会引发在线程内访问类成员失败,即访问self.queue
的内容居然是空列表,这个让我百思不得其解。master=false
之后问题竟就完美解决。
如果有知道的小伙伴,能在评论下面回答一下,解答我的疑惑吗??