import re


def generate_id(value, normalized):
    """
    Generate a Python identifier from a user provided string.

    :param value: The user provided string.
    :param normalized: :data:`True` to normalize the identifier to its
                       canonical form without underscores, :data:`False`
                       to preserve some readability.
    :returns: The generated identifier (a string).
    :raises: :exc:`~exceptions.ValueError` when nothing remains of `value`
             after normalization.

    If you just want a Python identifier from a user
    defined string you can use `normalized=False`:

    >>> generate_id('Any user-defined string', normalized=False)
    'any_user_defined_string'

    However if you want to use the identifier for comparison or as
    a key in a dictionary then its better to use `normalized=True`:

    >>> generate_id('Any user-defined string', normalized=True)
    'anyuserdefinedstring'

    The following example shows that values that would otherwise start with a
    digit are prefixed with an underscore, because Python identifiers cannot
    start with a digit:

    >>> generate_id('42', normalized=True)
    '_42'
    """
    value = str(value).lower()
    # Replace characters not allowed in identifiers with an underscore.
    value = re.sub('[^a-z0-9]+', '' if normalized else '_', value)
    # Strip leading and/or trailing underscores.
    value = value.strip('_')
    # Make sure something remains from the user provided string.
    if not value:
        msg = "Nothing remains of the given string after normalization! (%r)"
        raise ValueError(msg % value)
    # Add a leading underscore when the first character is a digit.
    if value[0].isdigit():
        value = '_' + value
    return value