English 中文(简体)
将扼杀作为“灰色”理由清单
原标题:Parsing a string as a Python argument list

Summary

我愿把代表“沙捞”理由清单的扼杀语打成我可以向职能呼吁的表格。

Detailed version

我正在拟定一份申请,在此过程中,我希望能够把论点清单从一份案文中删除,然后将这份清单转换成<代码>*args**kwargs,以转而采用一种实际方法。 例如,如果我的案文表明:

"hello",42,helper="Larry, the "wise""

定点结果与:

args=[ hello ,42]
kwargs={ helper :  Larry, the "wise" }

我知道ast 。 模块似乎只是为整篇发言提供一种机制。 我可以通过围绕它发表一项声明,例如,打造这种说法。

ast.parse( f("hello",42,helper="Larry, the "wise"") 

然后将相关领域从<条码>Call node中删除,但这似乎与许多环绕工程一样。

难道有什么办法只能把一个已知的 no子从灰色AST中分离出来,或者在获得这种功能方面有较容易的办法吗?

如果它有所帮助,我只需要能够支持数字和直截了当的论点,尽管有人说,需要支持嵌入的 com子和逃脱的quot语等。

If there is an existing module for building lexers and parsers in Python I am fine with defining my own AST, as well, but obviously I would prefer to just use functionality that already exists and has been tested correct and so on.

<说明>:许多答复侧重于如何储存平价结果,但这不是我所关心的;它给我试图解决的教条,最好是没有写上整个教区发动机。

另外,我的申请已经使用,Jinja,该节目在自己的模版面上用了一种陈词典,尽管我很不清楚如何使用它只用一种抑制语。 (不幸的是,这并不是一个模板,而是一个定制的Markdown过滤器,在这种过滤器中,我与辛塔克斯一样,尽可能密切地匹配金贾模板的功能。)

最佳回答

我想<代码>ast.parse是你的最佳选择。

如果参数按白色空间分开,我们可使用shlex.split:

>>> shlex.split(r "hello" 42 helper="Larry, the "wise"" )
[ hello ,  42 ,  helper=Larry, the "wise" ]

但不幸的是,这并没有按 com子分开:

>>> shlex.split(r "hello",42,helper="Larry, the "wise"" )
[ hello,42,helper=Larry, the "wise" ]

我也想到如何使用ast.literal_eval,但支持关键词:论点:

>>> ast.literal_eval(r "hello",42 )
( hello , 42)
>>> ast.literal_eval(r "hello",42,helper="Larry, the "wise"" )
Traceback (most recent call last):
  File "<unknown>", line 1
    "hello",42,helper="Larry, the "wise""
                     ^
SyntaxError: invalid syntax

我看不出任何支持立场和关键词论的字句。


由于缺乏更好的想法,这里使用的是ast.parse :

import ast

def parse_args(args):
    args =  f({}) .format(args)
    tree = ast.parse(args)
    funccall = tree.body[0].value

    args = [ast.literal_eval(arg) for arg in funccall.args]
    kwargs = {arg.arg: ast.literal_eval(arg.value) for arg in funccall.keywords}
    return args, kwargs

产出:

>>> parse_args(r "hello",42,helper="Larry, the "wise"" )
([ hello , 42], { helper :  Larry, the "wise" })
问题回答

这并非完全是你所希望的,而是结束的。

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument( --helper )
>>> kwargs,args = parser.parse_known_args(["hello", 42 , --helper="Larry, the "wise"" ])
>>> vars(kwargs)
{ helper :  "Larry, the "wise"" }
>>> args
[ hello ,  42 ]

您可使用<代码>re,也可使用一个简单的类别来追踪被标的:

import re
class Akwargs:
   grammar = r "[ws_]+"|"[ws,_"]+"|d+|[a-zA-Z0-9_]+|= 
   def __init__(self, tokens):
      self.tokens = tokens
      self.args = []
      self.kwargs = {}
      self.parse()
   def parse(self):
      current = next(self.tokens, None)
      if current:
         check_next = next(self.tokens, None)
         if not check_next:
            self.args.append(re.sub( ^"+|"+$ ,   , current))
         else:
            if check_next ==  = :
               last = next(self.tokens, None)
               if not last:
                   raise ValueError("Expecting kwargs key")
               self.kwargs[current] = re.sub( ^"|"$ ,   , last)
            else:
               self.args.extend(list(map(lambda x:re.sub( ^"+|"+$ ,   , x), [current, check_next])))
         self.parse()

s =  "hello",42,helper="Larry, the "wise"" 
tokens = iter(re.findall(Akwargs.grammar, s))
params = Akwargs(tokens)
print(params.args)
print(params.kwargs)

产出:

[ hello ,  42 ]
{ helper :  Larry, the "wise" }

全面测试:

strings = [ 23,"Bill","James" ,  name="someone",age=23,"testing",300 , "hello","42" ,  "hello=42",  foo_bar=5 ]
new_data = [(lambda x:[getattr(x, i) for i in [ args ,  kwargs ]])(Akwargs(iter(re.findall(Akwargs.grammar, d)))) for d in strings]

产出:

[[[ 23 ,  Bill ,  James ], {}], [[ testing ,  300 ], { age :  23 ,  name :  someone }], [[ hello ,  42 ], {}], [[], { hello :  42 }], [[], { foo_bar :  5 }]]

你们可以利用一种功能,帮助你摆脱压力和压力:

def f(*args, **kwargs):
  return args, kwargs

import numpy as np
eval("f(1,  a , x=np.int32)")

阁下

((1,  a ), { x : <class  numpy.int32 >})

我调整了Aran-Fey提出的解决办法。 这项工程按预期进行:

import ast

def parse_function_arguments(arg_str):
    # Wrap the argument string in a dummy function call to make it valid Python syntax
    wrapped_arg_str = f"dummy_func({arg_str})"
    # Safe parsing
    tree = ast.parse(wrapped_arg_str, mode="eval")  # Use  eval  mode for expression parsing
    # Assuming the first part of the tree is a Call node
    funccall = tree.body
    # Process arguments: extract literals directly with safe literal_eval
    args = tuple([ast.literal_eval(arg) for arg in funccall.args])
    # Process keyword arguments: convert values from AST nodes to literals
    kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in funccall.keywords}

    return args, kwargs




相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签