如何在Python中使用临时文件系统模拟os.walk?

34 投票
1 回答
13522 浏览
提问于 2025-04-18 11:52

我正在尝试测试一些使用os.walk的代码。我想创建一个临时的、在内存中的文件系统,这样我就可以在里面放一些示例(空的)文件和目录,然后os.walk就能返回这些内容。这可以让我省去模拟os.walk调用以模拟递归的复杂性。

具体来说,我想测试的代码是:

if recursive:
    log.debug("Recursively searching for files under %s" % path)

    for (dir_path, dirs, files) in os.walk(path):
        log.debug("Found %d files in %s: %s" % (len(files), path, files))
        for f in [os.path.join(dir_path, f) for f in files
                  if not re.search(exclude, f)]:
            yield f
else:
    log.debug("Non-recursively searching for files under %s" % path)

    for (dir_path, dirs, files) in os.walk(path):
        log.debug("Found %d files in %s: %s" % (len(files), path, files))
        for f in [os.path.join(dir_path, f) for f in files
                    if not re.search(exclude, f)]:
            yield f

在Python中,这样做可能吗?

1 个回答

55

不,os.walk() 完全是基于 os.listdir() 来构建的,同时也用到了 os.path.islink()os.path.isdir()。这些其实都是系统调用,所以你需要在系统层面上模拟你的文件系统。除非你想写一个 FUSE 插件,否则模拟起来会比较麻烦。

其实,os.walk() 只需要返回一个元组的列表。除非你在测试处理 dirs 这个部分,否则这件事简单得不能再简单了:

with mock.patch('os.walk') as mockwalk:
    mockwalk.return_value = [
        ('/foo', ('bar',), ('baz',)),
        ('/foo/bar', (), ('spam', 'eggs')),
    ]

这段代码会模拟以下的目录结构:

/foo
 ├── baz
 └── bar 
     ├── spam
     └── eggs

撰写回答