【问题标题】:Python: recursion with async/awaitPython:使用 async/await 进行递归
【发布时间】:2020-03-13 02:45:58
【问题描述】:

这是一些用于遍历文件树的简单工作代码。它使用了同步生成器的思想:

def list_dir_groom(abs_path):
    """Returns the list of directories
    and the list of files ([abs_path] offspring).
    """
    dirs, files = [], []

    for i in os.listdir(abs_path):
        if i[0] != ".":
            x = abs_path.joinpath(i)
            if x.is_dir():
                dirs.append(x)
            else:
                if is_target_file(x):
                    files.append(x)

    return dirs, files


def traverse_target_tree(tgt_dir):
    """Recursively traverses the target directory [tgt_dir]
    and yields a sequence of file names.
    """
    dirs, files = list_dir_groom(tgt_dir)

    for d in dirs:
        yield from traverse_target_tree(d)

    for f in files:
        yield f


def tweak():
    """Tweak all files.
    """
    for i in traverse_target_tree(ARGS.tgt_dir):
        print(f"{i}")

出于教育目的,我一直在尝试使用 asyncio (Python 3.8.1) 重写它。当然,这正常工作:

async def traverse_target_tree_async(tgt_dir):
    """Recursively traverses the target directory [tgt_dir]
    and yields a sequence of file names.
    """
    dirs, files = list_dir_groom(tgt_dir)

    for d in dirs:
        yield traverse_target_tree_async(d)

    for f in files:
        yield f


async def tweak_async():
    """Tweak all files.
    """
    async for i in traverse_target_tree_async(ARGS.tgt_dir):
        print(f"{i}")

...

asyncio.run(tweak_async())

示例输出如下所示:

<async_generator object traverse_target_tree_async at 0x7f4993429ca0>
<async_generator object traverse_target_tree_async at 0x7f4993429d30>
<async_generator object traverse_target_tree_async at 0x7f4993429ca0>
<async_generator object traverse_target_tree_async at 0x7f4993429d30>
/home/user/spaces/python/tex-tweak/n.vim
/home/user/spaces/python/tex-tweak/README.md
/home/user/spaces/python/tex-tweak/pyproject.toml
/home/user/spaces/python/tex-tweak/poetry.lock

在某种程度上,这是有道理的,但我不知道我应该做的最后一步。

【问题讨论】:

  • 很难测试你的脚本,因为它不是一个最小的可执行示例。但无论如何,如果您将yield traverse_target_tree_async(d) 更改为yield from traverse_target_tree_async(d),它可能会起作用。
  • yield from 在异步上下文中是一个语法错误,这是正确的。
  • 啊,我什至不知道......使用async for手动扩展它怎么样?这个答案应该会有所帮助:stackoverflow.com/a/47378063/5588279
  • 旁注:os.listdiros.scandir 更糟糕,尤其是当你想做测试它是否是一个目录时(scandir 返回的DirEntry 可以告诉你免费,而您当前的方法需要每个文件一个 stat)。

标签: python recursion async-await


【解决方案1】:

建议解决方案here。感谢Sraw

async def traverse_target_tree_async(tgt_dir):
    """Recursively traverses the target directory [tgt_dir]
    and yields a sequence of file names.
    """
    dirs, files = list_dir_groom(tgt_dir)

    for d in dirs:
        async for f in traverse_target_tree_async(d):
            yield f

    for f in files:
        yield f

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 2020-07-26
    • 2017-05-13
    • 2017-11-08
    • 2018-02-09
    • 2018-04-02
    • 1970-01-01
    相关资源
    最近更新 更多