将 bash 数组传递给 python 列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33829444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:55:33  来源:igfitidea点击:

passing bash array to python list

pythonarrayslinuxbash

提问by Jim

I'm trying to pass an array from bash to python using the old getenv method however I keep getting this error:

我正在尝试使用旧的 getenv 方法将数组从 bash 传递到 python,但是我不断收到此错误:

./crcFiles.sh: line 7: export: `0021': not a valid identifier
Traceback (most recent call last):
  File "/shares/web/vm3618/optiload/prog/legalLitres.py", line 30, in <module>
    for i in mdcArray.split(' '):
AttributeError: 'NoneType' object has no attribute 'split'

could someone please explain why the $mdcNo isn't passing from bash to python successfully?

有人可以解释一下为什么 $mdcNo 没有成功地从 bash 传递到 python 吗?

Code .sh:

代码.sh:

#!/bin/bash

mdcNo=('0021' '0022' '0036' '0055' '0057' '0059' '0061' '0062' '0063' '0065' '0066' '0086' '0095' '0098' '0106' '0110' '0113' '0114' '0115' '0121' '0126' '0128' '0135' '0141' '0143' '0153' '0155' '0158')

localDIR=/shares/web/vm3618/optiload/prog

export mdcNo

$localDIR/legalLitres.py


for i in "${mdcNo[@]}"
do
echo $i
cp $localDIR/MDC$i/*/QqTrkRec.txt $localDIR/crccalc/.
cd $localDIR/crccalc
./crccalc.py QqTrkRec.txt
cp $localDIR/crccalc/QqTrkRec.txt $localDIR/MDC$i/.
done

code .py:

代码.py:

#!/usr/bin/python

import glob
import os

mdcArray = os.getenv('mdcNo')

#Legal Litres that hex and decimal
legalLitresHex = "47E0"
legalLitresTxt = '18,400'

# file name and Legal Litres header
legalHeader = ":00F0:"
hexFile = "QqTrkRec.txt"

# insert comment to explain change
comment = "#\n#  2015 Nov 20:  Legal Litres changed to 18,400\n#\n"
commentFlag0 = "#  SetDATA"
commentFlag1 = "# SetDATA"

try:
    for i in mdcArray.split(' '):


        line = ""

        Qqfile = glob.glob("/shares/web/vm3618/optiload/prog/MDC"+i+"/*/"+hexFile) 
        outFile = Qqfile[0]+".new"

        print i

回答by Mark Reed

When you exporta variable from the shell, what you are really doing is adding it to the POSIX "environment" array that all child processes inherit. But the POSIX environment is a flat array of name=value strings; it cannot itself contain arrays. So Bash doesn't even attempt to put arrays there. It will let you exportan array variable, and doing so even sets the "exported" flag on that variable, but the environment is not touched. You can verify this fact by running envor a new copy of bashand looking for the "exported" variable:

当您export从 shell 获取变量时,您真正要做的是将其添加到所有子进程继承的 POSIX“环境”数组中。但是 POSIX 环境是 name=value 字符串的平面数组;它本身不能包含数组。所以 Bash 甚至不会尝试将数组放在那里。它会给你export一个数组变量,这样做甚至会在该变量上设置“导出”标志,但不会触及环境。您可以通过运行envbash查找“exported”变量的新副本来验证这一事实:

$ export myArr=(this is an array)
$ bash -c 'echo "${myArr[@]}"'

$

(Some other array-having shells, notably ksh, will actually export an array variable to the environment, but the exported value will consist of only the first element of the array.)

(其他一些具有数组的 shell,特别是 ksh,实际上会将数组变量导出到环境中,但导出的值将仅包含数组的第一个元素。)

If you want to pass a shell array to the Python script, your best bet is to do so as command line arguments. If you run the Python script like this:

如果要将 shell 数组传递给 Python 脚本,最好的办法是将其作为命令行参数进行。如果您像这样运行 Python 脚本:

python code.py "${mdcNo[@]}"

... then the Python code can just loop over sys.argv, which is always a list. (Specifically, the passed-in array will be the slice sys.argv[1:], since sys.argv[0]is always set to the name of the script itself.)

...然后 Python 代码可以循环遍历sys.argv,它始终是一个列表。(具体来说,传入的数组将是 slice sys.argv[1:],因为sys.argv[0]它始终设置为脚本本身的名称。)

If that's not an option, then you'll have to set the environment variable to a string with some delimiter between elements and split it inside the Python code. Something like this..

如果这不是一个选项,那么您必须将环境变量设置为在元素之间带有一些分隔符的字符串,并将其拆分到 Python 代码中。像这样的东西..

Bash:

重击:

export mdcList='0021,0022,0036,0055,0057,0059,0061,0062,0063,0065,0066,0086,0095,0098,0106,0110,0113,0114,0115,0121,0126,0128,0135,0141,0143,0153,0155,0158'

Or you can build the string up from the array:

或者您可以从数组构建字符串:

export mdcList=${mdcNo[0]}
for i in "${mdcNo[@]:1}"; do
   mdcList+=,$i
done

Either way, the Python script can recover the array as a list like this:

无论哪种方式,Python 脚本都可以将数组恢复为如下列表:

mdc_no = os.getenv('mdcList').split(',')

If your array elements aren't just numbers, you can replace the comma with something less likely to show up in an element; the traditional choice would be the ASCII Unit Separator (U+001F, $'\x1f'in Bash, '\x1f'in Python).

如果您的数组元素不仅仅是数字,您可以将逗号替换为不太可能出现在元素中的内容;传统的选择是 ASCII 单位分隔符(U+001F,$'\x1f'在 Bash 中,'\x1f'在 Python 中)。

回答by lorenzog

I think Mark Reed already gave you a very good explanation and solution. Nevertheless, have you considered using python's argparse?

我认为 Mark Reed 已经给了你很好的解释和解决方案。不过,您是否考虑过使用 python 的argparse

#!/usr/bin/env python
import argparse


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('stuff', nargs='+')
    args = parser.parse_args()
    print args.stuff

if __name__ == '__main__':
    main()

Use:

用:

$ mdcNo=('0021' '0022' '0036' '0055' '0057' '0059' '0061' '0062' '0063' '0065' '0066' '0086' '0095' '0098' '0106' '0110' '0113' '0114' '0115' '0121' '0126' '0128' '0135' '0141' '0143' '0153' '0155' '0158')
$ python argp.py "${mdcNo[@]}"
['0021', '0022', '0036', '0055', '0057', '0059', '0061', '0062', '0063', '0065', '0066', '0086', '0095', '0098', '0106', '0110', '0113', '0114', '0115', '0121', '0126', '0128', '0135', '0141', '0143', '0153', '0155', '0158']