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 を適切なタイミングで処理し、次のようにするとメッセージを出力するだけです。

  1. 「default=」引数を削除します
  2. dir に '/Desktop' を追加しないで、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になり-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 に答える