首页 > 解决方案 > asyncio.create_subprocess_shell 错误:从未检索到未来异常 - BrokenPipeError

问题描述

每当我将 asyncio.create_subprocess_shell() 与 sp.communicate() 一起使用时,我都会在程序结束时收到此错误。

如果我使用 asyncio 运行多个 suprocesses,则会在每个进程的末尾打印错误。

虽然它不会影响我的程序,但我想找到源并解决问题。谢谢您的帮助!

追溯:

Future exception was never retrieved
future: <Future finished exception=BrokenPipeError(32, 'The pipe has been ended', None, 109, None)>
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\asyncio\subprocess.py", line 153, in _feed_stdin
    await self.stdin.drain()
  File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\asyncio\streams.py", line 387, in drain
    await self._protocol._drain_helper()
  File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\asyncio\streams.py", line 197, in _drain_helper
    await waiter
  File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 379, in _loop_writing
    f.result()
  File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\asyncio\windows_events.py", line 812, in _poll
    value = callback(transferred, key, ov)
  File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\asyncio\windows_events.py", line 538, in finish_send
    return ov.getresult()
BrokenPipeError: [WinError 109] The pipe has been ended

代码:

async def get(cs, url):
    async with cs.get(url) as r:
        b = b''
        while True:
            chunk = await r.content.read(4000000)
            b += chunk
            if not chunk:
                break
        
        if int(r.headers['content-length']) < 8000000:
            result = BytesIO(b)
            return [result, 'full']
        else:
            command = f"ffmpeg -y -i - -c:v copy -fs 8000000 -f matroska -"
            sp = await asyncio.create_subprocess_shell(command, stdin=asyncio.subprocess.PIPE,
                stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
            stdout, stderr = await sp.communicate(b)
            sp.wait()

            print(stderr.decode())
            print(len(stdout))
            output = str(stderr)
            index_d = output.find('Duration: ')
            index_t = output.rfind('time=')
            duration = await get_sec(output[index_d + 10:].split(",")[0])
            time_ = await get_sec(output[index_t + 5:].split(" ")[0])
            percentage = f"{round((time_ / duration) * 100)}%"

            result = BytesIO(stdout)
            return [result, 'preview', percentage]

async def main(urls):
    async with aiohttp.ClientSession() as cs:
            
        tasks = []
        for url in urls:
            task = asyncio.create_task(get(cs, url))
            tasks.append(task)
        
        results = []
        for task in tasks:
            result = await task
            results.append(result)
        
        return results

loop = asyncio.get_event_loop()
results = loop.run_until_complete(main(urls))

标签: ffmpegsubprocesspipepython-asynciobroken-pipe

解决方案


推荐阅读