【问题标题】:asyncio.create_subprocess_exec console window opening for each call每次调用都打开 asyncio.create_subprocess_exec 控制台窗口
【发布时间】:2018-01-27 22:15:31
【问题描述】:

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

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 时(假设我正在调用外部工具),没有打开任何控制台窗口。当我异步调用asyncio.create_subprocess_exec 时(再次,假设我正在调用一个外部工具),每次调用都会弹出一个控制台窗口短暂的时间,这使得计算机难以交互,直到异步调用完成。

有没有办法在不弹出控制台窗口的情况下异步调用asyncio.create_subprocess_exec

【问题讨论】:

  • 使用进程creation flag。您可以通过creationflags=DETACHED_PROCESS 完全阻止分配控制台。或者,通过creationflags=CREATE_NO_WINDOW 分配一个不创建窗口的控制台。不创建窗口的选项可能看起来毫无意义,但它提高了与某些控制台应用程序的兼容性,因为该进程仍然附加到控制台,而且这个无窗口控制台将被子进程继承。相反,当使用分离的进程时,子进程将分配一个新的控制台。
  • 感谢您提供此信息 - 我能够使用此功能调整原始功能,甚至使其更快。

标签: windows python-3.x subprocess python-asyncio windows-console


【解决方案1】:

根据 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

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

    • 使用 shell 不是运行任意 cmd 的好解决方案,尤其是在任何子字符串来自用户输入的情况下。
    • 在我的用例中,没有用户输入 - cmd 是由应用程序根据调用的函数以及适用于该函数调用的参数编写的。
    猜你喜欢
    • 2013-06-30
    • 2011-07-01
    • 1970-01-01
    • 2014-04-20
    • 2010-12-26
    • 2012-06-07
    • 2017-02-26
    • 2020-04-19
    • 2013-06-01
    相关资源
    最近更新 更多