无法在runner.isolated_filesystem()中使用click.Path选项读取文件

0 投票
1 回答
15 浏览
提问于 2025-04-13 13:24

我第一次使用click来用Python 3.12.2创建一个命令行程序。

我创建了一个简单的click命令,它接受一个选项('-f' / '--file'选项),这个选项是一个文件路径,类型是click.Path():

@click.command()
@click.option(
    "-f",
    "--file",
    "input_file_path",
    type=click.Path(path_type=Path, exists=True, resolve_path=True),
    required=True,
)
@click.option("-e", "--executor", "executor", default="pbiservice")
def validate(input_file_path: Path, executor):
    executor = EXECUTORS[executor]
    processed_validations_spec = (
        process_validations_spec_from_local_file_and_return_resulting_validations_spec(
            input_file_path, executor
        )
    )
    click.echo(processed_validations_spec)

现在,当我尝试使用click的CliRunner来测试这个命令时,我想要一个独立的临时目录,这个目录在测试结束后会被删除。这样我就可以创建一个测试文件,调用命令并指向那个文件路径,然后在测试结束后把所有东西清理掉。

所以我使用runner.isolated_filesystem上下文管理器为这个命令创建了一个测试。

但是,不管我怎么尝试,我都无法在runner.invoke()里面使用我创建的cli命令访问之前写入临时目录的文件。以下是我的测试:

def test_validate(validations_spec):
    runner = CliRunner()
    with runner.isolated_filesystem() as td:
        file_name = "validations_spec.json"
        write_validations_spec_to_local_file(validations_spec, Path(file_name))
        result = runner.invoke(
            validate,
            [f"-f {file_name}"],
        )
        processed_validations_spec = validations_spec.process(MirrorExecutor())
        assert result.output == processed_validations_spec

这个测试总是失败,错误信息是Error: Invalid value for '-f' / '--file': Path ' validations_spec.json' does not exist.

我尝试用Python内置的open函数读取这个文件,结果是可以的,所以文件确实存在。问题是click命令找不到它,我不知道为什么。


我期望的结果和尝试过的:

在isolated_filesystem中调用的click命令应该能够访问在这个独立文件系统中创建的文件路径。

然而,它却声称文件不存在。

  • 我用内置的open函数检查了文件,确认它确实存在
  • 我尝试调整click.Path类型的resolve_path=True/False参数,但没有任何变化

1 个回答

0

你的问题出在这段代码上:

        result = runner.invoke(
            validate,
            [f"-f {file_name}"],
        )

这就像是在命令行中运行以下命令:

./myprogram "-f validation_spec.json"

在这两种情况下,-fvalidation_spec.json之间的空格被当作文件名的一部分。所以你的错误信息看起来像这样:

Error: Invalid value for '-f' / '--file': Path ' validations_spec.json' does not exist.

你看到' validation_spec.json'中的那个空格了吗?

解决办法是传递一个参数列表:

        result = runner.invoke(
            validate,
            ["-f", file_name],
        )

撰写回答