使用 $(...) 将 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