Python PEP8和使用长关键字参数初始化对象

Python PEP8和使用长关键字参数初始化对象,python,argparse,pep8,Python,Argparse,Pep8,在我看来,要在argparse模块中使用RawDescriptionHelpFormatter而不违反PEP8或弄乱您的命名空间,是不容易的 以下是最明显的格式化方法: parser = argparse.ArgumentParser(prog='PROG', .... formatter_class=argparse.RawDescriptionHelpForma

在我看来,要在
argparse
模块中使用
RawDescriptionHelpFormatter
而不违反PEP8或弄乱您的命名空间,是不容易的

以下是最明显的格式化方法:

parser = argparse.ArgumentParser(prog='PROG',
                                 ....
                                 formatter_class=argparse.RawDescriptionHelpFormatter)
这违反了行不应超过80个字符的规定

下面是
argparse
文档中的示例的外观(spoiler:这实际上是正确的;请参见下面的注释):

这违反了关于连续行缩进的PEP8 E128

这是另一种可能性:

parser = argparse.ArgumentParser(
    prog='PROG',
    formatter_class=
    argparse.RawDescriptionHelpFormatter,
    ....
这违反了PEP8 E251关于键控参数的
=
周围空格的规定

(当然,这甚至没有解决我的行字符计数假设
解析器
标记从第一列开始这一事实,这是最好的情况;如果我们想在类和/或函数内创建解析器怎么办?)

因此,就我所知,剩下的唯一选择是要么将名称空间弄得乱七八糟:

from argparse import RawDescriptionHelpFormatter, ArgumentParser
rawformatter = argparse.RawDescriptionHelpFormatter
parser = argparse.ArgumentParser(prog='PROG',
                                 ....
                                 formatter_class=rawformatter)
…或使用愚蠢的临时变量(这也会使命名空间混乱):


我错过什么了吗?我想在当前名称空间中直接使用RawDescriptionHelpFormatter和ArgumentParser并不是什么大问题,但这似乎是一个不必要的挫折。

您的第二个示例在我看来很好,似乎与“#挂起的缩进应该增加一个级别”匹配。示例如下:


也似乎与这个类似的问题/答案相吻合:

还有一些其他的变化:

from argparse import RawDescriptionHelpFormatter as formatter

parser = argparse.ArgumentFormatter(prog='PROG')
# you can reassign a parser attribute after initialization
parser.formatter_class = formatter 
但是,
ArgumentParser
还有其他输入,它们可能足够长,需要包装或赋值给单独的变量

usage = 'PROG [-h] --foo FOO BAR etc'
description = """\
This is a long multiline description
that may require dedenting.
"""
description = textwrap.dedent(description)
parser=Argparse(usage=usage, description=description, formatter_class=formatter)
查看
test_argparse.py
以了解定义长的多方面解析器的多种方法


提出了一个问题,即如果需要对格式化程序进行多次修改,该怎么办,例如:

这意味着我们可以传递argparse.RawDescriptionHelpFormatter或argparse.ArgumentDefaultsHelpFormatter,但不能同时传递两者

建议的解决方案是将格式化程序子类化:

class MyFormatter(argparse.RawDescriptionHelpFormatter, 
    argparse.ArgumentDefaultsHelpformatter):
    pass
保持名称空间干净的另一个策略是将解析器定义包装到函数或模块中

是一个示例,演示了
IPython
如何包装
argparse
为用户创建新的API

另一个基于
argparse
构建的解析器,
plac
首先构建一个
cfg
字典:


argparse
示例如何违反E128?如果在第一行中放置任何参数,则后续参数必须缩进以匹配;如果不这样做,它们必须缩进一步。后者正是
argparse
示例所做的。这与中的“悬挂缩进应添加级别”示例相同。
pep8
检查器和我身边的另外两个过梁都同意这一点。“那么,是什么让你觉得它不好呢?”阿巴内特说。没有。在我运行PEP8检查器的实际示例文件中,第一行有参数。愚蠢的错误,但我很高兴我在这里问了。我认为这个问题应该结束,但我给出了错误的结束理由。这是一个“无法再复制或是一个简单的打字错误”的案例,而不是一个“不清楚你在问什么”的问题。很明显,它只是没有询问正确的代码,如果是的话,您应该已经知道答案了……您的第二个代码块有一个>=80个字符的行,并且没有显示换行,并且您还有一个带有中断的连续体的字符串,这将引发
语法错误
(这应该写成三重引号的字符串),再加上至少一个例外(a
namererror
)但是,最重要的是,我不知道它应该显示什么。@abarnert我认为hpaulj的观点是,通常最好将
用法
描述
分配给单独的变量,这是正确的。在任何情况下,+1用于指出
格式化程序类
可以在初始化后分配.Opps,我的意思是使用三重引号。我又添加了几个复杂的
ArgumentParser
definitions.Dang示例。你已经在这里获得了一个像样的
argparse
教程的种子。你应该写一个,然后发布到某个地方。
class MyFormatter(argparse.RawDescriptionHelpFormatter, 
    argparse.ArgumentDefaultsHelpformatter):
    pass
def pconf(obj):
    ...
    cfg = dict(description=obj.__doc__, 
               formatter_class=argparse.RawDescriptionHelpFormatter)
    ...
    return cfg

def parser_from(obj, **confparams):
    ...
    conf = pconf(obj).copy()
    conf.update(confparams)
    parser = ArgumentParser(**conf)