Categories
python string

How to convert string representation of list to a list

792

I was wondering what the simplest way is to convert a string representation of a list like the following to a list:

x = '[ "A","B","C" , " D"]'

Even in cases where the user puts spaces in between the commas, and spaces inside of the quotes, I need to handle that as well and convert it to:

x = ["A", "B", "C", "D"] 

I know I can strip spaces with strip() and split() and check for non-letter characters. But the code was getting very kludgy. Is there a quick function that I’m not aware of?

0

    1067

    >>> import ast
    >>> x = '[ "A","B","C" , " D"]'
    >>> x = ast.literal_eval(x)
    >>> x
    ['A', 'B', 'C', ' D']
    >>> x = [n.strip() for n in x]
    >>> x
    ['A', 'B', 'C', 'D']
    

    ast.literal_eval:

    With ast.literal_eval you can safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, booleans, and None.

    6

    • 8

      Per comment below, this is dangerous as it simply runs whatever python is in the string. So if someone puts a call to delete everything in there, it happily will.

      Nov 18, 2017 at 21:15

    • 23

      @PaulKenjora: You’re thinking of eval, not ast.literal_eval.

      Mar 19, 2018 at 23:29

    • 31

      ast.literal_eval is safer than eval, but it’s not actually safe. As recent versions of the docs explain: “Warning It is possible to crash the Python interpreter with a sufficiently large/complex string due to stack depth limitations in Python’s AST compiler.” It may, in fact, be possible to run arbitrary code via a careful stack-smashing attack, although as far as I know nobody’s build a public proof of concept for that.

      – abarnert

      Mar 30, 2018 at 0:12

    • 2

      @sqp_125, then it’s a regular list, and you don’t need to parse anything?

      – ForceBru

      Jun 15, 2020 at 14:01

    • 2

      The documentation states (in 2021): “This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.”

      – sebieire

      Dec 6, 2021 at 8:51


    203

    The json module is a better solution whenever there is a stringified list of dictionaries. The json.loads(your_data) function can be used to convert it to a list.

    >>> import json
    >>> x = '[ "A","B","C" , " D"]'
    >>> json.loads(x)
    ['A', 'B', 'C', ' D']
    

    Similarly

    >>> x = '[ "A","B","C" , {"D":"E"}]'
    >>> json.loads(x)
    ['A', 'B', 'C', {'D': 'E'}]
    

    6

    • 20

      This works for ints but not for strings in my case because each string is single quoted not double quoted, sigh.

      Nov 18, 2017 at 21:16


    • 21

      As per @PaulKenjora’s comment, it works for '["a","b"]' but not for "['a','b']".

      Jun 19, 2019 at 9:33

    • 4

      In my case I had to replace single quotes with double quotes in initial string to ensure it works .replace('\'', '"') But I was sure that data inside that string didn’t contain any crucial single/double quotes in it that would affect the final result.

      Dec 10, 2020 at 9:23


    • It does not work for this string. someone knows why? '[{"car_id": "1", "price": 19527.11, "outlier": false}]'

      Sep 24, 2021 at 8:21


    • If user should only enter list of numeric, I think this is the safest way to go to stop malicious intend user.

      Dec 12, 2021 at 5:27

    107

    The eval is dangerous – you shouldn’t execute user input.

    If you have 2.6 or newer, use ast instead of eval:

    >>> import ast
    >>> ast.literal_eval('["A","B" ,"C" ," D"]')
    ["A", "B", "C", " D"]
    

    Once you have that, strip the strings.

    If you’re on an older version of Python, you can get very close to what you want with a simple regular expression:

    >>> x='[  "A",  " B", "C","D "]'
    >>> re.findall(r'"\s*([^"]*?)\s*"', x)
    ['A', 'B', 'C', 'D']
    

    This isn’t as good as the ast solution, for example it doesn’t correctly handle escaped quotes in strings. But it’s simple, doesn’t involve a dangerous eval, and might be good enough for your purpose if you’re on an older Python without ast.

    2

    • Could you please tell me what why did you say “The eval is dangerous – you shouldn’t execute user input.”? I am using 3.6

      Jul 17, 2017 at 1:56

    • 1

      @AaryanDewan if you use eval directly, it will evaluate any valid python expression, which is potentially dangerous. literal_eval solves this problem by only evaluating Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

      Sep 21, 2017 at 23:28