2

这个简化的脚本足以导致问题......只需检查“-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. 从我的主目录运行脚本!?!?

详细说明:如果我执行上述任何操作,即使 '-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' 应该有所不同?

4

2 回答 2

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从with执行它-d /home/user会给出:

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

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

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

于 2012-08-16T16:02:24.973 回答
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关键字参数,即使他们在文档中这样做。该参数是将输入字符串转换为其他类型。如果你真的想在解析时进行验证,你应该考虑使用 custom 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()) 
于 2012-08-16T16:04:33.123 回答