【问题标题】:Use a Glob() in VariantDir() einvironment to find files recursively in Python?在 VariantDir() 环境中使用 Glob() 在 Python 中递归查找文件?
【发布时间】:2012-06-15 11:56:51
【问题描述】:

如何在 Python 中的 VariantDir() 环境中创建递归 Glob()

问题 Use a Glob() to find files recursively in Python?> 的答案将不起作用,因为您需要使用 Glob() 来获取知道 VariantDir() 环境的文件列表。

所以你需要这样的东西:

import fnmatch
import os

matches = []
for root, dirnames, filenames in os.walk('src'):
  for filename in fnmatch.filter(filenames, '*.c'):
    matches.append(os.path.join(root, filename))

matches = Glob(matches)

这行得通吗?

【问题讨论】:

  • 这种构造matches = Glob(matches) 不起作用,但可以使用matches.append(Glob(os.path.join(root, filename))) 代替它。虽然它似乎不是最优的。

标签: python scons


【解决方案1】:

我相信只有当您的源目录是 '.' 时,接受的答案才有效。

这是一个工作示例,其中源目录为src,变体目录为build

文件布局

.
├── include
│   └── sum.h
├── SConstruct
└── src
    ├── dir
    │   └── sum.cpp
    └── main.cpp

文件

sum.h

#ifndef _SUM_H_
#define _SUM_H_

double sum(const double x, const double y);

#endif

main.cpp

#include <iostream>
#include <sum.h>

using namespace std;

int main() {

    cout << "Sum of 1 and 2 = " << sum(1., 2.) << endl;
    return 0;
}

sum.cpp

#include <sum.h>

double sum(const double x, const double y) {
    return x + y;
}

S构造

import os

def variantglob(env, pattern, ondisk=True, source=True, strings=False,
                recursive=False):
    matches = []
    for root, dirs, filenames in os.walk(env['SOURCE_DIR']):
        cwd = Dir(os.path.join(env['VARIANT_DIR'],
                               os.path.relpath(root, env['SOURCE_DIR'])))
        matches.extend(cwd.glob(pattern, ondisk, source, strings))
    return matches

# Create Build Environment
env = Environment()

# Customize Environment
env.Replace(VARIANT_DIR='build',
            SOURCE_DIR='src')
env.Append(CPPPATH=['include'])

# Setup Variant Directory
VariantDir(variant_dir=env['VARIANT_DIR'],
           src_dir=env['SOURCE_DIR'], duplicate=0)

# Build the executable
exe = env.Program(os.path.join(env['VARIANT_DIR'], 'example'),
                  variantglob(env, '*.cpp', recursive=True))

# Install the executable
Install('bin', exe)

构建

只需在顶级目录执行scons。这将创建一个build 目录并将所有临时文件放在那里(变体目录),然后它将构建的结果安装到 bin 文件夹中。

运行

执行 bin/example 以查看它的工作原理。

注意

这个例子是在 linux 上测试的。

为什么会起作用

使用变体目录构建时,您必须指定源的路径,就好像它已经位于变体目录中一样,但这些目录可能不存在。这个 glob 函数遍历源代码树以构造 在变体目录中的路径,然后针对这些路径进行 glob。

【讨论】:

  • 经过数小时的尝试让目标文件在构建库中编译后,这对我有用。
【解决方案2】:

您的方法只需稍作调整即可工作,如下所示:

import fnmatch
import os

def RecursiveGlob(pathname)
    matches = []
    for root, dirnames, filenames in os.walk(pathname):
        for filename in fnmatch.filter(filenames, '*.c'):
            matches.append(File(os.path.join(root, filename)))

    return matches

请注意,我将其转换为 File(),因为如果“strings”参数为 false,SCons Glob() 函数将返回 Nodes。

为了能够处理 VariantDir 等并更好地将功能与现有 SCons Glob() 功能集成,您实际上可以合并对现有 Glob() 函数的调用,如下所示:

# Notice the signature is similar to the SCons Glob() signature,
# look at scons-2.1.0/engine/SCons/Node/FS.py line 1403
def RecursiveGlob(pattern, ondisk=True, source=True, strings=False):
    matches = []
    # Instead of using os.getcwd() consider passing-in a path
    for root, dirnames, filenames in os.walk(os.getcwd()):
        cwd = Dir(root)
        # Glob() returns a list, so using extend() instead of append()
        # The cwd param isnt documented, (look at the code) but its 
        # how you tell SCons what directory to look in.
        matches.extend(Glob(pattern, ondisk, source, strings, cwd))

    return matches

您可以更进一步,执行以下操作:

def MyGlob(pattern, ondisk=True, source=True, strings=False, recursive=False):
    if not recursive:
        return Glob(pattern, ondisk, source, strings)

    matches = []
    # Instead of using os.getcwd() consider passing-in a path
    for root, dirnames, filenames in os.walk(os.getcwd()):
        cwd = Dir(root)
        # Glob() returns a list, so using extend() instead of append()
        # The cwd param isnt documented, (look at the code) but its 
        # how you tell SCons what directory to look in.
        matches.extend(Glob(pattern, ondisk, source, strings, cwd))

    return matches

【讨论】:

  • 你能告诉我如何调用这个 glob 的变体吗?我的安装抱怨第六个参数。我可以在源代码中看到正确的版本,但我一生都无法调用它?
  • @AdamNaylor,您指的是哪个版本的 glob()?我没有看到这个答案中有 6 个参数的 glob 变体。如果您想使用其中一种 glob 变体,则需要在您的 SConstruct 中定义它。
  • 当我运行第三个示例时,我得到: TypeError: Glob() 最多接受 5 个参数(给定 6 个)如果我编辑 Environment.py (scons v2.3.0) 的第 2055 行以包含它工作的 cwd 参数?!?
  • 事实上,它似乎并不尊重 VariantDir,因为如果我在循环内打印“目录名”,它总是为空的。这意味着它正在查看 VariantDir,而不是源目录。
猜你喜欢
  • 2011-01-12
  • 1970-01-01
  • 2019-01-03
  • 2023-03-29
相关资源
最近更新 更多