nouseforaname nouseforaname - 24 days ago 5
Python Question

datetime.datetime.now() returns old value

I'm looking up a datastore entry in python by matching dates. What i want is pick the entry for "today" on each day. But for some reason when i upload my code to the gae server it'll work just for one day and on the next day it still returns the same value.

e.g. when i upload my code and execute it on 07-01-2014 it returns the value of 07-01-2014 but the next day on 08-01-2014 it still returns 07-01-2014.

If i redeploy the same code and execute it again it moves on to the 08-01-2014 but will again fail on the next day.

In my development environment it works fine...

Why? Thanks for your help!

class ClosingValueHandler(webapp2.RequestHandler):
def get(self):
sct()


(...)

def sct(from_date=datetime.datetime.now().date()):
value = getValueByDate(from_date)

def getValueByDate(date):

query = "SELECT * FROM Value WHERE date = DATE('%s')" % str(date)
try:
q = db.GqlQuery(query)
value = q.get()

except Exception as e:
logging.error("Could not fetch Value value for date '%s' \n Error message: %s \n" % (str(date), str(e)))
return

return value

Answer

As @blackbullet4749 mentions, it's this bit of the code causing you problems:

def sct(from_date=datetime.datetime.now().date()):
    value = getValueByDate(from_date)

Specifically, you're expecting this code to run datetime.datetime.now().date() every time you call the function.

What actually happens is that datetime.datetime.now().date() is run once, not when the function is called, but when it is first defined - which is to say, when the function object is instantiated. When executing your code, Python actually runs those lines of code and creates a function object that exists just like any other object. The default parameters live in a tuple assigned as an attribute of the function object.

To see this for yourself, try this:

def sct(from_date=datetime.datetime.now().date()):
    value = getValueByDate(from_date)

print sct.func_defaults

Whatever you see in that tuple that gets printed out is the "from_date" value that keeps being reused in your code.

If you want to be able to call the function with the default behavior being that it takes the current time, but with the option to override, then do this instead:

def sct(from_date=None):
    if from_date is None:
        from_date = datetime.datetime.now().date()
    value = getValueByDate(from_date)

For more details on default parameter values, see this effbot post.

btw, not sure what this function is supposed to do. Doesn't seem to return anything.