来自 python 脚本的 运行 shell 命令与 \n

Running shell command from python script with \n

我正在尝试 运行 shell 命令

echo -e 'FROM busybox\nRUN echo "hello world"' | docker build -t myimage:latest -

来自使用子进程的 jupyter notebook

我试过代码

p = subprocess.Popen('''echo -e 'FROM busybox\nRUN echo "hello world"' | docker build -t myimage:latest - ''', shell=True)
p.communicate()

和一些使用 运行() 或 call() 的迭代,但每次输出都是

-e 'FROM busybox

好像是换行符\n导致的问题。有解决问题的想法吗?

\n 被 Python 解析为文字换行符。您可以通过使用原始字符串来避免这种情况,

p = subprocess.run(
    r'''echo -e 'FROM busybox\nRUN echo "hello world"' | docker build -t myimage:latest - ''',
    shell=True, check=True)

但我会推荐 运行 单个进程并传入 Python 的输出;这也是 avoids a shell,这通常是可取的。

p = subprocess.run(['docker', 'build', '-t', 'myimage:latest', '-'],
    input='FROM busybox\nRUN echo "hello world"',
    text=True, check=True)

另请注意,我们更喜欢 subprocess.run() 而不是更原始的 subprocess.Popen();正如文档中所建议的那样,您希望尽可能避免使用这种低级功能。对于 check=True,我们还注意将任何子流程错误传播到 Python 父流程。

顺便说一句,printfecho -e 更通用、更便携;我通常会建议您完全避免 echo -e

这个 ideone demo with nl instead of docker build 展示了变化,并且巧合地证明了为什么你想要避免 echo -e 即使你的登录 shell 例如Bash(在这种情况下,您认为应该支持它;但是 subprocess 不使用您的登录名 shell)。