如何在使用 python 调度模块与共享作业队列并行执行作业时传递参数
How to pass arguments when execute jobs in parallel with a shared job queue using python schedule module
我打算 运行 并行执行多个作业并按照示例 here 使用作业队列,但它执行了一次并在我尝试传递参数时引发了异常 'NoneType' object is not callable
.下面列出的代码:
import Queue
import schedule
import threading
import time
def job(arg):
print 'Argument is %s' % arg
def worker_main():
while True:
try:
job_func = jobqueue.get()
job_func()
except Exception as e:
print e
jobqueue = Queue.Queue()
schedule.every(2).seconds.do(jobqueue.put, job(1))
schedule.every(2).seconds.do(jobqueue.put, job(2))
worker_thread = threading.Thread(target=worker_main)
worker_thread.start()
while True:
try:
schedule.run_pending()
time.sleep(1)
except Exception as e:
print e
sys.exit()
输出为:
Arg is 1
Arg is 2
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
...
有解决这个问题的想法吗?
原因是 schedule.every(2).seconds.do(jobqueue.put, job(1))
中传递给 do
方法的参数实际上是 None
.
因为代码正在调用 job
函数并将 1(和 2)作为参数传递给 job
。因此 job
函数的 return 值(它是 None
因为它只是打印)作为第二个参数传递给 do
方法调用。因此,作业队列中存储的不是函数引用,而是 None
实例。
将参数传递给作业的问题是 schedule
包中的 do
方法可以接受额外的作业参数 运行,但是正在安排什么,就是把作业放到队列中,队列项只是函数引用,没有额外的参数。
一个解决方案是将作业与它们的参数一起放入队列。然后工作人员需要获取它们并通过将参数传递给它来调用作业。像这样:
import Queue
import schedule
import threading
import time
def job(arg):
print 'Argument is %s' % arg
def worker_main():
while True:
try:
job_func, job_args = jobqueue.get()
job_func(*job_args)
except Exception as e:
print e
jobqueue = Queue.Queue()
schedule.every(2).seconds.do(jobqueue.put, (job, [1]))
schedule.every(2).seconds.do(jobqueue.put, (job, [2]))
worker_thread = threading.Thread(target=worker_main)
worker_thread.start()
while True:
try:
schedule.run_pending()
time.sleep(1)
except Exception as e:
print e
sys.exit()
在这里,我们将作业函数引用的元组和参数列表放入队列。
然后工作人员将获取它们,并将参数列表传递给作业函数。
另一种解决方案是将作业(job(1)
和 job(2)
调用)包装在不需要参数的其他函数中,然后将这些函数注册到作业队列中,如下所示:
def job1():
job(1)
def job2():
job(2)
jobqueue = Queue.Queue()
schedule.every(2).seconds.do(jobqueue.put, job1)
schedule.every(2).seconds.do(jobqueue.put, job2)
我打算 运行 并行执行多个作业并按照示例 here 使用作业队列,但它执行了一次并在我尝试传递参数时引发了异常 'NoneType' object is not callable
.下面列出的代码:
import Queue
import schedule
import threading
import time
def job(arg):
print 'Argument is %s' % arg
def worker_main():
while True:
try:
job_func = jobqueue.get()
job_func()
except Exception as e:
print e
jobqueue = Queue.Queue()
schedule.every(2).seconds.do(jobqueue.put, job(1))
schedule.every(2).seconds.do(jobqueue.put, job(2))
worker_thread = threading.Thread(target=worker_main)
worker_thread.start()
while True:
try:
schedule.run_pending()
time.sleep(1)
except Exception as e:
print e
sys.exit()
输出为:
Arg is 1
Arg is 2
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
'NoneType' object is not callable
...
有解决这个问题的想法吗?
原因是 schedule.every(2).seconds.do(jobqueue.put, job(1))
中传递给 do
方法的参数实际上是 None
.
因为代码正在调用 job
函数并将 1(和 2)作为参数传递给 job
。因此 job
函数的 return 值(它是 None
因为它只是打印)作为第二个参数传递给 do
方法调用。因此,作业队列中存储的不是函数引用,而是 None
实例。
将参数传递给作业的问题是 schedule
包中的 do
方法可以接受额外的作业参数 运行,但是正在安排什么,就是把作业放到队列中,队列项只是函数引用,没有额外的参数。
一个解决方案是将作业与它们的参数一起放入队列。然后工作人员需要获取它们并通过将参数传递给它来调用作业。像这样:
import Queue
import schedule
import threading
import time
def job(arg):
print 'Argument is %s' % arg
def worker_main():
while True:
try:
job_func, job_args = jobqueue.get()
job_func(*job_args)
except Exception as e:
print e
jobqueue = Queue.Queue()
schedule.every(2).seconds.do(jobqueue.put, (job, [1]))
schedule.every(2).seconds.do(jobqueue.put, (job, [2]))
worker_thread = threading.Thread(target=worker_main)
worker_thread.start()
while True:
try:
schedule.run_pending()
time.sleep(1)
except Exception as e:
print e
sys.exit()
在这里,我们将作业函数引用的元组和参数列表放入队列。 然后工作人员将获取它们,并将参数列表传递给作业函数。
另一种解决方案是将作业(job(1)
和 job(2)
调用)包装在不需要参数的其他函数中,然后将这些函数注册到作业队列中,如下所示:
def job1():
job(1)
def job2():
job(2)
jobqueue = Queue.Queue()
schedule.every(2).seconds.do(jobqueue.put, job1)
schedule.every(2).seconds.do(jobqueue.put, job2)