我是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作业将被删除,并且将开始一个新作业。
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但结果相同。
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]
我的代码(可能是所有内容)出了什么问题,如何让它按预期运行?
答案 0 :(得分: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()