【问题标题】:How to limit the number of concurrent read / write with aiofiles?如何使用 aiofiles 限制并发读/写的数量?
【发布时间】:2019-12-13 14:49:27
【问题描述】:

我的程序会同时用aiohttp下载大约1000万条数据,然后将数据写入磁盘上大约4000个文件。

我使用aiofiles 库是因为我希望我的程序在读/写文件时也能做其他事情。

但我担心如果程序尝试同时写入所有 4000 个文件,硬盘无法快速完成所有写入。

是否可以使用 aiofiles(或其他库)限制并发写入的数量? aiofiles 是否已经这样做了?

谢谢。

测试代码:

import aiofiles
import asyncio


async def write_to_disk(fname):
    async with aiofiles.open(fname, "w+") as f:
        await f.write("asdf")


async def main():
    tasks = [asyncio.create_task(write_to_disk("%d.txt" % i)) 
             for i in range(10)]
    await asyncio.gather(*tasks)


asyncio.run(main())

【问题讨论】:

    标签: python python-asyncio aiohttp python-aiofiles


    【解决方案1】:

    您可以使用asyncio.Semaphore 来限制并发任务的数量。只需在写入之前强制您的 write_to_disk 函数获取信号量:

    import aiofiles
    import asyncio
    
    
    async def write_to_disk(fname, sema):
        # Edit to address comment: acquire semaphore after opening file
        async with aiofiles.open(fname, "w+") as f, sema:
            print("Writing", fname)
            await f.write("asdf")
            print("Done writing", fname)
    
    
    async def main():
        sema = asyncio.Semaphore(3)  # Allow 3 concurrent writers
        tasks = [asyncio.create_task(write_to_disk("%d.txt" % i, sema)) for i in range(10)]
        await asyncio.gather(*tasks)
    
    
    asyncio.run(main())
    

    注意sema = asyncio.Semaphore(3) 行以及async with 中添加的sema,

    输出:

    """
    Writing 1.txt
    Writing 0.txt
    Writing 2.txt
    Done writing 1.txt
    Done writing 0.txt
    Done writing 2.txt
    Writing 3.txt
    Writing 4.txt
    Writing 5.txt
    Done writing 3.txt
    Done writing 4.txt
    Done writing 5.txt
    Writing 6.txt
    Writing 7.txt
    Writing 8.txt
    Done writing 6.txt
    Done writing 7.txt
    Done writing 8.txt
    Writing 9.txt
    Done writing 9.txt
    """
    

    【讨论】:

    • 当其中一个文件对象正在缓冲时,另一个文件对象可以写入而不会对性能造成太大影响。但是,如果我向 f.write 添加一个信号量,即使写入只是缓冲而不是实际写入磁盘,也会阻塞吗?数据是json。
    • @DuhHuh 刚刚更新了我的答案,将信号量移动到 async with 中的 .open 之后确保文件将首先被打开,但同时对它们的写入受到限制
    猜你喜欢
    • 1970-01-01
    • 2015-12-06
    • 2019-07-31
    • 1970-01-01
    • 2019-09-04
    • 2023-04-01
    • 2022-12-11
    • 2012-01-19
    • 1970-01-01
    相关资源
    最近更新 更多