我有一个驱动许多软件包安装的脚本。在一个地方,它使用点子。其中一个软件包需要它自己的构建过程的特殊命令行参数。
pip使安装选项能够传递到构建过程,如下所示:
pip install -U --timeout 30 $ options --install-option =' - hdf5 = / usr / local / hdf5'tables
- install-option是pip的参数。它设置的值--hdf5 = / usr / local / hdf5将被传递给构建过程。因此,单引号必须在那里将所有文本组合为一个遵循等号的参数。您可能会说我可以使用双引号来包围install-option的值。好吧,在命令行我可以。
但是,这是增加的复杂性。这是一个脚本。 pip命令的参数值将传递给数组中的函数。此包的数组条目如下所示:
( “表,PIP ,, - 安装选项= ' - HDF5 =的/ usr /本地/ HDF5'”)
接收函数使用此片段中的set解析数组条目:
IFS="," # to split apart the pkg array entries
for pkg in "${pkglist[@]}"; do
set -- ${pkg}
if [[ "$2" == "pip" ]]; then # $1 is pkg, $2 is pip, $3 is url, $4 is options
DoPip $1 $3 $4
...
因此,对于这个软件包,DoPip看到:DoPip表'' - install-option =' - hdf5 = / usr / local / hdf5'
DoPip中出现问题。当我需要运行pip本身时,我无法弄清楚如何扩展最后一个参数。我做了一堆调试,看看会发生什么。会发生什么是3美元的价值被简单地删除 - 它只是消失了。它将以字符串形式回显,但它不会作为命令的一部分工作。
查看功能DoPip。为了帮助调试,我将参数重新分配给显式变量。这没有必要,但有助于确保我没有愚蠢的错误。
DoPip() {
# run pip command to install packages
# arguments: 1: package-name 2: optional source <URL>
# 3: optional pip options
pkgname=$1
url=$2
options=$3
接下来,如果url是非空的,我将变量源设置为pkgname或url。我正在跳过这个片段 - 它有效。
要调试,我回显重新分配的参数:
echo "1. The inbound arguments are: $pkgname $url $options"
输出LOOKS就像它应该工作:
这是使用这些参数实际运行pip的语句:
pip install -U --timeout 30 $options $source
通过调试,这是Bash实际看到和运行的内容:
+ pip install -U --timeout 30 tables
哇! $ options有什么变化?没了!实际上,在此语句之前,我重复回显以验证脚本中间没有任何部分导致值被刷新。不是问题。我可以立即回复$ options的价值 - 没关系。然后,它消失了。
我无法弄清楚发生了什么或如何做到这一点。我已经尝试了各种方法来转义数组中的单引号,其中最初根据读取非常特殊的单引号创建字符串文字。什么都行不通。整个变量扩张就消失了。
我尝试过以各种方式进行扩展:
pip install -U --timeout 30 "$options" $source
这不起作用。选项中的字符串出现但被单引号括起,因此pip命令会引发错误。接下来,我试过了:
pip install -=U --timeout 30 "${options}" $source
也失败了:单引号和花括号出现,pip再次不高兴。
--install-options参数是必不可少的。如果没有它,构建就会失败。
必须有一些方法可以做到这一点。有什么建议吗?
答案 0 :(得分:0)
$ bash -version
GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
此脚本提供了以下输出:
#!/bin/bash -vx
options=--install-option='--hdf5=/usr/local/hdf5'
source=tables
pip install -U --timeout 30 $options $source
$ ./script.sh
#!/bin/bash -vx
options=--install-option='--hdf5=/usr/local/hdf5'
+ options=--install-option=--hdf5=/usr/local/hdf5
source=tables
+ source=tables
pip install -U --timeout 30 $options $source
+ pip install -U --timeout 30 --install-option=--hdf5=/usr/local/hdf5 tables
Downloading/unpacking tables
Downloading tables-3.1.1.tar.gz (6.7MB): 6.7MB downloaded
Running setup.py (path:/tmp/pip_build_ankur/tables/setup.py) egg_info for package tables
* Using Python 2.7.3 (default, Feb 27 2014, 19:58:35)
* Found numpy 1.6.1 package installed.
.. ERROR:: You need numexpr 2.0.0 or greater to run PyTables!
Complete output from command python setup.py egg_info:
* Using Python 2.7.3 (default, Feb 27 2014, 19:58:35)
* Found numpy 1.6.1 package installed.
.. ERROR:: You need numexpr 2.0.0 or greater to run PyTables!
----------------------------------------
Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_ankur/tables
Storing debug log for failure in /home/ankur/.pip/pip.log
忽略错误,我看到$ options的值被正确读取并传递给shell。
答案 1 :(得分:0)
所有这些都嵌入在一个非常大的脚本中。我创建了一个较短的版本来专注于这个问题。最后,我采用了一种不同的方法,依赖于环境变量HDF5_DIR而不是pd的cmd线路开关。
显然,你只能做一个或另一个。在任何情况下,在清理过的代码中传递参数,但如果存在环境变量则这是一个错误。去图。
如果有人有兴趣,我会有更短的代码。
当敲头太猛时,远离墙壁,找到另一种方法。我打电话给这个人。
答案 2 :(得分:0)
python包表(也称为potables)的安装程序通过提供给pip的构建开关或通过在开始构建之前设置环境变量来查找hdf5库。在bash脚本中,在开始构建表之前立即创建环境变量更容易/更可靠。没有必要把它放在bash_profile中。环境变量只需要存在于构建表的shell中。安装表后,不再需要环境变量。
在此代码片段中,pkglist是要安装的模块数组,InstallPackages是一个遍历数组并调用相应安装程序的函数:在这种情况下为pip。
if [[ "$hdf5exists" == "True" ]]; then
# assert hdf libraries installed
export HDF5_DIR=/usr/local/hdf5
pkglist=("${hdf5_pkglist[@]}") # only install Python wrappers for hdf5
InstallPackages
fi
所以,这是我采用的解决方案。