我应该如何在 Makefile 中嵌入 python 脚本?
How should I embed a python script in a Makefile?
我想在 Makefile
中嵌入 python
脚本
我构建了一个 python -c
脚本(如下),它在我的 MacBook 中运行良好 Hyper terminal:
% python -c $'from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))'
由于我还不明白的原因,如果我用它构建一个 Makefile,这似乎会失败(注意:一个制表符是四个空格......我在 Makefile 中使用了制表符缩进)。
all:
$(shell python -c $'from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))')
运行 make all
目标...
% make all
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `python -c from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))''
make: `all' is up to date.
%
我为此苦恼了一段时间...
有人可以帮助解释 make all
失败的原因以及修复此 python -c
命令的最佳方法吗?我的 shell CLI python -c ...
命令在我的 MacBook 上成功启动 Docker 桌面。
我知道有非 python 方法可以解决这个特定问题...我需要一个通用的 python Makefile 解决方案。
由于 Python 的缩进要求,在 Makefile
中使用 python -c
很棘手。如果您想使用 Bash“C 风格”字符串,一个简单的解决方案是使用 SHELL=/bin/bash
:
SHELL=/bin/bash
all:
# python command must be wrapped in single quotes _and_ have double dollar sign in front
python -c $$'from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))'
(注意美元符号需要加倍才能转义它。显然,这限制了 Makefile
到 Bash 可用的系统的可移植性。$'...'
语法允许您在字符串中使用 \n
和 \t
等转义码,并将它们分别扩展为换行符和制表符。此构造特别需要前导美元符号和字符串周围的单引号 - 只是 '...'
做的事情略有不同,而 $"..."
做的事情 完全 不同。)
您还可以 define
一个 make
多行变量。但在这个孤立的案例中,Python 无论如何都没有发挥任何作用。
all:
open --background -a Docker
如果 open
失败,make
将终止并显示错误消息;从 Python 打印本质上相同的消息似乎是多余的。如果你想在错误的情况下继续,你可以这样做
all:
open --background -a Docker || \
echo "Docker desktop failed to launch: exit-code: $$?"
...尽管我认为 Python 脚本失败(原文如此)只是一个错误。
我找到了一种相当简单的方法来将多行 python 脚本嵌入 Makefile
...
- 另存为
Makefile
...
define MULTILINE_PYTHON_SCRIPT
###########################################
# Start multiline python string here...
###########################################
from subprocess import getstatusoutput as gso
print("Here we go:")
for hello_int in [1, 2, 3,]:
print(' Hello World %i' % hello_int)
retval, _ = gso("ls -la")
assert retval==0, "ls command execution failed"
###########################################
# End of multiline python string...
###########################################
endef
export MULTILINE_PYTHON_SCRIPT
EMBEDDED_PY := python -c "$$MULTILINE_PYTHON_SCRIPT"
.PHONY: nothing
nothing:
echo "raw makefile command"
.PHONY: test
test:
$(EMBEDDED_PY)
.PHONY: all
all:
open --background -a Docker
- 测试输出:
% make nothing
echo "raw makefile command"
raw makefile command
%
% make test
python -c "$MULTILINE_PYTHON_SCRIPT"
Here we go:
Hello World 1
Hello World 2
Hello World 3
%
%
我想在 Makefile
python
脚本
我构建了一个 python -c
脚本(如下),它在我的 MacBook 中运行良好 Hyper terminal:
% python -c $'from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))'
由于我还不明白的原因,如果我用它构建一个 Makefile,这似乎会失败(注意:一个制表符是四个空格......我在 Makefile 中使用了制表符缩进)。
all:
$(shell python -c $'from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))')
运行 make all
目标...
% make all
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `python -c from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))''
make: `all' is up to date.
%
我为此苦恼了一段时间...
有人可以帮助解释 make all
失败的原因以及修复此 python -c
命令的最佳方法吗?我的 shell CLI python -c ...
命令在我的 MacBook 上成功启动 Docker 桌面。
我知道有非 python 方法可以解决这个特定问题...我需要一个通用的 python Makefile 解决方案。
由于 Python 的缩进要求,在 Makefile
中使用 python -c
很棘手。如果您想使用 Bash“C 风格”字符串,一个简单的解决方案是使用 SHELL=/bin/bash
:
SHELL=/bin/bash
all:
# python command must be wrapped in single quotes _and_ have double dollar sign in front
python -c $$'from subprocess import getstatusoutput\noutput=getstatusoutput("open --background -a Docker")\nif int(output[0])>0:\n print("Docker desktop failed to launch: exit-code:{}".format(output[0]))'
(注意美元符号需要加倍才能转义它。显然,这限制了 Makefile
到 Bash 可用的系统的可移植性。$'...'
语法允许您在字符串中使用 \n
和 \t
等转义码,并将它们分别扩展为换行符和制表符。此构造特别需要前导美元符号和字符串周围的单引号 - 只是 '...'
做的事情略有不同,而 $"..."
做的事情 完全 不同。)
您还可以 define
一个 make
多行变量。但在这个孤立的案例中,Python 无论如何都没有发挥任何作用。
all:
open --background -a Docker
如果 open
失败,make
将终止并显示错误消息;从 Python 打印本质上相同的消息似乎是多余的。如果你想在错误的情况下继续,你可以这样做
all:
open --background -a Docker || \
echo "Docker desktop failed to launch: exit-code: $$?"
...尽管我认为 Python 脚本失败(原文如此)只是一个错误。
我找到了一种相当简单的方法来将多行 python 脚本嵌入 Makefile
...
- 另存为
Makefile
...
define MULTILINE_PYTHON_SCRIPT
###########################################
# Start multiline python string here...
###########################################
from subprocess import getstatusoutput as gso
print("Here we go:")
for hello_int in [1, 2, 3,]:
print(' Hello World %i' % hello_int)
retval, _ = gso("ls -la")
assert retval==0, "ls command execution failed"
###########################################
# End of multiline python string...
###########################################
endef
export MULTILINE_PYTHON_SCRIPT
EMBEDDED_PY := python -c "$$MULTILINE_PYTHON_SCRIPT"
.PHONY: nothing
nothing:
echo "raw makefile command"
.PHONY: test
test:
$(EMBEDDED_PY)
.PHONY: all
all:
open --background -a Docker
- 测试输出:
% make nothing
echo "raw makefile command"
raw makefile command
%
% make test
python -c "$MULTILINE_PYTHON_SCRIPT"
Here we go:
Hello World 1
Hello World 2
Hello World 3
%
%