【问题标题】:Passing integer lists to python将整数列表传递给python
【发布时间】:2013-03-17 10:58:25
【问题描述】:

我想将 2 个整数列表作为输入传递给 python 程序。

例如,(从命令行)

python test.py --a 1 2 3 4 5 -b 1 2  

此列表中的整数范围为 1-50,列表 2 是列表 1 的子集。
有什么帮助/建议吗? argparse 是正确的模块吗?使用它有什么问题吗?

我试过了:

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--a', help='Enter list 1 ')
    parser.add_argument('--b', help='Enter list 2 ')
    args = parser.parse_args()
    print (args.a)

【问题讨论】:

  • 整数列表长什么样?
  • 显示您要使用的示例命令行?另外,添加常见的 cmets 作为问题的一部分。
  • 每个列表中的整数范围从 1 到 50。列表 2 是列表 1 的子集
  • 按照惯例,空格分隔的值是不同的参数。引用您的列表 ("1 2 3 4 5") 或用逗号分隔它们 (1,2,3,4,5) -- 然后 argparse 会将它们视为一个参数。
  • @katrielalex: nargs="+" 改变了这种行为,所以它把-a 1 2 3 作为一个列表吃掉了

标签: python command-line argparse


【解决方案1】:

argparse 支持nargs 参数,它告诉你它吃了多少个参数。 当nargs="+" 接受一个或多个参数时,您可以传递-b 1 2 3 4 并将其作为列表分配给b 参数

# args.py
import argparse

p = argparse.ArgumentParser()

# accept two lists of arguments
# like -a 1 2 3 4 -b 1 2 3
p.add_argument('-a', nargs="+", type=int)
p.add_argument('-b', nargs="+", type=int)
args = p.parse_args()

# check if input is valid
set_a = set(args.a)
set_b = set(args.b)

# check if "a" is in proper range.
if len(set_a - set(range(1, 51))) > 0: # can use also min(a)>=1 and max(a)<=50
    raise Exception("set a not in range [1,50]")

# check if "b" is in "a"
if len(set_b - set_a) > 0:
    raise Exception("set b not entirely in set a")

# you could even skip len(...) and leave just operations on sets
# ...

所以你可以运行:

$ python arg.py  -a 1 2 3 4 -b 2 20
Exception: set b not entirely in set a

$ python arg.py  -a 1 2 3 4 60 -b 2
Exception: set a not in range [1,50]

这是有效的:

$ python arg.py  -a 1 2 3 4 -b 2 3

【讨论】:

  • 好决定!如果需要列出 50 个数字,而不是 5,则为 true))
  • 因为你要求的设置检查。当您检查 B 是否在 A 中时,它是设置操作 - 检查设置 b - 设置 a 是否为空。对于范围,我可以使用min(a) &gt;= 1 and max(a) &lt;= 50,尽管我想保持一致。您问过“列表 2 是列表 1 的子集。”,不是吗?
  • 对于有效性检查,为什么不使用if all(1 &lt;= a &lt;= 50 for a in set_a)
  • @InbarRose:不错,如果我重构它,我会用它
【解决方案2】:

您可以将它们作为字符串传递而不是转换为列表。 您可以使用argparseoptparse

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--l1', type=str)
parser.add_argument('--l2', type=str)
args = parser.parse_args()
l1_list = args.l1.split(',') # ['1','2','3','4']

示例:python prog.py --l1=1,2,3,4

此外,作为一条线,您可以传递类似 1-50 的内容,然后在“-”上拆分并构造范围。 像这样的:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--l1', type=str, help="two numbers separated by a hyphen")
parser.add_argument('--l2', type=str)
args = parser.parse_args()
l1_list_range = xrange(*args.l1.split('-')) # xrange(1,50)
for i in l1_list_range:
    print i

示例:python prog.py --l1=1-50

逻辑我认为你可以自己写。 :)

【讨论】:

  • 任何示例代码可以做到这一点?如果任何列表为空或包含超出范围的数字,我也想抛出错误?
  • 请带一份您想通过的样品清单。
  • @Swati StackOverflow 不是代码编写服务。请自己尝试解决问题,然后寻求解决方案的帮助。
  • 示例列表 list1 包含数字 1-50,而 list2 包含来自 list1 的数字子集
【解决方案3】:

这对我有用:

parser.add_argument('-i', '--ids', help="A comma separated list IDs", type=lambda x: x.split(','))

编辑:

我刚刚意识到这实际上并不能回答所提出的问题。 Jakub 有正确的解决方案。

【讨论】:

    【解决方案4】:

    为了完整起见,只需添加这个。我很惊讶我没有看到这种方法。

    from argparse import Action, ArgumentParser
    
    
    class CommaSeparatedListAction(Action):
        def __call__(self, parser, namespace, values, option_string=None):
            setattr(namespace, self.dest, values.split(','))
    
    
    parser = ArgumentParser()
    parser.add_argument('-l', action=CommaSeparatedListAction)
    print(parser.parse_args('-l a,b,c,d'.split()))
    
    # Namespace(l=['a', 'b', 'c', 'd'])
    

    这只是一个基本示例,但您也可以以某种方式添加验证或转换值,例如将它们强制为大写。

    from argparse import Action, ArgumentParser
    
    
    class UppercaseLetterCommaSeparatedListAction(Action):
        def __call__(self, parser, namespace, values, option_string=None):
            letters = values.split(',')
            for l in letters:
                self._validate_letter(parser, l)
            setattr(
                namespace,
                self.dest,
                list(map(lambda v: v.upper(), letters))
            )
    
        def _validate_letter(self, parser, letter):
            if len(letter) > 1 or not letter.isalpha():
                parser.error('l must be a comma separated list of letters')
    
    
    parser = ArgumentParser()
    parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction)
    print(parser.parse_args('-l a,b,c,d'.split()))
    
    # Namespace(l=['A', 'B', 'C', 'D'])
    
    parser = ArgumentParser()
    parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction)
    print(parser.parse_args('-l a,bb,c,d'.split()))
    
    # usage: list.py [-h] [-l L]
    # list.py: error: l must be a comma separated list of letters
    
    parser = ArgumentParser()
    parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction)
    print(parser.parse_args('-l a,1,c,d'.split()))
    
    # usage: list.py [-h] [-l L]
    # list.py: error: l must be a comma separated list of letters
    

    【讨论】:

      【解决方案5】:

      optparseargparse 的工作方式是它们从命令行读取参数,参数由空格分隔,因此如果您想通过命令行接口从optparse 输入整数列表或argparse - 您可以通过删除空格或用" 包围您的论点来做到这一点,例如:

      > my_script.py --a "1 2 3 4 5" --b "1 2"
      

      或:

      > my_script.py --a 1,2,3,4,5 --b  1,2
      

      然后您的脚本需要将这些输入转换为实际列表。

      使用argparse 语法(与optparse 非常相似):

      # with spaces and "
      a_lst = [i for i in args.a.split(' ')] 
      b_lst = [i for i in args.b.split(' ')]
      
      # without spaces and ,
      a_lst = [i for i in args.a.split(',')] 
      b_lst = [i for i in args.b.split(',')]
      

      另一种方法是导入您要运行的模块并将列表对象传递给处理您的代码的类,或者使用while循环和raw_input/input收集想要的列表。

      【讨论】:

        【解决方案6】:

        如果 only 参数是列表和分隔符,你可以相对简单地做到:

        sa = sys.argv.index('-a')
        sb = sys.argv.index('-b')
        lista = [int(i) for i in sys.argv[sa+1:sb]]
        listb = [int(i) for i in sys.argv[sb+1:]]
        

        添加验证很简单:

        aval = [i for i in lista if i>1 and i<50]
        if len(aval) < len(lista):
            print 'The -a list contains invalid numbers.'
        bval = [i for i in listb if i>1 and i<50]
        if len(bval) < len(listb):
            print 'The -b list contains invalid numbers.'
        

        生成帮助消息:

        if sys.argv[1] in ['-h', '-H'] or len(sys.argv) == 1:
            print "Usage: <name> -a [list of integers] -b [list of integers]"
        

        【讨论】:

        • 我喜欢你的方法,我该如何提供有关输入参数和范围验证的帮助?
        猜你喜欢
        • 1970-01-01
        • 2018-06-27
        • 2015-03-13
        • 2015-08-31
        • 2016-02-23
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        • 2013-06-18
        相关资源
        最近更新 更多