【问题标题】:Subprocess.Popen reading stdout but execution not finishingSubprocess.Popen 读取标准输出但执行未完成
【发布时间】:2020-07-20 17:30:09
【问题描述】:

在使用 subprocess.Popen 时遇到一些麻烦。

这是我正在使用的代码:

def parse_replay(rep_record):
    rep_path = rep_record['rep_path']
    screp_cmd = f"{cwd}/screp -cmds -mapres -maptiles '{rep_path.replace('..', os.path.dirname(cwd))}'"
    p = subprocess.Popen(screp_cmd, shell=True)
    out = p.stdout.read()
    rep_action_log = json.loads(out)
    return rep_action_log

如果我使用 shell=False,我会收到文件未找到错误。 使用 shell=True 时,命令被执行但函数没有返回(显然它一直在监听命令的输出)。

你知道有什么方法可以在正确完成我的函数执行的同时捕获我的命令的标准输出吗?

PS:screp 是一个将 json 信息输出到标准输出的 CLI https://github.com/icza/screp

【问题讨论】:

  • 这看起来不像是一个您有充分理由使用shell=True 的命令,并且冒着随之而来的安全漏洞的风险。为什么不将您的参数列表作为列表传递,以便您可以使用shell=False
  • 即:screp_cmd = [ f"{cwd}/screp", "-cmds", "-mapres", "-maptiles", f"{rep_path.replace('..', os.path.dirname(cwd))}"]
  • 也就是说,能够捕获标准输出与shell=Trueshell=False 无关。您无法捕获标准输出,因为您没有通过 stdout=subprocess.PIPE
  • ...理想情况下,使用subprocess.communicate(),同时明确设置stdinstdoutstderr 中的所有三个(如何设置取决于您希望在 stderr 上发生什么,以及您是否希望从 Python 进程本身继承 stdin)。
  • ...无论如何,为了让任何人能够全面回答这个问题,他们需要了解更多关于screp 的信息——它从哪些文件描述符中读取、写入和写入的文件什么顺序。理想情况下,更好的minimal reproducible example 只需要人们已经拥有的工具,因此没有这个“screp”工具的人可以自己看到问题。

标签: python subprocess


【解决方案1】:

所以查尔斯的 cmets 工作了!

标记列表中的第一个格式可让您避免使用 shell=True。 第二个 stoud=subprocess.PIPE 可让您捕获标准输出。

def parse_replay(rep_record):
    rep_path = rep_record['rep_path']
    screp_cmd = [f"{cwd}/screp", "-cmds", "-mapres", "-maptiles", f"{rep_path.replace('..', os.path.dirname(cwd))}"]
    p = subprocess.Popen(screp_cmd, stdout=subprocess.PIPE)
    out = p.stdout.read()
    rep_action_log = json.loads(out)
    return rep_action_log

【讨论】:

    最近更新 更多