I tried eval, but it did not work. And any other mechanism I think
turns out to be creating a full fledged python parser.
Is there any mechanism with which we can do this straight away?
Firstly, don't use `str` as a variable name since it conflicts with
the name of the builtin type.
Now here's how to use eval() properly:
[insert standard 'eval() is EVIL!' warning/lecture here]
eval("test("+the_str+")")
or
eval(test.__name__+"("+the_str+")")
Cheers,
Chris
--
I have a blog:
http://blog.rebertia.com
Thank you very much Chris.
I also thought about the first method a second after I posted this.
But I never thought about the second method.
I will heed the warning about the str part.
Thank you very much again, Chris.
If the string has all of the names you could parse it into a
dictionary and pass it as the keyword arguments
This might work [again be avoid eval if possible].
You _might want to do something like:
def _args(*_nargs, **_kwargs):
'''Collect call parameters from a call'''
return _nargs, _kwargs
...
nargs, kwargs = eval('_args(%s)' % arglist
...
test(*nargs, **kwargs)
--Scott David Daniels
Scott....@Acm.Org
I heard 'pyparsing' was good. ...Not that I've even been to its
webpage.
Did someone say 'pyparsing'? :) Here is a first cut (partially lifted
from a previous post):
from pyparsing import *
LPAR,RPAR,LBRACK,RBRACK,EQ,COMMA = map(Suppress,"()[]=,")
noneLiteral = Literal("None")
boolLiteral = oneOf("True False")
integer = Combine(Optional(oneOf("+ -")) + Word(nums)).setName
("integer")
real = Combine(Optional(oneOf("+ -")) + Word(nums) + "." +
Optional(Word(nums))).setName("real")
ident = Word(alphas+"_",alphanums+"_")
listStr = Forward().setName("list")
tupleStr = Forward().setName("tuple")
listItem = real | integer | noneLiteral | boolLiteral | \
quotedString.setParseAction(removeQuotes) | Group(listStr) |
tupleStr | ident
listStr << ( LBRACK + Optional(delimitedList(listItem)) + Optional
(COMMA) + RBRACK )
tupleStr << (LPAR + Optional(delimitedList(listItem)) + Optional
(COMMA) + RPAR)
# parse actions perform parse-time conversions
noneLiteral.setParseAction(lambda: None)
boolLiteral.setParseAction(lambda toks: toks[0]=="True")
integer .setParseAction(lambda toks: int(toks[0]))
real .setParseAction(lambda toks: float(toks[0]))
listStr .setParseAction(lambda toks: toks.asList())
tupleStr .setParseAction(lambda toks: tuple(toks.asList()))
arg = Group(ident("varname") + EQ + listItem("varvalue")) | listItem
argstring = 'True, type=rect, sizes=[3, 4,], coords = ([1,2],[3,4])'
parsedArgs = delimitedList(arg).parseString(argstring)
args = []
kwargs = {}
for a in parsedArgs:
if isinstance(a,ParseResults):
if isinstance(a.varvalue,ParseResults):
val = a.varvalue.asList()
else:
val = a.varvalue
kwargs[a.varname] = val
else:
args.append(a)
print "Args:", args
print "Kwargs:", kwargs
Prints:
Args: [True]
Kwargs: {'coords': ([1, 2], [3, 4]), 'type': 'rect', 'sizes': [3, 4]}
Ha, ok, out of my league. It's a bit heavyweight I accede. The OP
didn't say what s/he knew about his/er data prior, what fault
tolerance s/he needed, what complexity and nesting of data in the
string, etc.
Hmmm..., just thinking. Could the strings come from a python file:
test1= fargs(True, type=rect, sizes=[3, 4])
test2= fargs(...)
?
from lepl import *
comma = Drop(',')
none = Literal('None') >> (lambda x: None)
bool = (Literal('True') | Literal('False')) >> (lambda x: x == 'True')
ident = Word(Letter() | '_',
Letter() | '_' | Digit())
float_ = Float() >> float
int_ = Integer() >> int
str_ = String() | String("'")
item = str_ | int_ | float_ | none | bool | ident
with Separator(~Regexp(r'\s*')):
value = Delayed()
list_ = Drop('[') & value[:, comma] & Drop(']') > list
tuple_ = Drop('(') & value[:, comma] & Drop(')') > tuple
value += list_ | tuple_ | item
arg = value >> 'arg'
karg = (ident & Drop('=') & value > tuple) >> 'karg'
expr = (karg | arg)[:, comma] & Drop(Eos()) > Node
parser = expr.string_parser()
ast = parser('True, type=rect, sizes=[3, 4], coords = ([1,2],[3,4])')
print(ast[0])
which gives:
Node
+- arg True
+- karg (u'type', u'rect')
+- karg (u'sizes', [3, 4])
`- karg (u'coords', ([1, 2], [3, 4]))
you can then access those values:
>>> ast[0].arg
[True]
>>> ast[0].karg
[('type', 'rect'), ('sizes', [3, 4]), ('coords', ([1, 2], [3, 4]))]
alternatively, you could avoid using a Node altogether and just put them
in a list or whatever....
andrew
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>