【问题标题】:argparse command line -option after given path给定路径后的 argparse 命令行选项
【发布时间】:2018-05-01 08:12:10
【问题描述】:

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

这是我的电话:

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

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

#!/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()

【问题讨论】:

    标签: python argparse


    【解决方案1】:

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

    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 的内容。如果为真,请对这些内容执行 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()
    

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

    【讨论】:

    • 如果我不需要使用 argv=None 作为函数的参数怎么办?我只需要从命令行获取一个路径名,转到该目录,然后分析其中的文件。如果不使用 sys.argv[1],我该怎么做?
    • 只有 argparse 模块会为我处理解析参数和选项吗?还是我需要使用 sys.argv[1] 来获取用户输入?非常感谢您给我的帮助
    • argv=None 表示函数参数是可选的。你可以省略它。我的代码接受目录为'--dir '。 os.listdir(args.dir) 是您的目录加载的缩写版本。
    • 如果 -name 被调用,我仍然无法弄清楚如何将文件与给定的正则表达式匹配。当我称它为./find.py ../directory 时它有效,但当我这样做时./find.py ../directory -name [a-z] 它告诉我./find.py: No match.
    猜你喜欢
    • 2023-03-13
    • 2012-12-13
    • 2013-11-11
    • 2023-03-21
    • 2011-07-31
    • 2011-09-17
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    相关资源
    最近更新 更多