【问题标题】:Python: switching from optparse to argparsePython:从 optparse 切换到 argparse
【发布时间】:2012-04-22 00:00:19
【问题描述】:

从 optparse 切换到 argparse 后 - 我遇到了奇怪的错误。 argparse 仅在不留空格时才解析 args:

myScript.py -oOpt

或放一个等号:

myScript.py -o=Opt

它不能正常工作:

myScript.py -o Opt

这是我的 argparse 初始化:

#!/usr/bin/env python
# to get description use the -h flag

import argparse, os, sys


# ======================
# Python2.7 is expected:

if sys.version_info[0] != 2 or sys.version_info[1] < 7:
    sys.exit('This program needs Python2.7+')


# ==========
# preambule:

desc = """Enter dirs in the current dir and makes gro out of state.cpt there."""
# parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(description=desc, version='2.3', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-w', '--workWith',
                    help = 'to specify a Gromacs exec suffix', 
                    dest = 'wW',
                    action = 'store',
                    default = '-4.5.5-single',
                    )
parser.add_argument('-g', '--gro',
                    help = '.gro postfix: <nameOfTheDir><postfix>.gro', 
                    dest = 'myGroPostfix',
                    action = 'store',
                    default = "_membrane",
                    )
parser.add_argument('-H', '--here',
                    help = 'toggles - single (current) dir behaviour (the output will be state.gro)', 
                    dest = 'Here',
                    action = 'store_true',
                    )
parser.add_argument('-D', '--dirs',
                    help = 'include these dirs (python\'s rgxp in SINGLE quotes), defaults to \'\'', 
                    dest = 'inclDirs',
                    action = 'store',
                    default = '',
                    )

args = parser.parse_args()


print args.wW

编辑

更多:

 gmx_bk-simulate-mems.py -j bk-runs-mpi.bash -p 1 -w="-4.5.5-double_non-parallel_gcc" 2&> ../`date +%Y-%b-%d-%H%M%S`.log &

给予:

 gmx_bk-simulate-mems.py: error: unrecognized arguments: 2

看起来argparse2&amp;&gt; 视为选项(或2&amp;&gt;../date +%Y-%b-%d-%H%M%S.log 作为选项)!

编辑 2

总结一下:

  • 对于argparse - "-4.5.5-double_non-parallel_gcc" 是一个错误的选项名称 - 这就是为什么它需要写成-w="-4.5.5-double_non-parallel_gcc"。对于optparsebash (!) 这很好。 bash 甚至在 -w="-4.5.5-double_non-parallel_gcc" 处给出错误 - 它认为 arg 是 ="-4.5.5-double_non-parallel_gcc" (!);

  • 没有2&amp;&gt; 这样的东西。 2&gt; 应该可以使用并且不会出错;

  • 这是 shell 将行拆分为 args,而不是 python

  • argparseoptparse 好很多。

【问题讨论】:

  • 将您的代码放入tmp.pypython tmp.py -w3python tmp.py -w 3 都为我打印'3'。
  • @chepner: 是的,确实如此...实际上,问题在gmx_bk-get-results.bash 中给出了第75 行:如果从该行中删除= - 脚本给出错误 - 好像我没有给出它"$wW"。为了重现一个还需要得到bk-copies-from-dirs.pygmx_bk-cpt2gmx.py...在optparse 上一切正常。我希望有人会从“理论上”看到这个问题。
  • 迂腐评论:您不需要版本检查器。如果使用 Python 3,底部的 print 语句会导致语法错误,甚至不会加载脚本。如果您使用 Python 2.6 或更低版本,脚本将在导入 argparse 时失败,甚至在您进行版本检查之前。
  • 不过,这是一个非常有趣的问题,思考它教会了我一些关于argparse 的新东西。感谢分享!

标签: python shell command-line-arguments argparse optparse


【解决方案1】:

首先,有必要做一个小的区分。 argparse 模块不会解析你的命令行参数,shell 会。 shell 负责将您在 shell 中键入的行转换为标记,然后将其传递给sys.argv,这是一个 python 数组/命令行参数序列。 argparse 模块可以简单地理解 sys.argv 中出现的内容。

这种区别将澄清您注意到的两个“错误”。首先,考虑-w "-4.5.5-double_non-parallel_gcc"(注意缺少等号)。 shell 将这两个标记解析为-w-4.5.5-double_non-parallel_gcc,并将这两个字符串传递给 sys.argv。没有等号,这似乎是两个选项:-w(没有参数)和-4.5.5-double_non-parallel_gcc 作为参数。您需要等号,以便将所有内容都解析为单个标记。

编辑部分

对于2&amp;&gt;,argparse 无法控制给定标记是否被视为参数。如果 sys.argv 中出现某些内容,则表示您的 shell 将其视为参数。

这里的标志是错误消息。请注意,该消息不是unrecognized arguments: 2&amp;&gt;,而是unrecognized arguments: 2。您的 shell 将“&>”识别为输出重定向,并相应地解析该行的其余部分(包括日志文件)。传递的唯一参数是“2”,因为2&amp;&gt; 不是真正的重定向类型。 (&amp;&gt; 已经涵盖了 stderr 和 stdout,那么 2 会添加什么?)

在评论中,您声称optparse 可以“处理”“2&>”。实际上并非如此。 optparse 模块所做的正是 argparse 所做的,但 optparse 不像 argparse 那样验证位置参数。事实上,optparse 正在让一个真正的编程错误(在这种情况下,使用2&amp;&gt; 作为一种 shell 重定向)悄悄溜走!您应该发布原始 optparse 代码,但我怀疑您将参数解析如下:

opt, args = parser.parse_args()

你的脚本没有位置参数,所以我想你之后没有对args 做任何其他事情。但是如果你检查args,你会发现2 被认为是一个位置参数!

一般来说,如果脚本不接受位置参数并且您使用optparse,那么最好验证您是否收到位置参数,如下所示:

opt, args = parser.parse_args()
if args:
    parser.error("script takes no positional arguments")

argparse 模块为您工作,这就是它领先于optparse 的原因(以及其他原因)。

【讨论】:

  • optparse 一切正常。但看起来"-4.5.5-double_non-parallel_gcc" 是一个“错误的选项名称”,而optparse 留下引号,argparse 没有 - 因此出现错误。但是2&amp;&gt; 部分呢? optparse 工作正常。没有 2 可以正常工作:&amp;&gt;。我可以这样生活——但这不是很奇怪吗?应该解决。它也应该与2&amp;&gt; 一起使用。
  • 我已经编辑了上面的答案以解决您的问题。同样,2&amp;&gt; 不是真正的重定向标志; 2&gt; 是,&amp;&gt; 是,甚至是 2&gt;&amp;1,但不是 2&amp;&gt;。如果您不相信我,请尝试使用内置的 shell:ls 2&amp;&gt; tmp.txt&amp;&gt; 捕获 stderr,因此您不会立即看到它,但如果您查看 tmp.txt,您会看到错误消息。
猜你喜欢
  • 2017-09-02
  • 2012-07-15
  • 2013-01-01
  • 2017-04-01
  • 2014-08-09
  • 2015-05-07
  • 2012-09-11
  • 2011-03-14
  • 2011-11-22
相关资源
最近更新 更多