Steven D'Aprano wrote: > bob gailer wrote: >> On 11/28/2011 12:47 PM, James Reynolds wrote: >>> >>> >>> On Mon, Nov 28, 2011 at 12:32 PM, Mayo Adams <mayoad...@gmail.com >>> <mailto:mayoad...@gmail.com>> wrote: >>> >>> I am trying to pass a set of tuple strings from a file to a >>> function I >>> have defined. Each tuple is on a separate line, and looks something >>> like this: >>> ('note',2048) >>> >> >> As already pointed out - this is a string (a representation of a tuple), >> not a tuple. >> >> Your code must parse the string to extract the string representations of >> the values, then convert as needed to the desired Python values. >> >> Tasks like this are not trivial. > > > In general, parsing can be a hard problem. In this case though, it is easy > to solve 95% of the problem with a hand-built converter, which may be good > enough. > > def strto2tuple(s): > """Convert a string like "('abc', 42)" to a tuple with two items.""" > # Ignore leading and trailing whitespace. > s = s.strip() > # Check for round brackets (parentheses), and remove them. > if s[0] != '(' or s[-1] != ')': > raise ValueError('malformed string, missing ( or )') > s = s[1:-1] > # Split the string into exactly two pieces. > # FIXME this assumes that the first item contains no commas. > items = s.split(',') > n = len(items) > if n != 2: > raise ValueError('expected exactly two items but found %d' % n) > a, b = items > # Ignore spaces around each item, e.g. ( 'abc' , 42 ) => ('abc', 42) > a = a.strip() > b = b.strip() > # Make sure that the first item looks like a string. > quotes = '"\'' # FIXME no support for triple quotes yet, or raw > strings. assert len(quotes) == 2 > for q in quotes: > if a.startswith(q) and a.endswith(q): > # Don't include the delimiter quotes in the string. > a = a[1:-1] > break > else: > # This executes if we don't hit a break in the for loop. > raise ValueError('mismatched or missing quotes') > assert isinstance(a, str) > # Make sure the second item is an integer. > b = int(b, 0) # Support hex and octal formats too. > return (a, b) # And return a real tuple. > > > This untested function will convert strings in a file like these: > > ( 'fe', 1) > ( 'fi' ,2 ) > ("fo",0x03) > ( "fum" , 4 ) > > into proper tuples with a string and a number. Notice that we allow the > user to be sloppy with spaces, but we are strict about quotation marks and > brackets. > > > Our converter function is both a little too strict (e.g. it forbids the > user from including triple-quoted strings) and a little too lax (e.g. it > allows malformed strings like ''abc'). You might not care about these > weaknesses. If you do, you need to move up to a real parser, which is > significantly more complex.
And here's the lazy-bastard version: >>> lines = """( 'fe', 1) ... ( 'fi' ,2 ) ... ("fo",0x03) ... ( "fum" , 4 ) ... ("gvn", __import__("os").remove("that could be your valuable data.txt")) ... """.splitlines() >>> import ast >>> for line in lines: ... print ast.literal_eval(line.strip()) ... ('fe', 1) ('fi', 2) ('fo', 3) ('fum', 4) Traceback (most recent call last): File "<stdin>", line 2, in <module> File "/usr/lib/python2.6/ast.py", line 68, in literal_eval return _convert(node_or_string) File "/usr/lib/python2.6/ast.py", line 58, in _convert return tuple(map(_convert, node.elts)) File "/usr/lib/python2.6/ast.py", line 67, in _convert raise ValueError('malformed string') ValueError: malformed string _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor