os.walk() 缓存/加速
我有一个原型服务器[0],它在处理每个客户端[0]的请求时,会使用一个叫os.walk()
[1]的功能。
我现在在寻找一些方法来:
- 把这些数据缓存到内存中,
- 加快查询速度,
- 希望将来能扩展到存储元数据和数据持久化。
我觉得用SQL来处理树形结构的数据有点复杂,所以在决定使用SQLite之前,我想先听听建议。
有没有一些跨平台的、可以嵌入或打包的非SQL数据库,能够处理这种类型的数据呢?
- 我有一个小的文件列表(大约1万到10万文件)。
- 我连接的数量非常少(大概10到20个)。
- 我还希望能够扩展到处理元数据。
[0] 这个服务器和客户端其实是同一个软件,这是一个点对点(P2P)应用,旨在通过一个可信的本地网络共享文件,不需要主服务器,使用zeroconf
来发现设备,其他大部分功能则用twisted来实现。
[1] 目前在处理1万个文件时,查询时间是1.2秒,使用的是os.walk()
。
这是我Python代码中负责遍历文件的相关功能:
def populate(self, string):
for name, sharedir in self.sharedirs.items():
for root, dirs, files, in os.walk(sharedir):
for dir in dirs:
if fnmatch.fnmatch(dir, string):
yield os.path.join(name, *os.path.join(root, dir)[len(sharedir):].split("/"))
for file in files:
if fnmatch.fnmatch(file, string):
yield os.path.join(name, *os.path.join(root, ile)[len(sharedir):].split("/"))
3 个回答
你有没有看过 MongoDB?那 mod_python
呢?使用 mod_python
的话,你可以用 os.walk()
来遍历文件夹,然后把数据存储在 Python 的数据结构里,因为这个脚本在连接之间是可以保持运行的。
你其实不需要把树形结构保存下来——实际上,你的代码正在把目录树的自然树形结构拆解成一个线性的顺序,那你为什么还想下次从树形结构开始呢?
看起来你需要的只是一个有序的序列:
i X result of os.path.join for X
这里的 X 是一个字符串,表示文件或目录(你可以把它们当成一样的),i 是一个逐渐增加的整数(用来保持顺序),结果列也是一个字符串,是通过 os.path.join(name, *os.path.join(root,
等等得到的结果。
当然,这些内容很容易放进一个 SQL 表里!
第一次创建表的时候,只需从你的填充函数中去掉 if fnmatch.fnmatch
(还有 string
参数),在 os.path.join
结果之前先输出目录或文件,然后用 cursor.executemany
来保存调用的 enumerate
(或者用一个自增的列,随你选择)。使用这个表时,populate
基本上变成了:
select result from thetable where X LIKE '%foo%' order by i
其中 string
是 foo
。
我一开始误解了问题,但现在我想我有了一个解决办法(而且和我之前的回答有很大不同,所以值得单独提一下)。基本上,第一次在一个文件夹里运行的时候,你正常查询文件,但要把得到的结果存起来。第二次运行的时候,你就直接用存下来的结果。为了方便,我把os.walk()的调用包裹了一下,因为它比较短,但你也可以把整个生成器包裹起来。
cache = {}
def os_walk_cache( dir ):
if dir in cache:
for x in cache[ dir ]:
yield x
else:
cache[ dir ] = []
for x in os.walk( dir ):
cache[ dir ].append( x )
yield x
raise StopIteration()
我不太清楚你的内存需求,但你可能需要考虑定期清理一下cache
。