Makefile while loop try/catch 相当于先用 conda 安装 python 依赖然后用 pip
Makefile while loop try/catch equivalent to install python dependencies first with conda then with pip
我需要 运行 一个 while
循环来安装 Python 依赖项。在 Python 世界中,最近有 2 种安装依赖项的方法已经建立:
- 使用
conda
(对于某些人来说,这是 "robust/stable/desired way",由名为 Anaconda/Miniconda 的 "Python distribution" 提供),
- 使用
pip
(在过去几年中作为 Python 本身的官方方式)。
"pseudocode"应该是:
- 尝试使用
conda
命令安装依赖项
- 如果失败则使用
pip
命令安装
在 Python 世界中,依赖项在 requirements.txt
文件中指定,通常是精确版本 (==
) 每行一个依赖项,模式为 <MY_DEPENDENCY>==<MY_VERSION>
。
等效的 bash
所需命令是:while read requirement; do conda install --yes $requirement || pip install $requirement; done < requirements.txt
,但是由于我不完全了解的原因,这在 GNU make
/Makefile
世界中不起作用得到.
我尝试了几种不同的 while
循环 - 都没有成功。基本上,一旦 conda
命令失败,我就无法继续进行 pip
尝试。我不确定为什么会发生这种情况(因为它在 "normal bash
" 中有效)并且我找不到管理某种低级 try/catch 模式的方法(对于那些熟悉高级编程语言的人)。
这是我最后一次尝试,但没有成功,因为它在 conda
失败时停止:
foo-target:
# equivalent to bash: conda install --yes $requirement || pip install $requirement;
while read requirement; do \
conda install --yes $requirement ; \
[ $$? != 0 ] || pip install $requirement; \
done < requirements.txt
我如何确保首先使用 conda
尝试在 requirements.txt
中安装每个要求,当 conda
失败时,然后使用 pip
?
为什么我的代码不起作用?我看到有人指出 sh
和 bash
之间的差异,但我无法隔离问题。
编辑:
我最终在 Makefile
中使用 bash
命令解决了问题,但是 我发现这个解决方案并不理想,因为我还需要维护单行 bash 脚本中的另一段代码(见下文),有没有办法将所有内容保存在 Makefile
中,完全避免 bash
?
Makefile
目标:
foo-target:
bash install-python-dependencies.sh
bash
一行脚本:
#!/usr/bin/env bash
while read requirement; do conda install --yes $requirement || pip install $requirement; done < requirements.txt
我可以直接从命令行 运行 脚本 (bash
),我也可以 运行 它来自 Makefile
,但是 我想摆脱 bash 脚本并始终执行 make foo-target
而不使用 bash
(即使在 Makefile
内部也避免 bash
).
如上所示,您的 makefile 将按预期工作,除了您必须转义 shell 变量中的 $
,例如 $$requirement
.
我无法通过简化示例来模拟行为来重现您的问题:
foo-target:
for i in 1 2 3; do \
echo conda; \
test $$i -ne 2; \
[ $$? -eq 0 ] || echo pip; \
done
给出预期的输出:
$ make
conda
conda
pip
conda
您是否已将 .POSIX:
目标添加到您的 makefile 中,但此处未显示?如果我这样做,那么我就会得到你声称看到的行为:
conda
make: *** [Makefile:2: foo-target] Error 1
原因在 the manual for .POSIX
中描述:
In particular, if this target is mentioned then recipes will be invoked as if the shell had been passed the '-e' flag: the first failing command in a recipe will cause the recipe to fail immediately.
如果您想保持 .POSIX
模式但又不想出现此错误,最简单的方法是使用您在第一个示例中展示的方法;我不知道你为什么停止使用它:
foo-target:
while read requirement; do \
conda install --yes $$requirement || pip install $$requirement; \
done < requirements.txt
我需要 运行 一个 while
循环来安装 Python 依赖项。在 Python 世界中,最近有 2 种安装依赖项的方法已经建立:
- 使用
conda
(对于某些人来说,这是 "robust/stable/desired way",由名为 Anaconda/Miniconda 的 "Python distribution" 提供), - 使用
pip
(在过去几年中作为 Python 本身的官方方式)。
"pseudocode"应该是:
- 尝试使用
conda
命令安装依赖项 - 如果失败则使用
pip
命令安装
在 Python 世界中,依赖项在 requirements.txt
文件中指定,通常是精确版本 (==
) 每行一个依赖项,模式为 <MY_DEPENDENCY>==<MY_VERSION>
。
等效的 bash
所需命令是:while read requirement; do conda install --yes $requirement || pip install $requirement; done < requirements.txt
,但是由于我不完全了解的原因,这在 GNU make
/Makefile
世界中不起作用得到.
我尝试了几种不同的 while
循环 - 都没有成功。基本上,一旦 conda
命令失败,我就无法继续进行 pip
尝试。我不确定为什么会发生这种情况(因为它在 "normal bash
" 中有效)并且我找不到管理某种低级 try/catch 模式的方法(对于那些熟悉高级编程语言的人)。
这是我最后一次尝试,但没有成功,因为它在 conda
失败时停止:
foo-target:
# equivalent to bash: conda install --yes $requirement || pip install $requirement;
while read requirement; do \
conda install --yes $requirement ; \
[ $$? != 0 ] || pip install $requirement; \
done < requirements.txt
我如何确保首先使用 conda
尝试在 requirements.txt
中安装每个要求,当 conda
失败时,然后使用 pip
?
为什么我的代码不起作用?我看到有人指出 sh
和 bash
之间的差异,但我无法隔离问题。
编辑:
我最终在 Makefile
中使用 bash
命令解决了问题,但是 我发现这个解决方案并不理想,因为我还需要维护单行 bash 脚本中的另一段代码(见下文),有没有办法将所有内容保存在 Makefile
中,完全避免 bash
?
Makefile
目标:
foo-target:
bash install-python-dependencies.sh
bash
一行脚本:
#!/usr/bin/env bash
while read requirement; do conda install --yes $requirement || pip install $requirement; done < requirements.txt
我可以直接从命令行 运行 脚本 (bash
),我也可以 运行 它来自 Makefile
,但是 我想摆脱 bash 脚本并始终执行 make foo-target
而不使用 bash
(即使在 Makefile
内部也避免 bash
).
如上所示,您的 makefile 将按预期工作,除了您必须转义 shell 变量中的 $
,例如 $$requirement
.
我无法通过简化示例来模拟行为来重现您的问题:
foo-target:
for i in 1 2 3; do \
echo conda; \
test $$i -ne 2; \
[ $$? -eq 0 ] || echo pip; \
done
给出预期的输出:
$ make
conda
conda
pip
conda
您是否已将 .POSIX:
目标添加到您的 makefile 中,但此处未显示?如果我这样做,那么我就会得到你声称看到的行为:
conda
make: *** [Makefile:2: foo-target] Error 1
原因在 the manual for .POSIX
中描述:
In particular, if this target is mentioned then recipes will be invoked as if the shell had been passed the '-e' flag: the first failing command in a recipe will cause the recipe to fail immediately.
如果您想保持 .POSIX
模式但又不想出现此错误,最简单的方法是使用您在第一个示例中展示的方法;我不知道你为什么停止使用它:
foo-target:
while read requirement; do \
conda install --yes $$requirement || pip install $$requirement; \
done < requirements.txt