os.walk() 缓存/加速

3 投票
3 回答
1863 浏览
提问于 2025-04-16 03:07

我有一个原型服务器[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 个回答

0

你有没有看过 MongoDB?那 mod_python 呢?使用 mod_python 的话,你可以用 os.walk() 来遍历文件夹,然后把数据存储在 Python 的数据结构里,因为这个脚本在连接之间是可以保持运行的。

3

你其实不需要把树形结构保存下来——实际上,你的代码正在把目录树的自然树形结构拆解成一个线性的顺序,那你为什么还想下次从树形结构开始呢?

看起来你需要的只是一个有序的序列:

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

其中 stringfoo

3

我一开始误解了问题,但现在我想我有了一个解决办法(而且和我之前的回答有很大不同,所以值得单独提一下)。基本上,第一次在一个文件夹里运行的时候,你正常查询文件,但要把得到的结果存起来。第二次运行的时候,你就直接用存下来的结果。为了方便,我把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

撰写回答