开发者问题收集

使用 $(...) 将 shell 命令转换为 Python subprocess.Popen()

2019-08-12
523

我有一个 docker 命令,它可以从终端运行并给出预期结果。

现在我需要将此脚本重写为 python。每当尝试运行 python 时,都会出现以下错误: 未知简写标志:-a 中的“a” 请参阅“docker logs --help”。

以下是命令。我一直在尝试使用列表数组,但似乎没有任何效果。

终端中的原始命令:

docker logs $(docker ps -a -f status=exited| grep -w "dev"| awk '{print $1}')

Python 等效命令:

 output = subprocess.Popen([
    "docker",
    "logs",
    "$(docker",
    "ps",
    "-a",
    "-f",
    "status=exited",
    "|",
    "grep",
    "-w",
    "'dev'",
    "|",
    "awk",
    "'{print $1}'"
])
2个回答

在 bash 中,$(...) 作为另一个进程运行,输出将代替它。从解释器的角度来看,里面的所有内容都是一个参数。

您需要先运行 docker ps -a -f status=exited| grep -w "dev"| awk '{print $1}' ,并将其输出用作 docker logs ... 的参数。

但是,使用 python 您不需要通过 grep 和 awk 进行管道传输,您可以使用列表推导进行映射和过滤:

import subprocess
containers = subprocess.Popen(["docker", "ps", "-a", "-f", "status=exited"], stdout=subprocess.PIPE)
lines = [l.decode('utf-8') for l in containers.stdout.readlines()] # Convert bytes to strings
filtered = [line for line in lines if 'dev' in line] # Keep only lines with keyword
ids = [l.split()[0] for l in filtered]               # Select first column


for i in ids:
    print(">>>> Logs for " + i)
    subprocess.call(['docker', 'logs', i])
patonw
2019-08-12

您的原始 bash 代码不运行一个命令——而是运行四个命令!

  • 首先,它运行一个由三个命令组成的管道,每个命令的标准输出连接到下一个命令的标准输入:

    • ['docker', 'ps', '-a', '-f', 'status=exited']
    • ['grep', '-w', 'dev']
    • ['awk', '{print $1}']
  • 其次,它使用该管道最后一部分( awk 命令)的输出来构造最终的 docker logs 命令:

    • ['docker', 'logs'] + shlex.split(awk_pipeline_output) (大致如此;因为您没有正确引用,它还会将该 split 结果的每个单词作为 glob 表达式进行评估)。

因此,如果您真的想将该代码转换为 Python,并使其保持原样,则它看起来像:

from subprocess import Popen, PIPE
import shlex

p1 = Popen(['docker', 'ps', '-a', '-f', 'status=exited'], stdout=PIPE)
p2 = Popen(['grep', '-w', 'dev'], stdin=p1.stdout, stdout=PIPE)
p3 = Popen(['awk', '{print $1}'], stdin=p2.stdout, stdout=PIPE)
p1.stdout.close()
p2.stdout.close()
pipeline_output, _ = p3.communicate()

p4 = Popen(['docker', 'logs'] + shlex.split(pipeline_outlet))
Charles Duffy
2019-08-12