First of all, I checked this question in order to make sure that I have no duplicates.
I have a singleton class that has 2 internal methods that I want to trigger via a public method.
Each method should be run in a background job scheduled by a BackgroundScheduler
.
Each method has a different interval.
Here is the code:
import inspect
import threading
import structlog
from apscheduler.schedulers.background import BackgroundScheduler
from typing import Optional, Iterator, Callable
SCAN_A_INTERVAL: int = 30
SCAN_B_INTERVAL: int = 10
scheduler = BackgroundScheduler()
class Scanner:
__instance: Optional["Scanner"] = None
def __init__(self):
self.__logger = structlog.get_logger()
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super(Scanner, cls).__new__(cls)
return cls.__instance
@scheduler.scheduled_job("interval", seconds=SCAN_A_INTERVAL)
def _scan_a(self):
print("I'm in a")
@scheduler.scheduled_job("interval", seconds=SCAN_B_INTERVAL)
def _scan_b(self):
print("I'm in b")
def scan_all(self):
scan_methods: Iterator[Callable] = (
tup[1] for tup in inspect.getmembers(self, inspect.ismethod)
if tup[0].startswith("_scan_")
)
for method in scan_methods:
threading.Thread(target=method, daemon=True).start() # We want the method to starts manually the first time
scheduler.start()
if __name__ == '__main__':
Scanner().scan_all()
# Flask application running so the main thread doesn't die
When running this I get the following error:
File "full_path/scanner/scanner.py", line 44, in <module>
class Scanner:
File "full_path/scanner/scanner.py", line 64, in Scanner
def _scan_a(self):
File "full_path/virtualenvs/repo/lib/python3.8/site-packages/apscheduler/schedulers/base.py", line 470, in inner
self.add_job(func, trigger, args, kwargs, id, name, misfire_grace_time, coalesce,
File "full_path/virtualenvs/repo/lib/python3.8/site-packages/apscheduler/schedulers/base.py", line 438, in add_job
job = Job(self, **job_kwargs)
File "full_path/virtualenvs/repo/lib/python3.8/site-packages/apscheduler/job.py", line 49, in __init__
self._modify(id=id or uuid4().hex, **kwargs)
File "full_path/virtualenvs/repo/lib/python3.8/site-packages/apscheduler/job.py", line 180, in _modify
check_callable_args(func, args, kwargs)
File "full_path/virtualenvs/repo/lib/python3.8/site-packages/apscheduler/util.py", line 399, in check_callable_args
raise ValueError('The following arguments have not been supplied: %s' %
ValueError: The following arguments have not been supplied: self
What I tried: When adding the jobs manually in a loop (
for method in scan_methods:
scheduler.add_job(method, "interval", seconds=<accordingly>)
), The code runs perfectly. I want to use the decorated function and not add the job manually.
Thank you!