【问题标题】:python argparse set behaviour when no arguments provided没有提供参数时的python argparse设置行为
【发布时间】:2012-12-30 19:00:48
【问题描述】:

我对 python 还很陌生,在使用命令行参数时,我一直在思考如何构建我的简单脚本。

脚本的目的是自动化我工作中与排序和处理图像相关的一些日常任务。

我可以指定参数并让它们调用相关函数,但我也想在没有提供参数时设置默认操作。

这是我目前的结构。

parser = argparse.ArgumentParser()
parser.add_argument("-l", "--list", help="Create CSV of images", action="store_true")
parser.add_argument("-d", "--dimensions", help="Copy images with incorrect dimensions to new directory", action="store_true")
parser.add_argument("-i", "--interactive", help="Run script in interactive mode", action="store_true")
args = parser.parse_args()

if args.list:
    func1()
if args.interactive:
    func2()
if args.dimensions:
    func3()

但是当我不提供任何参数时,什么都不会被调用。

Namespace(dimensions=False, interactive=False, list=False)

如果没有提供任何参数,我想要的是一些默认行为

if args.list:
        func1()
    if args.interactive:
        func2()
    if args.dimensions:
        func3()
    if no args supplied:
        func1()
        func2()
        func3()

这似乎应该很容易实现,但我迷失了如何检测所有参数是否为假而不循环通过参数并测试是否全部为假的逻辑。

更新

多个参数一起有效,这就是我没有走 elif 路线的原因。

更新 2

考虑到@unutbu 的回答,这是我的更新代码

这似乎并不理想,因为所有内容都包含在 if 语句中,但在短期内我找不到更好的解决方案。我很高兴接受@unutbu 的回答,如果提供任何其他改进,我们将不胜感激。

lists = analyseImages()
    if lists:
        statusTable(lists)

        createCsvPartial = partial(createCsv, lists['file_list'])
        controlInputParital = partial(controlInput, lists)
        resizeImagePartial = partial(resizeImage, lists['resized'])
        optimiseImagePartial = partial(optimiseImage, lists['size_issues'])
        dimensionIssuesPartial = partial(dimensionIssues, lists['dim_issues'])

        parser = argparse.ArgumentParser()
        parser.add_argument(
        "-l", "--list", 
        dest='funcs', action="append_const", const=createCsvPartial,
        help="Create CSV of images",)
        parser.add_argument(
        "-c", "--convert", 
        dest='funcs', action="append_const", const=resizeImagePartial,
        help="Convert images from 1500 x 2000px to 900 x 1200px ",)
        parser.add_argument(
        "-o", "--optimise", 
        dest='funcs', action="append_const", const=optimiseImagePartial,    
        help="Optimise filesize for 900 x 1200px images",)
        parser.add_argument(
        "-d", "--dimensions", 
        dest='funcs', action="append_const", const=dimensionIssuesPartial,
        help="Copy images with incorrect dimensions to new directory",)
        parser.add_argument(
        "-i", "--interactive", 
        dest='funcs', action="append_const", const=controlInputParital,
        help="Run script in interactive mode",)
        args = parser.parse_args()

        if not args.funcs:
            args.funcs = [createCsvPartial, resizeImagePartial, optimiseImagePartial, dimensionIssuesPartial]

        for func in args.funcs:
            func()

    else:
        print 'No jpegs found'

【问题讨论】:

    标签: python python-2.7 argparse


    【解决方案1】:

    您可以将函数append_const 设置为属性args.funcs,然后在未设置任何选项时使用一个 if 语句来提供默认行为:

    if not args.funcs:
        args.funcs = [func1, func2, func3]
    

    import argparse
    
    def func1(): pass
    def func2(): pass
    def func3(): pass
    
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-l", "--list",
        dest='funcs', action="append_const", const=func1,
        help="Create CSV of images", )
    parser.add_argument(
        "-i", "--interactive",
        dest='funcs', action="append_const", const=func2,
        help="Run script in interactive mode",)
    parser.add_argument(
        "-d", "--dimensions",
        dest='funcs', action='append_const', const=func3,
        help="Copy images with incorrect dimensions to new directory")
    args = parser.parse_args()
    if not args.funcs:
        args.funcs = [func1, func2, func3]
    
    for func in args.funcs:
        print(func.func_name)
        func()
    

    % test.py
    func1
    func2
    func3
    
    % test.py -d
    func3
    
    % test.py -d -i
    func3
    func2
    

    请注意,与您的原始代码不同,这允许用户控制调用函数的顺序:

    % test.py -i -d
    func2
    func3
    

    这可能是可取的,也可能不是。


    响应更新 2

    您的代码可以正常工作。但是,您可以通过以下方式组织它:

    • 除了将主程序嵌套在 if 子句中,您还可以 使用

      if not lists:
          sys.exit('No jpegs found')
      # put main program here, unnested
      

      sys.exit 将打印No jpegs foundstderr 并以退出代码1 终止。

    • 虽然我最初建议使用functools.partial,但现在我想到了另一种——也许更简单——的方法:而不是

      for func in args.funcs:
          func()
      

      我们可以说

      for func, args in args.funcs:
          func(args)
      

      我们需要做的就是在args.func 中存储一个元组(func, args) 而不是单独的函数。

    例如:

    import argparse
    import sys
    
    def parse_args(lists):
        funcs = {
            'createCsv': (createCsv, lists['file_list']),
            'resizeImage': (resizeImage, lists['resized']),
            'optimiseImage': (optimiseImage, lists['size_issues']),
            'dimensionIssues': (dimensionIssues, lists['dim_issues']),
            'controlInput': (controlInput, lists)
        }
        parser = argparse.ArgumentParser()
        parser.add_argument(
            "-l", "--list",
            dest='funcs', action="append_const", const=funcs['createCsv'],
            help="Create CSV of images",)
        parser.add_argument(
            "-c", "--convert",
            dest='funcs', action="append_const", const=funcs['resizeImage'],
            help="Convert images from 1500 x 2000px to 900 x 1200px ",)
        parser.add_argument(
            "-o", "--optimise",
            dest='funcs', action="append_const", const=funcs['optimiseImage'],
            help="Optimise filesize for 900 x 1200px images",)
        parser.add_argument(
            "-d", "--dimensions",
            dest='funcs', action="append_const", const=funcs['dimensionIssues'],
            help="Copy images with incorrect dimensions to new directory",)
        parser.add_argument(
            "-i", "--interactive",
            dest='funcs', action="append_const", const=funcs['controlInput'],
            help="Run script in interactive mode",)
        args = parser.parse_args()
        if not args.funcs:
            args.funcs = [funcs[task] for task in
                          ('createCsv', 'resizeImage', 'optimiseImage', 'dimensionIssues')]
        return args
    
    if __name__ == '__main__':
        lists = analyseImages()
    
        if not lists:
            sys.exit('No jpegs found')
    
        args = parse_args(lists)   
        statusTable(lists)    
        for func, args in args.funcs:
            func(args)
    

    【讨论】:

    • 这似乎是一个整体上更好的解决方案,但我接受的答案解决了我的问题。更详细一点,我不只是打电话给func1(),它更像func1(lists['file_list']),这似乎与您的建议不太相符。我可以重新编辑问题以使其更清楚。
    • 好的,没关系。如果您对如何使用预设参数“准备”函数感到好奇,请查看functools.partial。如果您希望我看一下您重新编辑的问题,请留下指向“@unutbu”的评论,以便系统通知我。
    • 考虑到您的建议,我对我的问题添加了更新。感谢您的帮助和 functools.partial 的链接。除非您有任何其他改进建议,否则我准备好接受您的回答。 @unutbu
    • @d.learious:您的代码可以正常工作。但是,我现在想到有一种方法可以在没有 functools.partial 的情况下执行此操作,我认为它看起来更漂亮一些。我已经编辑了上面的帖子,以说明我的意思。
    • 我接受了这个答案,因为它给了我更多的建议来推进和改进我的程序。感谢@unutbu 的帮助
    【解决方案2】:

    您可以通过检查 args 的数量是否等于 1 来处理此问题。这意味着仅通过了您的 python 命令。

    import argparse
    import sys
    
    parser = argparse.ArgumentParser()
    parser.add_argument("-l", "--list", help="Create CSV of images", action="store_true")
    parser.add_argument("-d", "--dimensions", help="Copy images with incorrect dimensions to new directory", action="store_true")
    parser.add_argument("-i", "--interactive", help="Run script in interactive mode", action="store_true")
    args = parser.parse_args()
    
    if len(sys.argv)==1:
        # display help message when no args are passed.
        parser.print_help()
        sys.exit(1)
    

    【讨论】:

      【解决方案3】:

      这是你想要的吗?

      if args.list:
          func1()
      if args.interactive:
          func2()
      if args.dimensions:
          func3()
      if not any(vars(args).values()):
          func1()
          func2()
          func3()
      

      (感谢@J.F.Sebastian 提供any 版本)

      【讨论】:

      • 不行,因为可能list interactive都是有效选项,然后需要调用两个函数。
      • 嗨 Martijn,这是正确的,这就是我远离 elif 路线的原因
      • 嗨,太好了,解决了我的问题。我会确保研究filter(None, vars(args).values()):的含义
      • 没问题! filter(None, iter) 表示序列中的所有真实项目。虚假物品将被剔除。 vars(args) 是作为字典的参数,dict.values 是获取字典值作为列表的方法。
      • if not any(vars(args).values()):
      猜你喜欢
      • 2015-04-09
      • 2015-07-24
      • 2021-06-01
      • 2021-12-01
      • 2012-01-05
      • 2019-10-18
      • 2018-01-22
      • 1970-01-01
      相关资源
      最近更新 更多