Reputation: 53993
I've got a function which gets and stores something from an exchange every minute. I run the functions using the (normally excellent) APScheduler. Unfortunately, when I add cron jobs from a loop, it doesn't seem to work as I expect it to.
I've got a little list with a couple strings, for which I want to run the getAndStore function. I could do this like so:
from apscheduler.scheduler import Scheduler
apsched = Scheduler()
apsched.start()
apsched.add_cron_job(lambda: getAndStore('A'), minute='0-59')
apsched.add_cron_job(lambda: getAndStore('B'), minute='0-59')
apsched.add_cron_job(lambda: getAndStore('C'), minute='0-59')
This works fine, but since I'm a programmer and I love to automate stuff, I do this:
from apscheduler.scheduler import Scheduler
def getAndStore(apiCall):
# does a call to the api using apiCall as a value
# and stores it in the DB.
print apiCall
apiCalls = ['A', 'B', 'C']
apsched = Scheduler()
apsched.start()
for apiCall in apiCalls:
print 'Start cron for: ', apiCall
apsched.add_cron_job(lambda: getAndStore(apiCall), minute='0-59')
When I run this, the output is the following:
Start cron for: A
Start cron for: B
Start cron for: C
C
C
C
The strange thing is that it appears to start it for A, B and C, but it actually starts a cron for C three times. Is this a bug in APScheduler? Or am I doing something wrong here?
All tips are welcome!
Upvotes: 2
Views: 2280
Reputation: 44
This worked for me:
for apiCall in apiCalls:
print 'Start cron for: ', apiCall
action = lambda x = apiCall: getAndStore(x)
apsched.add_cron_job(action , minute='0-59')
Upvotes: -1
Reputation: 66
This annoyed me for a while until I finally figured it out. So much so, I created a stackoverflow account after years of lurking. First post!
Try dropping the lambda (I know..., I went down that route too) and pass the arguments via args as a tuple. I've used a slightly different scheduler below, but it should be easily adapted.
from apscheduler.schedulers.background import BackgroundScheduler
import time
def getAndStore(apiCall):
# does a call to the api using apiCall as a value
# and stores it in the DB.
print(apiCall)
apiCalls = ['A', 'B', 'C']
apsched = BackgroundScheduler()
apsched.start()
for apiCall in apiCalls:
print ('Start cron for: ' + apiCall)
apsched.add_job(getAndStore, args=(apiCall,), trigger='interval', seconds=1)
# to test
while True:
time.sleep(2)
Output is:
Start cron for: A
Start cron for: B
Start cron for: C
B
A
C
Upvotes: 5