5

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
Dan McGrath
  • 41,220
  • 11
  • 99
  • 130
nouseforaname
  • 309
  • 3
  • 11
  • Is the problem here that you're calling .now() only once when it's deployed and storing it in a variable, then just reusing that variable, not calling it each time you're adding a value?... – LexyStardust Jan 08 '15 at 15:22
  • I think i missed a detail here as im calling it as part of another method. So i edited my question. What do you think? – nouseforaname Jan 08 '15 at 15:32
  • In my opinion this is not the case as in the method declaration of "sct" it should always create a new timestamp instance. – nouseforaname Jan 08 '15 at 15:40

2 Answers2

10

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.

zehnpaard
  • 6,003
  • 2
  • 25
  • 40
  • Thank you very much for the detailed explanation! Moving timestamp creation into the the mehtod body solved my problem so far. The reason why i added the default to method declaration is that i wanted to be able to call that method for other dates as well, which is not really necessary at the moment but may come up again in the future. BTW I did cut the method for this post as it is quite long... – nouseforaname Jan 09 '15 at 09:18
  • 1
    Just to clarify, if you follow the `def sct(from_date=None)` pattern in my last example, `sct` will accept a different date as an optional argument. Then, `from_date` will not be `None` so `datetime.datetime.now().date()` will not be called. So you *can* have it both ways, have the current date as default, and accept another date as option. – zehnpaard Jan 11 '15 at 01:14
0

It appears that it's only getting the datetime at the deploy of the app. Move from_date=datetime.datetime.now().date() out of the definition into the body of the function and see if that works.

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

See if that changes your results. This usually happens when you set a value outside of a function, as it's never called again until the app restarts.