验证另一个参数

时间:2015-03-26 16:05:36

标签: python argparse

我还有两个选项,我需要首先考虑第二个选项。

我试过了:

#!/bin/env python3
# -*- coding: utf-8 -*-

from argparse import ArgumentParser, ArgumentTypeError
from os import getenv, path

def invalidArgument(value, text= None):
    raise ArgumentTypeError("%s %s" % (value, text))

def directory(value):
    if path.isdir(value):
        return value
    invalidArgument(value, "directory not found")

def parsing():
    parser= ArgumentParser("")
    parser.add_argument("-dir", type= directory, action= "store", default= "/home", help= "Base directory")
    parser.add_argument("-loc", action= "store_true", help= "Takes into account locale")
    namespace, other= parser.parse_known_args()
    if namespace.loc:
        l= getenv("LANG", "en")[0:2].lower()
        if l == "en":
            namespace.loc= False
        else:
            if path.isdir(path.join(namespace.dir, l)):
                namespace.loc= path.join(namespace.dir, l)
            else:
                invalidArgument(path.join(namespace.dir, l), "directory not found $LANG not valid")
    return namespace, other

if __name__ == "__main__":
    namespace, other= parsing()
    print("Base directory:", namespace.dir)
    print("Locale directory:", namespace.loc)

我得到(使用./tst.py -loc):

Traceback (most recent call last):
  File "./tst.py", line 32, in <module>
    namespace, other= parsing()
  File "./tst.py", line 28, in parsing
    invalidArgument(path.join(namespace.dir, l), "directory not found or $LANG not valid")
  File "./tst.py", line 8, in invalidArgument
    raise ArgumentTypeError("%s %s" % (value, text))
argparse.ArgumentTypeError: /usr/share/fr directory not found $LANG not valid

如果我打电话:

./tst.py

我需要:

Base directory: /home
Locale directory: False

如果我打电话:

./tst.py -loc

我需要:

Base directory: /home
Locale directory: /home/fr

如果我打电话:

./tst.py -dir=/home/foo -loc

我需要:

Base directory: /home/foo
Locale directory: /home/foo/fr

有没有人对我有想法或追踪?

3 个答案:

答案 0 :(得分:0)

你可以使用带有一个破折号的oneletter args和带有两个破折号的manyletters args: -h, - help

答案 1 :(得分:0)

如果/fr目录不存在,则错误消息有意义。

如果您需要包含使用和退出的错误消息,请使用parser.error(...),而不是仅提出异常。

我简化了你的代码,部分是为了适应常见的argparse用法,但更重要的是要专注于正确解析。由于我的LANG是'en',我把测试的那一部分拿出去了。在这一点上测试特定目录是一种分心。

我认为您的主要问题是type=directory参数。该参数应该是一个接受字符串并返回任何东西的函数。它没有指定您想要的对象类型。由于没有directory(astr)函数,该步骤失败。

def parsing():
    parser= ArgumentParser(prog='PROG')
    parser.add_argument('-d',"--dir", default= "/home", help= "Base directory")
    parser.add_argument('-l',"--loc", action= "store_true", help= "Takes into account locale")
    namespace, other= parser.parse_known_args()

    if namespace.loc:
        l = 'fr'
        namespace.loc= path.join(namespace.dir, l)
    return namespace, other

各种测试是:

1139:~/mypy$ python3 stack29283397.py
Base directory: /home
Locale directory: False
1144:~/mypy$ python3 stack29283397.py -l
Base directory: /home
Locale directory: /home/fr
1144:~/mypy$ python3 stack29283397.py --dir=/home/foo -l
Base directory: /home/foo
Locale directory: /home/foo/fr

loc测试更改为:

if namespace.loc:
    l = 'fr'
    namespace.loc= path.join(namespace.dir, l)
    parser.error('%s directory not found'%namespace.loc)

产生

1145:~/mypy$ python3 stack29283397.py --dir=/home/foo -l
usage: PROG [-h] [-d DIR] [-l]
PROG: error: /home/foo/fr directory not found

如果你想保留type=directory,那么你需要找到或写一个具有该名称的函数,例如

def directory(astring):
    # do something to validate this string
    # or transform it into something else
    return astring

答案 2 :(得分:0)

class Locale(Action):
    def __init__(self, loc, **kwargs):
        super().__init__(**kwargs)
    def __call__(self, parser, namespace, value= False, option_string= None):
        l= getenv("LANG", "en")[0:2].lower()
        if l != "en":
            if path.isdir(path.join(namespace.dir, l)):
                value= path.join(namespace.dir, l)
            else:
                parser.error("%s %s" % (option_string, "directory not found or $LANG not valid"))
        namespace.loc= value

def parsing():
    parser= ArgumentParser("")
    parser.add_argument("-dir", type= directory, action= "store", default= "/home")
    parser.add_argument("-loc", action= Locale, loc= None, nargs= "?", default= False)
    namespace, other= parser.parse_known_args()
    return namespace, other