使用argparse对默认参数进行自定义类型或动作

7 投票
1 回答
9576 浏览
提问于 2025-04-18 07:25

我想把传给argparse的参数转换成另一种格式;我的想法是传一个数字(通常是浮点数),然后把它转换成字符串(通常是浮点数的Fortran表示法)。

首先,我尝试创建一个自定义类型。

def FortranFloat(value):
    vfloat = float(value)
    vfloat = str(vfloat) + "d0"
    return vfloat

parser = argparse.ArgumentParser()
parser.add_argument("--xmin=", dest="xmin", type=FortranFloat, default=-2.0)
args = parser.parse_args()

这方法很好用……前提是我真的给了--xmin=这个参数。如果没有,它就会保持-2.0不变,而没有按照我想要的方式转换成-2.0d0。所以我想,给默认值用我想要的格式可能更简单,就把2.0换成'2.0d0'……有趣的是,这样做会出问题,因为它崩溃并抛出以下错误:

argparse.ArgumentError: argument --xmin=: invalid FortranFloat value: '-2.0d0'

为了绕过这个问题,我尝试创建一个自定义动作。

class FortranConverter(argparse.Action):
    def __call__(self, parser, namespace, values, option_strings=None):
        if type(values) is float:
            values = str(values) + "d0"
            setattr(args, self.dest, values)

parser = argparse.ArgumentParser()
parser.add_argument("--xmin=", dest="xmin", type=float, default=-2.0, action=FortranConverter)
args = parser.parse_args()

但这也没成功。似乎根本没有经过我的动作(如果我在__call__里打印东西,它会直接忽略掉)。

任何想法、主意或解释都非常感谢!

1 个回答

8

如果default是一个字符串,它会被传递给type函数处理。其他类型的值则直接使用:setattr(namespace, dest, default)。你试过'-2.0'吗?你的FortranFloat应该能把它转换成'-2.0d0'。

另一个选择是修改你的FortranFloat,让它能识别带有'd0'的字符串,并且不做任何改变地传递它。

在将参数字符串传递给action之前,会先通过type处理。如果我没记错的话,default是不会经过action的,它是直接设置的。

你不一定需要这样做,但为了能正常工作,你的FortranConverter函数应该使用setattr(namespace, self.dest, values)

你想用nargs=0达到什么目的?像'store_true'这样的操作会用它来表示它们不接受任何参数。否则,这对程序员来说就没有什么用处。

撰写回答