argparse.add_argument()默认总是使用...有时候

时间:2012-08-16 15:51:37

标签: python argparse

这个简化的脚本足以导致问题...只是检查'-d'参数是否是一个有效的目录,如果没有提供默认值,则提供默认值...

#!/usr/bin/python

import os
import argparse

def valid(dir):
   subdir = dir + '/Desktop'
   if not os.path.exists(subdir):
      raise argparse.ArgumentTypeError("%s is not a valid directory" % subdir)
   return dir

parser = argparse.ArgumentParser(description="blah blah blah")
parser.add_argument('-d', '--directory', help='directory to check', default=os.getcwd(), type=valid)
args = parser.parse_args()

默认参数是什么并不重要,当我运行脚本时,它使用默认值,无论我在命令行输入什么,并抛出未捕获的异常,如下所示:

Traceback (most recent call last):
  File "./parsertest.py", line 15, in <module>
    args = parser.parse_args()
  File "/usr/lib/python2.7/argparse.py", line 1688, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/lib/python2.7/argparse.py", line 1710, in parse_known_args
    default = self._get_value(action, default)
  File "/usr/lib/python2.7/argparse.py", line 2239, in _get_value
    raise ArgumentError(action, msg)
argparse.ArgumentError: argument -d/--directory: /home/users/jrice/Desktop/Desktop is not a valid directory

运行正常,我的意思是,处理ArgumentTypeError时应该如何,只要我执行以下操作就打印msg:

  1. 删除'default ='参数
  2. 不要将'/ Desktop'附加到dir,所以subdir = dir,或者只是检查dir本身
  3. 从我的主目录运行脚本!?!?
  4. 详细说明:如果我做了上述任何一项,即使'-d'无效,一切都很好。这是输出,这就是我想要的。

    >./Desktop/parsertest.py -d blah
    usage: parsertest.py [-h] [-d DIRECTORY]
    parsertest.py: error: argument -d/--directory: blah/Desktop is not a valid directory
    

    为什么os.getcwd()+'/ Desktop'会有所不同?

2 个答案:

答案 0 :(得分:3)

我相信你的“类型检查”过于激进了。您将不存在的目录视为无效类型,这不是argparse的考虑方式。在您的情况下,默认值可能不是混淆argparse的“有效类型”。查看以下代码及其输出:

#!/usr/bin/python

import os
import argparse

def valid(dir):
   print "Checking " + dir
   subdir = dir + '/Desktop'
   #if not os.path.exists(subdir):
   #   raise argparse.ArgumentTypeError("%s is not a valid directory" % subdir)
   return dir

parser = argparse.ArgumentParser(description="blah blah blah")
parser.add_argument('-d', '--directory', help='directory to check', type=valid, default=os.getcwd())
args = parser.parse_args()

使用/home/user/Desktop-d /home/user执行此操作会发出:

Checking /home/user/Desktop
Checking /home/user

如您所见,argparse首先转换默认值,然后转换为命令行给定值。

要解决上述问题,请确保默认值始终为“有效类型”,或者在argparse完成后检查目录。

答案 1 :(得分:2)

Argparse尝试将默认参数转换为赋予它的任何类型。

import argparse

parser = argparse.ArgumentParser(description="blah blah blah")
parser.add_argument('-i',default="1",type=int)

args = parser.parse_args([])
print args          # Namespace(i=1)
print type(args.i)  # <type 'int'>

这个设计选择的原因对我来说有点奇怪,但可能是这样你可以将字符串传递给default,就像在命令行上获取它们一样,然后帮助将被正确格式化。

注意我并不喜欢将验证码传递给type关键字参数,即使它们是在documentation中执行的。该参数是将输入字符串转换为其他类型。如果您真的想在解析时进行验证,则应考虑使用自定义Action,但对于此示例,它可能只是最简单的方法:

#...snip...
parser.add_argument('-d', '--directory', help='directory to check')
args = parser.parse_args()
args.directory = valid(args.directory if args.directory is not None else os.getcwd())
#the following should work too. 
#args.directory = valid(args.directory if args.directory else os.getcwd())