asyncio.create_subprocess_exec 控制台 window 为每次调用打开

asyncio.create_subprocess_exec console window opening for each call

我有一个异步运行子进程命令和 returns 结果的函数。它看起来像这样:

import asyncio
async def async_subprocess_command(*args):
    # Create subprocess
    process = await asyncio.create_subprocess_exec(
        *args,
        # stdout and stderr must a pipe to be accessible as process.stdout
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)
    # Wait for the subprocess to finish
    stdout, stderr = await process.communicate()

    #Remove final carriage return from string
    stdout_formatted = stdout.decode().strip().replace('\r', '')
    stderr_formatted = stderr.decode().strip().replace('\r', '')
    # Return stdout and sterr
    return stdout_formatted, stderr_formatted

如果我能负担得起同步工作,我倾向于使用这个对子进程模块的调用:

import subprocess
subprocess.getoutput([parameter1,parameter2,parameter3])

当我同步调用 subprocess.getoutput 时(假设我正在调用外部工具),没有控制台 window 打开。当我异步调用 asyncio.create_subprocess_exec 时(同样,假设我调用的是外部工具),控制台 window 会在每次调用它时弹出一小段时间,并使计算机难以交互,直到异步调用完成。

有没有一种方法可以在不弹出控制台 window 的情况下异步调用 asyncio.create_subprocess_exec

我在另一个函数中找到了答案:

async def async_subprocess_command(cmd):
        '''
        cmd should be a string exactly as you 
        write into the cmd line
        '''
        process = await asyncio.create_subprocess_shell(cmd, 
                stdin=None, stderr=asyncio.subprocess.PIPE, 
                stdout=asyncio.subprocess.PIPE)

        stdout, stderr = await process.communicate()

        stdout_formatted = stdout.decode().strip().replace('\r', '')
        stderr_formatted = stderr.decode().strip().replace('\r', '')

        return stdout_formatted, stderr_formatted

根据 eryksun 的建议,我能够使用带有额外参数 (creationflags=DETACHED_PROCESS) 的原始函数。它比在第一个答案中使用 asyncio.create_subprocess_shell 函数稍快,并且按预期工作。有关其他好处的更多信息,请参阅上面的 eryksun 评论。

async def async_subprocess_command(*args):

    #CREATE_NO_WINDOW = 0x08000000 using detatched_process is slightly faster
    DETACHED_PROCESS = 0x00000008
    # Create subprocess
    process = await asyncio.create_subprocess_exec(
        *args,
        # stdout and stderr must a pipe to be accessible as process.stdout
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE,
        creationflags=DETACHED_PROCESS,
        )
    # Wait for the subprocess to finish
    stdout, stderr = await process.communicate()

    #Remove final carriage return from string
    stdout_formatted = stdout.decode().strip().replace('\r', '')
    stderr_formatted = stderr.decode().strip().replace('\r', '')

    # Return stdout and sterr
    return stdout_formatted, stderr_formatted