检查是否定义了sys.argv [x]


Answers:


64

最后,try, except测试与测试之间的差异len(sys.argv)并不是很大。与argparse。相比,他们都有点笨拙。

不过,这对我来说是一种低成本的argparse:

arg_names = ['command', 'x', 'y', 'operation', 'option']
args = dict(zip(arg_names, sys.argv))

您甚至可以使用它生成namedtuple默认值为None-的四行内容的!

Arg_list = collections.namedtuple('Arg_list', arg_names)
args = Arg_list(*(args.get(arg, None) for arg in arg_names))

如果您不熟悉namedtuple,它只是一个像对象一样的元组,允许您使用tup.attribute语法而不是tup[0]语法访问其值。

因此,第一行将namedtuple为中的每个值创建一个新类型arg_names。第二行传递args字典中的get值,当给定的参数名称在字典中没有关联的值时,用于返回默认值。


我越来越喜欢Python,这全都归功于这样的答案,当然还有Stack Overflow!太糟糕了,我们没有最后两行的解释。我相信对于初学者来说会很棒。
Goujon

2
爱它!很容易找到这个问题的最佳解决方案。对于其他人:目前尚不明显,我(福利局):1)的“命令”每次都会通过作为第一个参数和2),您可以用ARGS [0]等通话效果
马特d

当然,这很酷,但是测试长度有何技巧?
colorlace19年

1
@timwiz我只是在与使用argparse进行比较。尽管如此,这些天来,每次回到旧脚本时,我都会踢自己,发现我没有使用argparse。
senderle '19

116

检查的长度sys.argv

if len(sys.argv) > 1:
    blah = sys.argv[1]
else:
    blah = 'blah'

有些人喜欢您建议的基于异常的方法(例如try: blah = sys.argv[1]; except IndexError: blah = 'blah'),但我不太喜欢它,因为它不能很好地“扩展”(例如,当您要接受两个或三个参数时)并可能隐藏错误(例如,如果您使用blah = foo(sys.argv[1]),但foo(...)引发IndexErrorIndexError将被忽略)。


1
只要您对此有所了解,就不必担心try, except。只需等待foo您的论点,直到该else条款。
senderle 2011年

3
另外,一旦您考虑进行缩放,就该移至了argparse
senderle 2011年

1
在argparse上+1。我参与了argparse.py所有命令行项目。
David Wolever'3

2
@senderle:当然,如果您很努力的话,那很好。但是根据我的经验,大多数程序员并不勤奋,并把所有逻辑都放在了try子句中……因此,鉴于这并不难(而且,IMO稍微更漂亮),我宁愿只检查长度(而且,避免有人大喊大叫您使用异常进行流量控制。
David Wolever 2011年

2
@David,是的,我明白你的意思。我try必须承认,我有点道歉。我只是觉得有时候比if声明更能表达我的意图。
senderle 2011年

22

我尚未看到的另一种方式是提前设置您的哨兵值。该方法利用了Python的惰性评估,在这种评估中,您不必总是提供一条else语句。例:

startingpoint = 'blah'
if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]

或者,如果您要使用CRAZY语法,则可以使用Python的三元运算符

startingpoint = sys.argv[1] if len(sys.argv) >= 2 else 'blah'

1
三元运算符的答案对我来说是最漂亮的。我坐在这里静静地咒骂我维护的某些软件与Python 2.4捆绑在一起,而Python 2.4却没有。
理查德·巴雷尔

11

我用它-它永远不会失败:

startingpoint = 'blah'
if sys.argv[1:]:
   startingpoint = sys.argv[1]

那不是检查是否定义。更像定义是否存在,至于不一样。我也使用这种方式来评估后备变量,但不是当前问题的答案。
m3nda

@ erm3nda我可以startingpoint从示例中删除变量,但是问题是分配了一个后备变量,所以我也做了相同的事情。
anatoly techtonik

1
如果删除它,则会出现有关未定义变量的错误。我再读一次这个问题,他期望的是,一个变量替换:)没关系。谢谢您的简短建议sys.argv[1:]:。这适用于位置参数,而count不适用。
m3nda

10

这是一个普通的Python列表。您可能会捕获到的异常是IndexError,但最好还是检查一下长度。

if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]
else:
  startingpoint = 'blah'

2

使用地图内置功能的解决方案!

arg_names = ['command' ,'operation', 'parameter']
args = map(None, arg_names, sys.argv)
args = {k:v for (k,v) in args}

然后,您只需要像这样调用参数即可:

if args['operation'] == "division":
    if not args['parameter']:
        ...
    if args['parameter'] == "euclidian":
        ...

1

您可以简单地将argv [1]的值附加到argv,然后检查argv [1]是否不等于您输入的字符串。示​​例:

from sys import argv
argv.append('SomeString')
if argv[1]!="SomeString":
            print(argv[1])

对于那些否决了我的人,请为您感到羞耻,因为他们没有澄清错误。
哈桑·阿卜杜勒·卡里姆

我猜那是因为它很黑。如果有人将SomeString作为参数传递怎么办?如果可以接受,那么如何使用1到5个参数呢?
pbogut

在用户不提供参数的情况下,很酷(但仍然有点怪异)用于设置默认值。只需追加,然后使用argv [1]。
Felizett

1

与发起者试图做的非常接近。这是我使用的功能:

def get_arg(index):
    try:
        sys.argv[index]
    except IndexError:
        return ''
    else:
        return sys.argv[index]

因此用法如下:

if __name__ == "__main__":
    banner(get_arg(1),get_arg(2))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.