You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

异步子进程流式输出在CMD中顺序错乱问题求助

异步调用子进程时CMD中stdout输出顺序错乱(PyCharm中正常)

我编写了test.py和test1.py两个文件,test.py通过异步方式调用test1.py并在控制台展示其输出。在PyCharm中运行test.py时输出顺序正常,但在Command Prompt(CMD)中运行时,stdout内容未按预期顺序输出,出现了顺序错乱的情况。

test1.py代码

import logging
import time

logging.error(1)
time.sleep(1)
print(2)
time.sleep(1)
print(3)
time.sleep(1)
logging.error(4)
time.sleep(1)
logging.error(5)
time.sleep(1)
print(6)

test.py代码

import asyncio


async def _read_stream(stream, cb):
    while True:
        line = await stream.readline()
        if line:
            cb(line)
        else:
            break


async def _stream_subprocess(cmd, stdout_cb, stderr_cb):
    process = await asyncio.create_subprocess_exec(*cmd,
                                                   stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
    stdout_task = asyncio.create_task(_read_stream(process.stdout, stdout_cb))
    stderr_task = asyncio.create_task(_read_stream(process.stderr, stderr_cb))

    await asyncio.wait([stdout_task, stderr_task])
    return await process.wait()


def execute(cmd, stdout_cb, stderr_cb):
    asyncio.run(_stream_subprocess(cmd, stdout_cb, stderr_cb))


if __name__ == '__main__':
    print(execute(["pipenv", "run", "python", 'test1.py'],
                  lambda x: print("STDOUT: %s" % x),
                  lambda x: print("STDERR: %s" % x),))

PyCharm中正常输出

STDERR: b'ERROR:root:1\r\n'
STDOUT: b'2\r\n'
STDOUT: b'3\r\n'
STDERR: b'ERROR:root:4\r\n'
STDERR: b'ERROR:root:5\r\n'
STDOUT: b'6\r\n'

CMD中错乱输出

STDERR: b'ERROR:root:1\r\n'
STDERR: b'ERROR:root:4\r\n'
STDERR: b'ERROR:root:5\r\n'
STDOUT: b'2\r\n'
STDOUT: b'3\r\n'
STDOUT: b'6\r\n'

问题原因与解决方法

原因

Python在终端环境下,stdout默认是行缓冲(仅在遇到换行符或缓冲区满时输出),而stderr是无缓冲(实时输出)。在CMD中,子进程的stdout输出会被缓冲,直到进程结束才一次性输出;而异步读取stderr的任务会实时处理输出,最终导致顺序错乱。PyCharm的终端环境默认禁用了stdout缓冲,因此输出顺序正常。

解决方法

有三种可行的方案:

方案1:运行Python时添加-u参数禁用缓冲

修改test.py中调用子进程的命令,添加-u参数强制Python禁用stdout和stderr的缓冲:

if __name__ == '__main__':
    print(execute(["pipenv", "run", "python", '-u', 'test1.py'],
                  lambda x: print("STDOUT: %s" % x),
                  lambda x: print("STDERR: %s" % x),))

方案2:在test1.py中手动刷新stdout

每次调用print时添加flush=True参数,强制刷新输出:

import logging
import time

logging.error(1)
time.sleep(1)
print(2, flush=True)
time.sleep(1)
print(3, flush=True)
time.sleep(1)
logging.error(4)
time.sleep(1)
logging.error(5)
time.sleep(1)
print(6, flush=True)

方案3:在test1.py开头全局禁用stdout缓冲

通过修改stdout的文件对象,设置无缓冲模式:

import logging
import time
import sys
import os

# 禁用stdout缓冲
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering=0)

logging.error(1)
time.sleep(1)
print(2)
time.sleep(1)
print(3)
time.sleep(1)
logging.error(4)
time.sleep(1)
logging.error(5)
time.sleep(1)
print(6)

内容的提问来源于stack exchange,提问作者j.p

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:35:05