For each key in keylist, puts its value in locals into a stringlist

    Args:
        locals_ (?):
        key_list (list):
        strlist_ (list): (default = None)
        prefix (unicode): (default = u'')

    Returns:
        list: strlist_

    CommandLine:
        python -m utool.util_dbg --exec-parse_locals_keylist

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_dbg import *  # NOQA
        >>> import utool as ut
        >>> locals_ = {'foo': [1, 2, 3], 'bar': 'spam', 'eggs': 4, 'num': 5}
        >>> key_list = [(len, 'foo'), 'bar.lower.__name__', 'eggs', 'num', 'other']
        >>> strlist_ = None
        >>> prefix = u''
        >>> strlist_ = parse_locals_keylist(locals_, key_list, strlist_, prefix)
        >>> result = ('strlist_ = %s' % (ut.repr2(strlist_, nl=True),))
        >>> print(result)
        strlist_ = [
            ' len(foo) = 3',
            " bar.lower.__name__ = 'lower'",
            ' eggs = 4',
            ' num = 5',
            ' other = NameError (this likely due to a misformatted printex and is not related to the exception)',
        ]

def parse_locals_keylist(locals_, key_list, strlist_=None, prefix=''):
    """ For each key in keylist, puts its value in locals into a stringlist

    Args:
        locals_ (?):
        key_list (list):
        strlist_ (list): (default = None)
        prefix (unicode): (default = u'')

    Returns:
        list: strlist_

    CommandLine:
        python -m utool.util_dbg --exec-parse_locals_keylist

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_dbg import *  # NOQA
        >>> import utool as ut
        >>> locals_ = {'foo': [1, 2, 3], 'bar': 'spam', 'eggs': 4, 'num': 5}
        >>> key_list = [(len, 'foo'), 'bar.lower.__name__', 'eggs', 'num', 'other']
        >>> strlist_ = None
        >>> prefix = u''
        >>> strlist_ = parse_locals_keylist(locals_, key_list, strlist_, prefix)
        >>> result = ('strlist_ = %s' % (ut.repr2(strlist_, nl=True),))
        >>> print(result)
        strlist_ = [
            ' len(foo) = 3',
            " bar.lower.__name__ = 'lower'",
            ' eggs = 4',
            ' num = 5',
            ' other = NameError (this likely due to a misformatted printex and is not related to the exception)',
        ]
    """
    from utool import util_str
    if strlist_ is None:
        strlist_ = []

    for key in key_list:
        try:
            if key is None:
                strlist_.append('')
            elif isinstance(key, tuple):
                # Given a tuple of information
                tup = key
                func, key_ = tup
                val = get_varval_from_locals(key_, locals_)
                funcvalstr = six.text_type(func(val))
                callname = util_str.get_callable_name(func)
                strlist_.append('%s %s(%s) = %s' % (prefix, callname, key_, funcvalstr))
            elif isinstance(key, six.string_types):
                # Try to infer print from variable name
                val = get_varval_from_locals(key, locals_)
                #valstr = util_str.truncate_str(repr(val), maxlen=200)
                valstr = util_str.truncate_str(util_str.repr2(val), maxlen=200)
                strlist_.append('%s %s = %s' % (prefix, key, valstr))
            else:
                # Try to infer print from variable value
                val = key
                typestr = repr(type(val))
                namestr = get_varname_from_locals(val, locals_)
                #valstr = util_str.truncate_str(repr(val), maxlen=200)
                valstr = util_str.truncate_str(util_str.repr2(val), maxlen=200)
                strlist_.append('%s %s %s = %s' % (prefix, typestr, namestr, valstr))
        except AssertionError as ex:
            strlist_.append(prefix + ' ' + six.text_type(ex) + ' (this likely due to a misformatted printex and is not related to the exception)')
    return strlist_