apscheduler 不会删除作业
apscheduler does not remove job
我是 python 的初学者,在我的 tkinter 中,我有一个选项菜单,总共有 4 个选项。
选项菜单
# 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 作业开始 运行ning,即使我切换到另一个应该删除作业的选项,它也不会停止。它堆叠了工作。因此,如果我 select 5 seconds
选项,它通常会 运行。但是,如果我切换到 10 seconds
选项,它将 运行 10 seconds
选项置于 5 seconds
选项之上。由于两个选项使用相同的功能,所以当 5 秒和 10 秒彼此重合时,它会给我两次相同的结果。
无论是否使用作业 ID,我都试过了,结果都一样。
这些是结果
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]
我的代码(可能是所有代码)有什么问题,如何按预期将其设置为 运行?
job
永远不会在 locals()
中,因为它是一个局部变量,并且您在设置之前正在检查它。当函数 returns 时,所有局部变量都被取消设置,因此下次调用该函数时它会再次被取消设置。
由于您似乎在使用 classes,因此您应该使用 class 变量,并将其初始化为 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()
我是 python 的初学者,在我的 tkinter 中,我有一个选项菜单,总共有 4 个选项。
选项菜单
# 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 作业开始 运行ning,即使我切换到另一个应该删除作业的选项,它也不会停止。它堆叠了工作。因此,如果我 select 5 seconds
选项,它通常会 运行。但是,如果我切换到 10 seconds
选项,它将 运行 10 seconds
选项置于 5 seconds
选项之上。由于两个选项使用相同的功能,所以当 5 秒和 10 秒彼此重合时,它会给我两次相同的结果。
无论是否使用作业 ID,我都试过了,结果都一样。
这些是结果
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]
我的代码(可能是所有代码)有什么问题,如何按预期将其设置为 运行?
job
永远不会在 locals()
中,因为它是一个局部变量,并且您在设置之前正在检查它。当函数 returns 时,所有局部变量都被取消设置,因此下次调用该函数时它会再次被取消设置。
由于您似乎在使用 classes,因此您应该使用 class 变量,并将其初始化为 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()