【问题标题】:Pythonic way to accept a tuple in a JSON argument在 JSON 参数中接受元组的 Pythonic 方式
【发布时间】:2020-04-21 10:55:22
【问题描述】:

我有一个脚本,它在命令行上接受参数来创建 matplotlib.patches.Rectangle 对象。

可以传递给 Rectangle 构造函数的典型参数可能类似于(在 Python 中,没有参数解析):

patches.Rectangle(
    xy=(15000,0),
    width=9.4,
    height=4,
    color='peachpuff'
)

用户可以像这样在命令行上对其进行编码:

--patches '[{ "x" : 15000,"y" : 0,"width" : 9.4,"height" : 4,"color" : "peachpuff"}]'

这个 json 数组加载了json.loads。请注意,大多数参数可以直接传递给Rectangle 构造函数,但xy 元组会导致问题:json.loads 永远不会生成元组类型,所以你可以' t 用这种方式创建一个元组。

为了解决这个问题,我让用户传递单独的 xy 映射,然后像这样组合它们:

p.add_argument('--patches', help='A JSON array of patches.Rectangle object arguments to patch onto the chart',
    type=json.loads)

# stuff

# put some patches on
if args.patches:
    def from_json(json):
        ret = dict(json)
        del ret['x']
        del ret['y']
        ret['xy'] = (json['x'], json['y'])
        return ret
    for pjson in args.patches:
        p = from_json(pjson)
        ax.add_patch(patches.Rectangle(**p))

该代码的一半(基本上是所有from_json)只是处理将xy args 转换为xy = (x, y) 元组。

还有更优雅/Pythonic 的方式来处理这个问题吗?

它可能涉及对 json 输入的更清晰处理,或者可能在命令行上传递除 json 以外的其他内容(但它必须与当前方法具有粗略的特征奇偶性)。

【问题讨论】:

  • json 中的元组通常使用数组表示。你不能用那个吗?另外,它可能不一定是一个元组,只是一些具有 2 个值的可迭代对象。
  • 优雅/Pythonic 的方式是不关心它是否特别是一个元组,正如@JeffMercado 评论的那样,而只是一些两元素序列。
  • @JeffMercado - 我真是个白痴,我不认为Rectangle 可以接受 2 元素列表而不是元组,但它可以,没问题。
  • 如果你真的想要脚本参数中字典的python语法,你也可以做某种ast.literal_eval

标签: python json command-line parameter-passing


【解决方案1】:

您的from_json 函数可以有效地用作--patches 选项的自定义类型。

def RectangleArgs(s):
    d = json.loads(s)
    d['xy'] = (d.pop('x'), d.pop('y'))
    return d


...

parser.add_argument('--patches', action='append', type=RectangleArgs)

...

for patch in args.patches:
    ax.add_patch(patches.Rectangle(**patch))

除了简单地处理从命令行读取的 JSON 之外,您还可以进行额外的验证,如果您在尝试在对 patches.Rectangle 的调用中使用返回值时发现任何会导致问题的内容,则可以提高 argparse.ArgumentTypeError

【讨论】:

    【解决方案2】:

    您认为Rectanglexy 参数需要一个元组的动机假设是不正确的:2 元素列表也可以正常工作,因此"xy" : "[1, 2]" 可以正常工作。

    Jeff in the comments指出。

    【讨论】:

      猜你喜欢
      • 2012-08-26
      • 1970-01-01
      • 2012-11-25
      • 2017-12-13
      • 2023-03-09
      • 1970-01-01
      • 2016-02-17
      • 2010-11-21
      • 1970-01-01
      相关资源
      最近更新 更多