将字符串转换为 **kwargs 的通用函数

key*_*oss 4 python parsing

我正在尝试找到一种传递字符串(来自Python世界之外!)的方法,该字符串可以被解释为**kwargs一旦到达Python端。

我一直在尝试使用这个 pyparsing 示例,但是此示例中传递的字符串太具体,而且直到现在我才听说过 pyparsing 。我正在努力使其更加人性化,并且对间距等的微小差异具有鲁棒性。例如,我想传递以下内容。

input_str = "a = [1,2], b= False, c =('abc', 'efg'),d=1"

desired_kwargs = {a : [1,2], b:False, c:('abc','efg'), d:1}
Run Code Online (Sandbox Code Playgroud)

但当我尝试这段代码时,没有爱。

from pyparsing import *

# Names for symbols
_quote = Suppress('"')
_eq = Suppress('=')

# Parsing grammar definition
data = (                        
        delimitedList(                   # Zero or more comma-separated items
            Group(                       #   Group the contained unsuppressed tokens in a list
                Regex(u'[^=,)\s]+') +    #     Grab everything up to an equal, comma, endparen or whitespace as a token
                Optional(                #     Optionally...
                    _eq +                #       match an = 
                    _quote +             #       a quote
                    Regex(u'[^"]*') +    #       Grab everything up to another quote as a token
                    _quote)              #       a quote
                )                        #   EndGroup - will have one or two items.
            ))                           # EndList
              

def process(s):
    items = data.parseString(s).asList()
    args = [i[0] for i in items if len(i) == 1]
    kwargs = {i[0]:i[1] for i in items if len(i) == 2}
    return args,kwargs


def hello_world(named_arg, named_arg_2 = 1, **kwargs):
    print(process(kwargs))
    
hello_world(1, 2, "my_kwargs_are_gross = True, some_bool=False, a_list=[1,2,3]")

#output: "{my_kwargs_are_gross : True, some_bool:False, a_list:[1,2,3]}"
Run Code Online (Sandbox Code Playgroud)

要求

  1. ' {'and'}'将附加在代码侧。
  2. kwargs-string 中只会使用标准类型/标准迭代(列表、元组等)。我想不出什么特殊的角色...
  3. kwargs-string 就像它们被输入到 python 端的函数中一样,即'x=1, y=2'. 不是作为字典的字符串。
  4. 我认为这是一个安全的假设,字符串解析的第一步是删除所有空格。

Ry-*_*Ry- 11

一种选择是使用ast 模块来解析字符串的一些包装,将其转换为有效的 Python 表达式。ast.literal_eval如果你\xe2\x80\x99对它能产生的一切都满意的话你甚至可以使用:

\n
>>> import ast\n>>> kwargs = "a = [1,2], b= False, c =(\'abc\', \'efg\'),d=1"\n>>> expr = ast.parse(f"dict({kwargs}\\n)", mode="eval")\n>>> {kw.arg: ast.literal_eval(kw.value) for kw in expr.body.keywords}\n{\'a\': [1, 2], \'b\': False, \'c\': (\'abc\', \'efg\'), \'d\': 1}\n
Run Code Online (Sandbox Code Playgroud)\n