Best way to get user to input items of different types into a list
Question: What's the best way in Python to prompt a user to input items to an empty list
and ensure the entries are evaluated to correct data types?

For example user enters following mix of `int`, `float`, `str` and `list` item
values:

    
    
    24
    190.45
    'steve'
    'steve smith'
    ['4A', '7B']
    

`new_list` becomes `[24, 190.45, 'steve', 'steve smith', ['4A', '7B']]`

I have tried two methods, each with significant issues.

**Method 1** \- asking user to input space delimited line of list items, using
`eval()` to evaluate and store data types correctly, and using `str.split()`
to split string into component items using `' '` as delimiter:

    
    
    #  user enters values separated by spaces
    input_list = [eval(l) for l in(raw_input('Enter the items for your list separated by spaces: ').split())]
    #  check by printing individual items with data type and also complete list
    for item in input_list:
        print item, type(item)
    print input_list
    

However, I understand using `eval()` is not good from a security perspective.
Also using `' '` delimiter for the split means I can't enter a string item
like `'steve smith'`. However, I don't want to ask the user to input something
ugly like comma delimiters, etc..

**Method 2** \- using a `while` loop with `break`, asking the user to input
each list item:

    
    
    input_list = []
    while True:
        item = eval(raw_input('Enter new list item (or <Enter> to quit): '))
        if item:
            input_list.append(item)
        else:
            break
    

Again, this uses `eval()` which I believe should be avoided. Also hitting
`Enter` to break throws an EOF parsing error, I'm guessing because `eval()`
can't evaluate it.

Is there a better way to do this?


Answer: Method two is clearly superior, but needs a slight tweak to avoid the error
you're seeing:

    
    
    from ast import literal_eval
    
    def get_input_list():
        input_list = []
        while True:
            item = raw_input('Enter new list item (or <Enter> to quit): ')
            if not item:
                break
            input_list.append(literal_eval(item))
        return input_list
    

Note the fact that the input is _only evaluated once it's known to be non-
empty_ , and the use of
[`ast.literal_eval`](https://docs.python.org/2/library/ast.html#ast.literal_eval),
which is safer than `eval`, although more limited:

> The string or node provided may only consist of the following Python literal
> structures: strings, numbers, tuples, lists, dicts, booleans, and `None`.

In use:

    
    
    >>> get_input_list()
    Enter new list item (or <Enter> to quit): 24
    Enter new list item (or <Enter> to quit): 190.45
    Enter new list item (or <Enter> to quit): 'steve'
    Enter new list item (or <Enter> to quit): 
    [24, 190.45, 'steve']
    

You could also add error handling, in case the user inputs a malformed string
or something that can't be evaluated (e.g. `'foo` or `bar`):

    
    
    try:
        input_list.append(literal_eval(item))
    except (SyntaxError, ValueError):
        print "Input not understood. Please try again."
    

