正是你要实现你的缓存是如何真正依靠什么平台你的Python代码会被运行。
因为地址的位置不会经常变化,所以你需要一个非常持久的“缓存”:-),所以一个数据库(在键值心情中)似乎是最好的。
因此,在很多情况下,我会选择sqlite3
,这是一个优秀的,非常轻量级的SQL引擎,它是Python标准库的一部分。除非可能我更喜欢例如我需要运行的MySQL实例,否则一个优点可能是,这将允许运行在不同节点上的多个应用程序共享“缓存” - 其他DB(包括SQL和非SQL)将对后者取决于你的约束和偏好。
但是,如果我是在Google App Engine上运行的,那么我会使用它包含的数据存储库。除非我有特定的原因想要在多个不同的应用程序之间共享“缓存”,在这种情况下,我可能会考虑诸如谷歌云和谷歌存储之类的替代方案,以及另一种由专用“缓存服务器”GAE应用程序组成的替代方案我自己的服务RESTful结果(也许w /端点?)。再次选择!非常非常依赖于您的约束和偏好(延迟,每秒查询大小等等)。
因此,请澄清您所在的平台以及您对数据库“缓存”的其他约束和偏好,以及可以轻松显示的非常简单的代码。但在澄清之前,显示六种不同的可能性不会很有成效。
补充:由于意见建议sqlite3
是可以接受的,而且也有代码最佳显示一些重要的细节(比如,如何序列化和从sqlite3
BLOB反序列化的geopy.location.Location
实例为/ - 类似的问题可能与其他底层数据库一起出现,并且解决方案相似),我决定在代码中最好地显示解决方案示例。所以,作为“地理缓存”显然是最好的,因为它自己的模块来实现,我写了下面简单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.')
我希望在这里说明的想法是很清楚 - 有每个方案设计的选择,但我试图让事情变得简单(特别是,当这个模块直接运行时,我使用了一个简单的示例暨小型测试,代替适当的单元测试套件......) 。
有关序列化到/从斑点,我选择pickle
的“最高协议”的位(-1
)协议 - 当然cPickle
将只是在Python 2为良好(快:-)但这些几天后,我尝试编写与Python 2或3相同的代码,除非我有特殊的理由不这样做:-)。当然,我为测试中使用的sqlite数据库使用了不同的文件名test.db
,因此您可以毫无顾虑地将其擦除以测试某些变体,而意图用于“生产”代码的默认文件名保持不变(它是相当可疑的设计选择使用相对的文件名 - 这意味着“在当前目录中” - 但决定放置这样的文件的位置的适当方式是相当平台依赖的,我不想在这里进入这样的exoterica :-)。
如果还有其他问题,请询问(也许最好在一个单独的新问题,因为这个答案已经变得如此之大 - )。
@cslstr,SQLite是最自然的解决方案,我 - 一个内存中加载字典在启动瓦特/泡菜,并在程序结束甩可以被认为是“简单”,但它需要一个无界的,数量不断增加的内存和启动/关闭时间随着时间的推移和“缓存”变大,所以我会将它看作是一个非常糟糕的耐用程序体系结构。 – 2015-02-08 19:02:29
这些是我关心的,只是在记忆中保留一个列表/字典,不知道他们会影响事情多少。 +1用于调查选项。 – cslstr 2015-02-08 19:09:06