4

I have this python '2.6.4' script:

#!/usr/bin/python
import MySQLdb
import csv
import pprint

db = MySQLdb.connect(host="localhost", # The Host
                     user="username", # username
                      passwd="password", # password
                      db="dbname") # name of the data base

cursor = db.cursor() 

cursor.execute("SELECT name, id, city, storeid FROM Products;")

StudentsData = cursor.fetchall()
pprint.pprint(StudentsData)

this query return millions of rows, and it takes 3 minutes to execute, and it run 20 times a day, and everyuser has to wait three minutes to fetch the output.

I was thinking about caching it, but I don't know how to do that in python, will that be a good idea, if so how can I do it, using the obove code.

please help me if there's a better way to do this?

1
  • The decision of whether to cache is entirely up to you. Will stale data be a problem? Commented Apr 1, 2013 at 19:02

2 Answers 2

6

The decision of whether to cache is entirely up to you. Will stale data be a problem?

The simplest caching scheme I can think of is something like the following using Python's pickle module:

import MySQLdb
import csv
import pprint
import time

MAX_CACHE_AGE = 60*20  # 20 Minutes
CACHE_FILENAME = 'results.cache'

with open(CACHE_FILENAME, 'r') as cache:
    cached = pickle.load(cache)

if(time.time() > cached['timestamp'] + MAX_CACHE_AGE):
    # Cache too old, run query
    db = MySQLdb.connect(host="localhost", # The Host
                     user="username", # username
                     passwd="password", # password
                     db="dbname") # name of the data base

    cursor = db.cursor() 
    cursor.execute("SELECT name, id, city, storeid FROM Products;")
    StudentsData = cursor.fetchall()

    # Update cache file
    data = {'results': StudentsData, 'timestamp':time.time()}
    with open(CACHE_FILENAME, 'w') as cache:
        pickle.dump(data, cache)

else:
    # Cached data is fresh enough, use that
    StudentsData = cached['results']

pprint.pprint(StudentsData)

You'll need to initialize the results.cache file once manually.


EDIT

The with syntax is a context manager and was introduced in Python 2.5.

with open(CACHE_FILENAME, 'r') as cache:
    cached = pickle.load(cache)

Can be rewritten as

cached = open(CACHE_FILENAME, 'r')
cached = pickle.load(cache)
cached.close()

EDIT2

After a long discussion in chat, the following works:

import MySQLdb
import csv
import pprint
import time
import pickle

MAX_CACHE_AGE = 60*20  # 20 Minutes
CACHE_FILENAME = 'results.cache'

regen = False
try:
    with open(CACHE_FILENAME, 'r') as cache:
        cached = pickle.load(cache)

    if(time.time() > cached['timestamp'] + MAX_CACHE_AGE):
        print("Cache too old: regenerating cache")
        regen = True
    else:
        print("Cached data is fresh enough: loading results from cache")

except IOError:
    print("Error opening %s: regenerating cache" % CACHE_FILENAME)
    regen = True

if(regen):
    # Cache too old, run query
    db = MySQLdb.connect(host="localhost", # The Host
                     user="username", # username
                     passwd="password", # password
                     db="dbname") # name of the data base

    cursor = db.cursor()
    cursor.execute("SELECT name, id, city, storeid FROM Products;")
    StudentsData = cursor.fetchall()
    cursor.close()

    # Update cache file
    data = {'results': StudentsData, 'timestamp':time.time()}
    with open(CACHE_FILENAME, 'w') as cache:
        pickle.dump(data, cache)

else:
    # Cached data is fresh enough, use that
    StudentsData = cached['results']


print StudentsData
Sign up to request clarification or add additional context in comments.

10 Comments

Thank you very much for the great example!! I believe that this is exactly what I'm looking for, the only thing is that I get this error, with open(CACHE_FILENAME, 'r') as cache: ^ SyntaxError: invalid syntax should I install something for the script to work? Thanks!
Did you miss the as in there?
I got the error with and without as . I tried to remove it and see if that will solve the issue. but it didn't.
What version of Python are you using? A version before context managers were supported? I edited in an alternative pattern in case you're using Python < 2.5
sorry, I didn't post that. '2.6.4'
|
2

In Python 3, and for a very simple case, you could look at functools.lru_cache: http://docs.python.org/3.2/library/functools.html#functools.lru_cache

For more sophisticated caching, Beaker is probably the way to go: http://beaker.readthedocs.org/en/latest/caching.html

1 Comment

Any alternatives for python2??

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.