apscheduler不会删除工作

问题描述 投票:0回答:1

我是python的初学者,在我的tkinter中,我有一个共4个选项的选项菜单。

Option Menu

# create tk variable
self.timervar = tk.StringVar(root)

# dropdown dictionary
self.timerDict = {"-", "5 seconds", "10 seconds", "15 seconds"}
self.timervar.set("-")  # <-- set the default value

# timer dropdown menu
self.timer_option = tk.OptionMenu(root, self.timervar, *self.timerDict, command=self.req_timer)
self.timer_option.grid(row=1, column=3, columnspan=2, padx=3, pady=3)

根据该选项,函数将每隔x分钟运行一次。当我切换到另一个选项时,该函数的apscheduler作业将被删除,并且将启动一个新作业。

apscheduler

def req_timer(self, option):

    scheduler = apscheduler.schedulers.background.BackgroundScheduler()

    if option == "15 minutes":
        if 'job' in locals():
            job.remove_job('option_timer')
            job = scheduler.add_job(self.req_client, 'cron', second='*/15', id='option_timer')
            scheduler.start()
        else:
            job = scheduler.add_job(self.req_client, 'cron', second='*/15', id='option_timer')
            scheduler.start()

    elif option == "10 minutes":
        if 'job' in locals():
            job.remove_job('option_timer')
            job = scheduler.add_job(self.req_client, 'cron', second='*/10', id='option_timer')
            scheduler.start()
        else:
            job = scheduler.add_job(self.req_client, 'cron', second='*/10', id='option_timer')
            scheduler.start()

    elif option == "5 minutes":
        if 'job' in locals():
            job.remove_job('option_timer')
            job = scheduler.add_job(self.req_client, 'cron', second='*/5', id='option_timer')
            scheduler.start()
        else:
            job = scheduler.add_job(self.req_client, 'cron', second='*/5', id='option_timer')
            scheduler.start()

    elif option == "-":
        if 'job' in locals():
            job.remove_job('option_timer')
        else:
            pass

但是在我的情况下,一旦apscheduler作业开始运行,即使我切换到应该删除了该作业的其他选项,它也不会停止。它堆积了工作。因此,如果我选择5 seconds选项,它将正常运行。但是如果我切换到10 seconds选项,它将在10 seconds选项之上运行5 seconds选项。由于两个选项都使用相同的功能,因此当5和10秒相互重合时,它会给我两次相同的结果。

我已经尝试了这个有和没有工作ID和相同的结果。

These are the results

Connecting to port...  # <-- 5 seconds option
Successfully connected to port 9998
Successfully connected to port 9999
Sending request  1 ...
Received reply  1 [ Sensor: 6 :: Data: 123456789 :: Client: 9100 ]
Sending request  2 ...
Received reply  2 [ Sensor: 7 :: Data: 987654321 :: Client: 9101 ]
Connecting to port...  # <-- at this point, the 10 seconds option was selected
Successfully connected to port 9998
Successfully connected to port 9999
Sending request  1 ...
Connecting to port...
Successfully connected to port 9998
Successfully connected to port 9999
Sending request  1 ...
Received reply  1 [ Sensor: 6 :: Data: 123456789 :: Client: 9100 ]
Sending request  2 ...
Received reply  1 [ Sensor: 6 :: Data: 123456789 :: Client: 9100 ]
Sending request  2 ...
Received reply  2 [ Sensor: 7 :: Data: 987654321 :: Client: 9101 ]
Received reply  2 [ Sensor: 7 :: Data: 987654321 :: Client: 9101 ]
Connecting to port...
Successfully connected to port 9998
Successfully connected to port 9999
Sending request  1 ...
Received reply  1 [ Sensor: 6 :: Data: 123456789 :: Client: 9100 ]  # <-- closed tkinter window
Execution of job "MainApplication.req_client (trigger: cron[second='*/5'], next run at: 2017-12-29 16:34:30 +08)" skipped: maximum number of running instances reached (1)
Execution of job "MainApplication.req_client (trigger: cron[second='*/5'], next run at: 2017-12-29 16:34:35 +08)" skipped: maximum number of running instances reached (1)
[Cancelled]

我的代码(可能是一切)有什么问题,如何让它按预期运行?

python python-3.x tkinter apscheduler
1个回答
2
投票

job永远不会出现在locals()中,因为它是一个局部变量,你在设置之前就检查它了。当函数返回时,所有局部变量都未设置,因此下次调用该函数时,它将再次被取消设置。

由于您似乎在使用类,因此应使用类变量,并将其初始化为None

class Whatever():
    def __init__(self, ...):
        self.job = None
        ...
    def req_timer(self, option=None):
        if self.job is not None:
            ...

此外,您还有许多可以删除的重复代码。例如,您可能需要考虑重写此函数以减少复制:

def req_timer(self, option):

    seconds_map = {
        "15 minutes": "*/15",
        "10 minutes": "*/10",
        "5 minutes": "*/5",
        "-": None,
    }

    scheduler = apscheduler.schedulers.background.BackgroundScheduler()

    if self.job is not None:
        self.job.remove_job('option_timer')
        self.job = None

    seconds = seconds_map.get(option, None)
    if seconds is not None:
        self.job = scheduler.add_job(self.req_client, 'cron',
                                     second=seconds,
                                     id='option_timer')
        scheduler.start()
© www.soinside.com 2019 - 2024. All rights reserved.