【问题标题】:Python: how to write code that looks nicely and works with argparse or optparse?Python:如何编写看起来不错并与 argparse 或 optparse 一起使用的代码?
【发布时间】:2014-01-21 01:20:55
【问题描述】:

我必须解析参数,所以我使用了argparse 模块。这适用于 Python 3.3 和 Python 2.7。但有时我不得不将它与 Jython 一起使用,而 Jython 的最后一个稳定版本是 2.5.3。这个版本没有argparse 模块所以我使用了旧的optparse 模块:

args = None
try:
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", action="store", dest="url", default=url, help='test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"')
    parser.add_argument("-t", "--threads", action="store", type=int, dest="threads_cnt", default=threads_cnt, help='threads count')
    parser.add_argument("-T", "--timeout", action="store", type=int, dest="timeout_minutes", default=timeout_minutes, help='timeout in minutes')
    args = parser.parse_args()
except:
    import optparse
    parser = optparse.OptionParser()
    parser.add_option("-u", "--url", action="store", dest="url", default=url, help='test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"')
    parser.add_option("-t", "--threads", action="store", type=int, dest="threads_cnt", default=threads_cnt, help='threads count')
    parser.add_option("-T", "--timeout", action="store", type=int, dest="timeout_minutes", default=timeout_minutes, help='timeout in minutes')
    args, _ = parser.parse_args()
return args

对我来说,这段代码看起来很难看,因为任何更改都必须在 2 个地方进行。当然我可以使用类似的东西:

OPT_THREADS_HELP = 'threads count'
...
... help=OPT_THREADS_HELP

这会有所帮助,但也许有更好的方法来编写这样的代码。有什么想法吗?

【问题讨论】:

  • 我担心你最好的选择是使用optparseonly;它在 Python 3.3 和 3.4 中仍然可用。

标签: python coding-style jython argparse optparse


【解决方案1】:

您是否考虑过单独存储参数?

 args = [{"args":("-u", "--url"), 
          "kwargs": {"action": "store", "dest": "url", "default": url, 
                     "help": 'test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"'}
         }, ...]

那么无论你使用哪个库,你都可以调用:

try:
    import argparse
    parser = argparse.ArgumentParser()
    for arg in args:
        parser.add_argument(*arg['args'], **arg['kwargs'])
except:
    import optparse
    parser = optparse.OptionParser()
    for arg in args:
        parser.add_option(*arg['args'], **arg['kwargs'])

您可以进一步简化,允许您通过单独使用绑定方法来减少try 块中的代码:

try:
    import argparse
except ImportError:
    import optparse
    parser = optparse.OptionParser()
    add_func = parser.add_option
else:
    parser = argparse.ArgumentParser()
    add_func = parser.add_argument

for arg in args:
    add_func(*arg["args"], **arg["kwargs"])

【讨论】:

  • 这是我正在考虑的事情。谢谢。除了 argparseoptparse API 更改之外,它还很有用。
  • 您不必在 try 块内实例化解析器 - 您只需将 add_func 分配给类变量即可。
【解决方案2】:

如果您不介意使用 3rd 方库,我建议您尝试使用 docopt:

你在那里做事的方式:

"""Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')
    print(arguments)

docopt

docopt 已使用 Python 2.5、2.6、2.7、3.2、3.3 和 PyPy 进行测试。

Docopt is also successfully used with Jython!

【讨论】:

  • docopt 是否支持 Jython?
  • @MartijnPieters,我假设 jython 支持所有 Python 2.5 代码...值得一试,因为如您所见,Docopt 真的很容易使用。
  • @MartijnPieters,Docopt 已经与 Jython 一起使用,请查看我发布的链接。
  • 很高兴知道这么强大的库。谢谢。
【解决方案3】:

您最好的选择是只使用 一个 命令行参数解析库。

optparse 在 Python 3.3 和 3.4 中仍然可用,并且尚未宣布何时将其删除(如果有的话)。是的,它已被弃用并且不会收到新版本,但它仍然可以正常工作

当你需要支持如此广泛的 Python 版本时,不要试图重复工作。如果optparse 满足您的需求,请使用just optparse

【讨论】:

  • 是的,但有时您必须将代码反向移植到旧版本的 API/Python 等。我从 argparse 开始。当然,我忘记尝试将独立的 argparse 与 Jython 一起使用。
  • 但是为什么还要保留两个库呢?您可以将argparse替换optparse。为什么支持两者?
【解决方案4】:

您可以将解析器类分配给一个变量,然后将猴子补丁OptionParser 分配给add_argument

像这样:

try:
    import argparse
    Parser = argparse.ArgumentParser
except ImportError:
    import optparse
    Parser = optparse.OptionParser
    Parser.add_argument = Parser.add_option


parser = Parser()
parser.add_argument("-u", "--url", action="store", dest="url", default=url, help='test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"')
parser.add_argument("-t", "--threads", action="store", type=int, dest="threads_cnt",default=threads_cnt, help='threads count')
parser.add_argument("-T", "--timeout", action="store", type=int, dest="timeout_minutes", default=timeout_minutes, help='timeout in minutes')

args, _ = parser.parse_args()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-02
    • 2015-03-11
    • 2023-04-06
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多