Python 将sys.argv替换为docopt

Python 将sys.argv替换为docopt,python,string,replace,sys,docopt,Python,String,Replace,Sys,Docopt,我正在合并一些字符串替换,目前使用sys.argv[I]将参数传递给脚本。我想用docopt替换sys,但到目前为止我发现文档相对不清楚 我的代码目前的工作方式是 filename.py -param_to_replace new_param_value 我还可以包含多个要替换的参数 然后由 if len(sys.argv) > 1: for i in range((len(sys.argv)-1) / 2): params[sys.argv[1+2*i].spl

我正在合并一些字符串替换,目前使用sys.argv[I]将参数传递给脚本。我想用docopt替换sys,但到目前为止我发现文档相对不清楚

我的代码目前的工作方式是

filename.py -param_to_replace new_param_value
我还可以包含多个要替换的参数

然后由

if len(sys.argv) > 1:
    for i in range((len(sys.argv)-1) / 2):
        params[sys.argv[1+2*i].split('-')[1]] = float(sys.argv[1+2*i+1])
其中params是一组已定义参数的名称

我想我应该能够让这个与docopt一起工作,但到目前为止,我所拥有的更像是

"""Docopt test
Usage:
  filename.py --param_name1 <val> --param_name2 <val>

  filename -h | --help
  filename --version

Options:
  -h --help     Show this screen.
  --param_name1 Change some param we call param_name1, all other params changed in similar way


"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='filename 1.0')
    print(arguments)
但这并没有通过任何程序,官方文件中提供的细节似乎到此为止。熟悉docopt的人知道如何更有效地传递命令行参数吗?或者我应该用后面的参数替换sys.argv吗

谢谢

如果您只想构建一个-param:value的dict,而不是使用docopt,因为docopt会返回一个-param:value,那么您可以通过字典理解来实现这一点,我想这比您目前正在做的更容易理解:

if __name__ == '__main__':
    if len(sys.argv) > 1:
        args = sys.argv[1:]
        assert len(args) % 2 == 0
        arguments = {args[i][1:]: args[i+1] for i in range(0, len(args), 2)}
        print(arguments)
然后测试它:

In [12]: runfile(
             'test.py', wdir='/home/mgc',
              args='-param_to_replace1 new_value1 -param_to_replace2 new_param_valu2')

{'param_to_replace2': 'new_param_valu2', 'param_to_replace1': 'new_value1'}
我刚意识到医生在做什么,看看我的评论

加载模块时,初始三重引号字符串将分配给其_doc__变量。通常,这是各种“帮助”包可以使用的文档。函数和类也有_udoc。对于docopt,它应该对命令行解析器的帮助显示进行建模

行将此文档字符串传递给docopt函数或类。这将推断出您想要接受的参数,解析sys.argv,并返回字典arguments

在您的示例中,用法行是:

filename.py --param_name1 <val> --param_name2 <val>
该参数将是一个字典,如下所示:

{'param_name1':'foo', 'param_name2':'bar'}
参数['param_name1']应该返回'foo'

您当前的代码显然试图解析输入,如

filename.py -foo 2.323 -xxx 1.23
表演

params['foo'] = 2.323
params['xxx'] = 1.23
我预计docopt版本会在输入时产生错误,但我不知道它处理错误的详细情况

是使用python docopt的较长示例

argparse版本 这里有一个argparse脚本,我认为它的行为与sys.argv解析类似。它在params字典中定义了一组基于argparse参数的条目,并应返回一个兼容的字典

import argparse

params = {'foo':None, 'bar':None, 'test':0}

parser = argparse.ArgumentParser()
for key in params:
    name = '--'+key
    default = params[key]
    if default is None:
        parser.add_argument(name)
    else:
        # could be more elaborate on setting type
        parser.add_argument(name, default=default, type=float)

parser.print_help()
print(params)
print(vars(parser.parse_args([]))) # no arguments, should == params
args = parser.parse_args()  # test the sys.argv
print(args)   # namespace
print(vars(args))  # dictionary equivalent
制作:

1033:~/mypy$ python stack34956253.py --foo 124 --test 323.3
usage: stack34956253.py [-h] [--test TEST] [--foo FOO] [--bar BAR]

optional arguments:
  -h, --help   show this help message and exit
  --test TEST
  --foo FOO
  --bar BAR
{'test': 0, 'foo': None, 'bar': None}
{'test': 0, 'foo': None, 'bar': None}
Namespace(bar=None, foo='124', test=323.3)
{'test': 323.3, 'foo': '124', 'bar': None}
这可能以同样的方式工作:

argparse_help = parser.format_help()
arguments = docopt(argparse_help, version='filename 1.0')

看起来您的docopt语法有问题。对我来说,使用。该设置使快速迭代语法变得容易,并查看它是否会生成对我的程序有用的结构

我将您的语法与参数-param_name1 foo-param_name2条放在一起,得到了以下结果:

{
  "--param_name1": "foo", 
  "--param_name2": true, 
  "<val>": "bar"
}
使用-old=foo-new=bar解析的结果是:

或者完全删除开关名,只使用位置参数。更容易预测要替换的对象的多个参数

Usage:
  filename <new> <old>...

我知道我有多喜欢docopt,所以我希望你能克服最初的理解障碍。

所以我想我会回到这个话题上来,因为我意识到我从来没有结束这个话题并发布过答案。传递参数的正确方法如下所示:

"""Usage: filename.py [--arg1=N] [--arg2=N] 

Options:
    --arg1=N passes arg1
    --arg2=N passes arg2
"""

 from docopt import docopt 
 arguments = docopt(__doc__,version='')
 print arguments[--arg1] #This is to print any argument or pass it through

似乎只是在使用方面出现了一些问题,这在这里的代码中已被澄清。

…您有问题吗?意识到我没有澄清我的问题,并已尝试澄清-抱歉!没用,请您是否尝试过以您的argparse版本生成的文档为例?感谢您的建议-在很长时间没有在任何StackExchange上发布后,您再次更新了问题。使用my sys.argv生成的文档生成替换每个指定参数的结果当前格式为params=['name':value,'name':value]。我希望docopt也能做到这一点,那么上面使用的参数是否适合替代sys.argv?正如@hpaulj所指出的,我认为docopt不适合您的用例,因为它解析docstring来构建您试图创建的arguments对象。有了这样一个docstring,它期望第一个选项的名称为param_name1,但它应该是一个变量,idem为param_name2。你应该坚持直接解析列表,你仍然可以编写一个漂亮的docstring!
Usage:
  filename --old=<old> --new=<new>
{
  "--new": "bar", 
  "--old": "foo"
}
Usage:
  filename <new> <old>...
{
  "<new>": "bar", 
  "<old>": [
    "foo", 
    "baz"
  ]
}
"""Usage: filename.py [--arg1=N] [--arg2=N] 

Options:
    --arg1=N passes arg1
    --arg2=N passes arg2
"""

 from docopt import docopt 
 arguments = docopt(__doc__,version='')
 print arguments[--arg1] #This is to print any argument or pass it through