【问题标题】:How to pass arguments when execute jobs in parallel with a shared job queue using python schedule module使用python schedule模块与共享作业队列并行执行作业时如何传递参数
【发布时间】:2016-08-09 20:57:27
【问题描述】:

我打算并行运行多个作业,并使用作业队列遵循示例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
...

有解决这个问题的想法吗?

【问题讨论】:

    标签: python python-2.7 queue scheduled-tasks scheduler


    【解决方案1】:

    原因是schedule.every(2).seconds.do(jobqueue.put, job(1))中传递给do方法的参数实际上是None

    因为代码调用job 函数并将1(和2)作为参数传递给job。所以job 函数的返回值(它是None,因为它只是打印)作为第二个参数传递给do 方法调用。因此,作业队列中存储的不是函数引用,而是 None 实例。

    将参数传递给作业的问题是 do 包中的 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)
    

    【讨论】:

    • 这将引发job() takes exactly 1 argument (0 given) 异常,我认为参数已传递给do 函数,我需要将它传递给函数job
    • 没错,我没有注意到正在调度的函数,不是job,而是将作业放入队列中。我更新了答案。
    猜你喜欢
    • 2016-09-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    相关资源
    最近更新 更多