猿问

Python子流程:他们如何/何时关闭文件?

我想知道为什么子进程使这么多文件保持打开状态。我有一个例子,其中某些文件似乎永远保持打开状态(在子进程完成后,甚至在程序崩溃之后)。


请考虑以下代码:


import aiofiles

import tempfile


async def main():

    return [await fds_test(i) for i in range(2000)]


async def fds_test(index):

    print(f"Writing {index}")

    handle, temp_filename = tempfile.mkstemp(suffix='.dat', text=True)

    async with aiofiles.open(temp_filename, mode='w') as fp:

        await fp.write('stuff')

        await fp.write('other stuff')

        await fp.write('EOF\n')


    print(f"Reading {index}")

    bash_cmd = 'cat {}'.format(temp_filename)

    process = await asyncio.create_subprocess_exec(*bash_cmd.split(), stdout=asyncio.subprocess.DEVNULL, close_fds=True)

    await process.wait()

    print(f"Process terminated {index}")


if __name__ == "__main__":

    import asyncio

    asyncio.run(main())

这将一个接一个地生成进程(按顺序)。我希望同时打开的文件数量也是一个。但事实并非如此,在某些时候我得到以下错误:


/Users/cglacet/.pyenv/versions/3.8.0/lib/python3.8/subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session)

   1410             # Data format: "exception name:hex errno:description"

   1411             # Pickle is not used; it is complex and involves memory allocation.

-> 1412             errpipe_read, errpipe_write = os.pipe()

   1413             # errpipe_write must not be in the standard io 0, 1, or 2 fd range.

   1414             low_fds_to_close = []


OSError: [Errno 24] Too many open files

我尝试在没有该选项的情况下运行相同的代码,但它仍然崩溃。这个答案表明,这可能是问题的根源,错误也指向线 。但这似乎不是问题所在(在没有该选项的情况下运行会产生相同的错误)。stdout=asyncio.subprocess.DEVNULLerrpipe_read, errpipe_write = os.pipe()

一只甜甜圈
浏览 84回答 1
1回答

翻翻过去那场雪

问题不是来自此代码中的问题是 tempfile.mkstemp() 实际上打开了该文件:create_subprocess_execmkstemp() 返回一个元组,其中包含一个打开文件的操作系统级句柄(由 os.open()返回) ...我以为它只会创建文件。为了解决我的问题,我只是在 中添加了一个调用。这消除了错误,但有点奇怪(打开文件两次)。所以我把它改写为:os.close(handle)import aiofilesimport tempfileimport uuidasync def main():    await asyncio.gather(*[fds_test(i) for i in range(10)])async def fds_test(index):    dir_name = tempfile.gettempdir()    file_id = f"{tempfile.gettempprefix()}{uuid.uuid4()}"    temp_filename = f"{dir_name}/{file_id}.dat"    async with aiofiles.open(temp_filename, mode='w') as fp:        await fp.write('stuff')    bash_cmd = 'cat {}'.format(temp_filename)    process = await asyncio.create_subprocess_exec(*bash_cmd.split(), close_fds=True)    await process.wait()if __name__ == "__main__":    import asyncio    asyncio.run(main())现在我想知道为什么错误是由而不是引起的,也许是因为它子进程打开了更多的文件,以至于它不太可能使临时文件创建成为打破限制的原因......subprocesstempfile.mkstemp
随时随地看视频慕课网APP

相关分类

Python
我要回答