Как именно вы хотите реализовать свой кэш действительно зависит от того, какую платформу код Python будет работать на.
Вы хотите довольно устойчивый «кеш», поскольку адреса не будут часто меняться :-), поэтому лучше всего использовать базу данных (в настроении с ключом).
Так что во многих случаях я бы выбрал sqlite3
, отличный, очень легкий механизм SQL, который является частью стандартной библиотеки Python. Если, возможно, я не предпочел, например, экземпляр MySQL, который мне нужно запустить в любом случае, одно из преимуществ может заключаться в том, что это позволит нескольким приложениям, работающим на разных узлах, совместно использовать «кеш» - другие БД, как SQL, так и non, были бы хороши для последний, в зависимости от ваших ограничений и предпочтений.
Но если бы я работал в Google App Engine, я бы использовал вместо него хранилище данных. Если у меня не было особых причин, чтобы поделиться «кешем» между несколькими разрозненными приложениями, в этом случае я мог бы рассмотреть альтернативы, такие как Google Cloud sql и хранилище google, а также еще одну альтернативу, которая все еще состоит из специального приложения GAE для кеша моих собственных результатов RESTful (возможно, с конечными точками?). Выбор снова, очень! Очень, очень зависит от ваших ограничений и предпочтений (латентность, размер запросов в секундах и т. Д. И т. Д.).
Итак, пожалуйста, уточните, на какой платформе вы находитесь, и какие другие ограничения и предпочтения у вас есть для вашего кеша базы данных, а затем очень простой код для реализации, который можно легко показать. Но показ полдюжины различных возможностей, прежде чем вы уточните, не будет очень продуктивным.
Добавлено: поскольку комментарии предполагают sqlite3
может быть приемлемым, и есть несколько важных деталей лучше всего показано в коде (например, как для сериализации и десериализации экземпляра geopy.location.Location
в/из sqlite3
сгустка - подобные вопросы могут хорошо возникают с другими базовыми базами данных, и решения аналогичны), я решил, что пример решения лучше всего показывать в коде. Так что, как «кэш-гео» явно лучше реализован как ее собственный модуль, я написал следующую простую geocache.py
...:
import geopy
import pickle
import sqlite3
class Cache(object):
def __init__(self, fn='cache.db'):
self.conn = conn = sqlite3.connect(fn)
cur = conn.cursor()
cur.execute('CREATE TABLE IF NOT EXISTS '
'Geo ('
'address STRING PRIMARY KEY, '
'location BLOB '
')')
conn.commit()
def address_cached(self, address):
cur = self.conn.cursor()
cur.execute('SELECT location FROM Geo WHERE address=?', (address,))
res = cur.fetchone()
if res is None: return False
return pickle.loads(res[0])
def save_to_cache(self, address, location):
cur = self.conn.cursor()
cur.execute('INSERT INTO Geo(address, location) VALUES(?, ?)',
(address, sqlite3.Binary(pickle.dumps(location, -1))))
self.conn.commit()
if __name__ == '__main__':
# run a small test in this case
import pprint
cache = Cache('test.db')
address = '1 Murphy St, Sunnyvale, CA'
location = cache.address_cached(address)
if location:
print('was cached: {}\n{}'.format(location, pprint.pformat(location.raw)))
else:
print('was not cached, looking up and caching now')
g = geopy.geocoders.GoogleV3()
location = g.geocode(address)
print('found as: {}\n{}'.format(location, pprint.pformat(location.raw)))
cache.save_to_cache(address, location)
print('... and now cached.')
Я надеюсь, что идеи, показанные здесь достаточно ясно - есть альтернативы по каждому дизайн, но я пытался упростить задачу (в частности, я использую простой пример-cum-mini-test, когда этот модуль запускается напрямую, вместо соответствующего набора модульных тестов ...) ,
Для немного о сериализации в/из сгустков, я выбрал pickle
с «высшим протоколом» (-1
) протокол - cPickle
конечно было бы так же хорошо в Python 2 (и быстрее :-), но они дней Я пытаюсь написать код, который одинаково хорош как Python 2 или 3, если у меня нет конкретных причин делать иначе :-).И, конечно же, я использую другое имя файла test.db
для базы данных sqlite, используемой в тесте, поэтому вы можете стереть ее без каких-либо проблем, чтобы проверить некоторые варианты, в то время как имя файла по умолчанию, предназначенное для использования в «производственном» коде, остается неизменным (это довольно сомнительный выбор дизайна для использования относительного имени файла, что означает «в текущем каталоге», - но подходящий способ решить, где разместить такой файл, зависит от платформы, и я не хотел Входите в такую экзотерию здесь :-).
Если у вас остался другой вопрос, пожалуйста, спросите (возможно, лучше по отдельному новому вопросу, так как этот ответ уже стал таким большим!).
@cslstr, SQLite является наиболее естественным решением для меня - в памяти ДИКТ загружается при запуске ж/рассола и сбрасывал в конце программы можно рассматривать как «простой», но это требует неограниченного, растущее количества памяти и времени запуска/завершения работы с течением времени, а «кеш» растет, поэтому я считаю это довольно плохой архитектурой для долговременной программы. –
Это были мои проблемы, просто сохраняя список/dict в памяти, не был уверен, насколько они повлияют на вещи. +1 для просмотра опций. – cslstr