argparse 命令行 - 给定路径后的选项 [英] argparse command line -option after given path

查看:25
本文介绍了argparse 命令行 - 给定路径后的选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Python 新手,目前正在试验使用 argparse 添加命令行选项.然而,我的代码不起作用,尽管查看了各种在线教程并阅读了 argparse,但我仍然没有完全理解它.我的问题是每当我尝试调用我的 -option 时,它都会给我一个 find.py 错误:argument regex:

I'm new to python and currently experimenting using argparse to add command line options. However my code is not working, despite looking at various online tutorials and reading up on argparse I still don't fully understand it. My problem is whenever I try to call my -option it gives me a find.py error: argument regex:

这是我的电话:

./find.py ../Python -name '[0-9]*\.txt'

../Python 是我当前目录后面的一个目录,并有一个文件/目录列表.如果没有 -name 选项,我会用它们的路径打印出文件(这很好用)但是使用 -name 选项我想打印出与正则表达式匹配的文件,但它不起作用.这是我目前拥有的:

../Python is one directory behind my current one and has a list of files/directories. Without the -name option I print out the files with their path (this works fine) but with the -name option I want to print out files matching the regex but it won't work. Here is what I currently have:

#!/usr/bin/python2.7

import os, sys, argparse,re 
from stat import *

def regex_type(s, pattern=re.compile(r"[a-f0-9A-F]")):
   if not pattern.match(s):
      raise argparse.ArgumentTypeError
   return s

def main():
   direc = sys.argv[1]

   for f in os.listdir(direc):
      pathname = os.path.join(direc, f)
      mode = os.stat(pathname).st_mode
      if S_ISREG(mode):
          print pathname

   parser = argparse.ArgumentParser()
   parser.add_argument(
    '-name', default=[sys.stdin], nargs="*")
   parser.add_argument('regex', type=regex_type) 
   args = parser.parse_args()



if __name__ == '__main__': 

      main()

推荐答案

我调整了您的类型函数以提供更多信息:

I tweaked your type function to be more informative:

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 函数.如果失败,它会发出错误消息和用法.

So it tries to pass sys.argv[1], the first string after the script name, to the regex_type function. If it fails it issues the error message and usage.

好的,问题出在 ..;我会创建一个目录:

OK, the problem was the ..; I'll make a directory:

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 函数传递它们.只有第一个非标志字符串会这样做.

The strings following '-name' are allocated to that attribute. There's nothing in your code that will test them or pass them through the regex_type function. Only the first non-flag string does that.

读取 sys.argv[1] 最初不会将其从列表中删除.它仍然可供解析器使用.

Reading sys.argv[1] initially does not remove it from the list. It's still there for use by the parser.

我会设置一个解析器,它使用 store_true --name 参数和 2 个位置 - 一个用于 dir,另一个用于对于 regex.

I would set up a parser that uses a store_true --name argument, and 2 positionals - one for the dir and the other for regex.

解析后检查args.name.如果为 false,则打印 args.dir 的内容.如果为 true,则对这些内容执行 args.regex 过滤器.glob 可能有用.

After parsing check args.name. If false print the contents of args.dir. If true, perform your args.regex filter on those contents. glob might be useful.

解析器找出您的用户想要什么.您自己的代码对其进行操作.尤其是初学者,把这两个步骤分开更容易、更干净.

The parser finds out what your user wants. Your own code acts on it. Especially as a beginner, it is easier and cleaner to separate the two steps.

与:

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']

我收到错误,因为它现在需要一个目录,即使它是.".

I get the error because it now requires a directory, even it is '.'.

注意脚本仍然使用:

if __name__ == '__main__': 
    main()

My main 加载 dir,并将 regex 过滤器应用于该名称列表.我的 args.dir 替换了你的 direc.

My main loads the dir, and applies the regex filter to that list of names. My args.dir replaces your direc.

这篇关于argparse 命令行 - 给定路径后的选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆