如何使用 argparse 让用户更改现有程序的输出?

Posted

技术标签:

【中文标题】如何使用 argparse 让用户更改现有程序的输出?【英文标题】:How to use argparse to let user make changes to output of existing program? 【发布时间】:2015-10-08 20:05:31 【问题描述】:

我有一个程序可以生成一个数据数组并很好地打印出来。我寻求解决方案的挑战如下:

在打印之前将数组中的数据弄脏,例如,插入 非 UTF-8 字符,将字段按错误顺序排列, 更改日期格式。 让用户选择发生了哪些“混乱”。

这是我现有程序的精简版,我希望截取和处理它的输出:

ex_matrix = [[402, 'Mayonnaise', '0123', 2014-12-18, '(Burlington, -, -)', 1.0],
             [413, 'Peanuts', '0177', 2014-11-10, '(Place, Florida, South Afrika)', 1.0],
             [415, 'Seaweed', '0713', 2014-12-02, '(The Pub, -, Newfoundland)', 1.0]]

def print_forecasts(matrix, num_rows):
    for r in xrange(num_rows):
        print("%s, [%s, %s, %s, %s], %s" % (matrix[r][0], matrix[r][1],
              matrix[r][2], matrix[r][3], matrix[r][4], matrix[r][5]))
        print "# Generated using pickles_program.py \n"

def main():
    print_forecasts(ex_matrix, 3)

main()

根据我对 Python 的 argparse tutorial、PEP re. argparse 和几个 *** 答案的阅读,似乎 argparse 是解决这个问题的关键。这是我写的,只是想了解一下 argparse 的工作原理:

import argparse

num_rows = 3

parser = argparse.ArgumentParser(description="base rate model: error adder")

parser.add_argument("muck2", help="muck up the population field", nargs='?')
args = parser.parse_args()
for i in xrange(num_rows):
    matrix[i][1] = "^&*#$)(*DJJJJ)"
    print matrix

将有超过 10 种类型的垃圾供用户选择。我想我希望用户能够对命令行说“python pickles_program.py 1 3 8 11”或类似的东西,并拥有muck-up的1、3、8和11 发生,“python pickles_program.py --help”显示所有的垃圾选项。

如果这是一个愚蠢的问题,我希望你能原谅我。我是一名 Python 新手,仍在学习如何使用许多资源来学习这门伟大的语言,但我已经搜索了高低的 SO 和 Python 文档——请相信我,如果我的问题有答案在那里,对于像我这样的人来说,它要么解释得不够好,要么就是太难找到了,因为我还没有找到。

请指教,特别是。关于如何更好/更清楚地提出我的问题!

【问题讨论】:

您能否将其简化为 MWE(最小工作示例)? @TobiaTesan 我愿意尽我所能使这个问题符合 SO,但我不知道“最小工作示例”是什么意思。请澄清一下? 感谢理解。这里:***.com/help/mcve 这可能是相关的(关于variable numbers of arguments) 【参考方案1】:

在我看来,将“垃圾”作为标志而不是数字来处理会容易得多。然后,您可以使用 ArgParse 检查这些标志是否已启用。例如:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
                    action="store_true")
args = parser.parse_args()
if args.verbose:
   print "verbosity turned on"

这样,通过 parser.add_argument("argument", action="store_true") 添加所有“垃圾”,然后在一系列 if 语句下为每个“垃圾”执行逻辑。

【讨论】:

如果您必须使用数字,请回复,我会想办法解决。 不,无论如何——我对使用数字没有任何依恋!事实上,标志是我想问的一个概念。我看到他们谈论了很多,但还没有掌握它们是什么。你能解释一下吗,或者推荐我去某个地方? 标志是参数,但您可以将它们放在任何位置。例如: nmap -sS 127.0.0.1 -p0 和 nmap -p0 -sS 127.0.0.1 产生相同的结果。如果它们存在或不存在,它们允许您“真”或“空”一个变量,以及将值分配给一个标志。比如上面nmap例子中的-p = 0。【参考方案2】:

为了您的学习目的,最好不使用任何额外的模块。只需直接从sys.argv 工作即可。例如

import sys
muck_ups = []
if sys.argv[1:]:  # values beyond the program name
    muck_ups = [int(i) for i in sys.argv[1:]]
    # this will throw an error if one of the strings can't be converted to an int
    # we can refine that later

if len(muck_ups)==0:
    print('help...')
    sys.exit(1)
    # print help if they don't give you any numbers

for m in muck_ups:
    if m in [1]:
       pass # do one muckup
    elif m in [2]:
       <do another>
    elif m in [3]:
       <etc>
    else:
        print('muckup %s not found'%m)

muck_ups 值不必是数字。它们可以是字符串,你可以有别名,例如

 elif m in [1,'1','one','first']:
    ....

如果您想按照muck_ups 值指示的顺序执行操作,请使用这样的逻辑。如果你想做action1,如果1 in muck_ups,然后action2if 2 in muck_ups:,等等,你会想要使用不同的逻辑。

一个简单的argparse 解析器:

parser.add_argument('muck_ups', type=int, nargs='*')

会在args.muck_ups 中给出相同的整数列表。如果您想添加更多开关和选项,argparse 会很有用,但对于这样的一个参数,它并没有太大区别。

argparse(和相关模块)主要是一种解析输入的方式;弄清楚用户想要做什么。它不是一种执行机制。不要因为让它做一些花哨的事情而挂断电话。

【讨论】:

以上是关于如何使用 argparse 让用户更改现有程序的输出?的主要内容,如果未能解决你的问题,请参考以下文章

如何让现有用户成为 AWS Redshift 中的超级用户

python 笔记:argparse

更新应用程序时,如何让所有现有用户退出 Google?

根据用户输入更改现有CSV文件

python ----Parser使用

如何让 argparse 使用选项而不是前缀从文件中读取参数