Я настроил вашу функцию типа для большей информативности:
def regex_type(s, pattern=re.compile(r"[a-f0-9A-F]")):
print('regex string', s)
if not pattern.match(s):
raise argparse.ArgumentTypeError('pattern not match')
return s
Вызывается с
2104:~/mypy$ python2 stack50072557.py .
Я получаю:
<director list>
('regex string', '.')
usage: stack50072557.py [-h] [-name [NAME [NAME ...]]] regex
stack50072557.py: error: argument regex: pattern not match
Поэтому он пытается передать sys.argv[1]
, первую строку после имени скрипта, в функцию regex_type
. Если это не удается, выдает сообщение об ошибке и использование.
ОК, проблема была ..
; Я сделаю каталог:
2108:~/mypy$ mkdir foo
2136:~/mypy$ python2 stack50072557.py foo
('regex string', 'foo')
Namespace(name=[<open file '<stdin>', mode 'r' at 0x7f3bea2370c0>], regex='foo')
2138:~/mypy$ python2 stack50072557.py foo -name a b c
('regex string', 'foo')
Namespace(name=['a', 'b', 'c'], regex='foo')
Строки, следующие за '-name', назначены этому атрибуту. В вашем коде нет ничего, что могло бы их протестировать или передать через функцию regex_type
. Только первая строка без флага делает это.
Чтение sys.argv[1]
изначально не удаляет его из списка. Это все еще там для использования парсером.
Я бы настроил парсер, который использует аргумент store_true
--name
и 2 позиционера - один для dir
, а другой для regex
.
После разбора проверьте args.name
. Если false, выведите содержимое args.dir
. Если true, выполните фильтр args.regex
для этого содержимого. glob
может быть полезно.
Парсер узнает, чего хочет ваш пользователь. Ваш собственный код действует на него. Особенно новичку легче и чётче разделить два этапа.
С:
def parse(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name', action='store_true')
parser.add_argument('--dir', default='.')
parser.add_argument('--regex', default=r"[a-f0-9A-F]")
args = parser.parse_args(argv)
print(args)
return args
def main(argv=None):
args = parse(argv)
dirls = os.listdir(args.dir)
if args.name:
dirls = [f for f in dirls if re.match(args.regex, f)]
print(dirls)
else:
print(dirls)
Я получаю пробеги как:
1005:~/mypy$ python stack50072557.py
Namespace(dir='.', name=False, regex='[a-f0-9A-F]')
['test.npz', 'stack49909128.txt', 'stack49969840.txt', 'stack49824248.py', 'test.h5', 'stack50072557.py', 'stack49963862.npy', 'Mcoo.npz', 'test_attribute.h5', 'stack49969861.py', 'stack49969605.py', 'stack49454474.py', 'Mcsr.npz', 'Mdense.npy', 'stack49859957.txt', 'stack49408644.py', 'Mdok', 'test.mat5', 'stack50012754.py', 'foo', 'test']
1007:~/mypy$ python stack50072557.py -n
Namespace(dir='.', name=True, regex='[a-f0-9A-F]')
['foo']
1007:~/mypy$ python stack50072557.py -n --regex='.*\.txt'
Namespace(dir='.', name=True, regex='.*\\.txt')
['stack49909128.txt', 'stack49969840.txt', 'stack49859957.txt']
и справка:
1007:~/mypy$ python stack50072557.py -h
usage: stack50072557.py [-h] [-n] [--dir DIR] [--regex REGEX]
optional arguments:
-h, --help show this help message and exit
-n, --name
--dir DIR
--regex REGEX
Если я изменю строку dir
на:
parser.add_argument('dir', default='.')
справка теперь
1553:~/mypy$ python stack50072557.py -h
usage: stack50072557.py [-h] [-n] [--regex REGEX] dir
positional arguments:
dir
optional arguments:
-h, --help show this help message and exit
-n, --name
--regex REGEX
и работает:
1704:~/mypy$ python stack50072557.py -n
usage: stack50072557.py [-h] [-n] [--regex REGEX] dir
stack50072557.py: error: too few arguments
1705:~/mypy$ python stack50072557.py . -n
Namespace(dir='.', name=True, regex='[a-f0-9A-F]')
['foo']
1705:~/mypy$ python stack50072557.py ../mypy -n --regex='.*\.txt'
Namespace(dir='../mypy', name=True, regex='.*\\.txt')
['stack49909128.txt', 'stack49969840.txt', 'stack49859957.txt']
Я получаю сообщение об ошибке, потому что теперь для него требуется каталог, даже если это '.'.
Обратите внимание, что скрипт все еще использует:
if __name__ == '__main__':
main()
My main
загружает dir
и применяет фильтр regex
к этому списку имен. Мой args.dir
заменяет ваш direc
.