def to_identifier(string):
    """Makes a python identifier (perhaps an ugly one) out of any string.

    This isn't an isomorphic change, the original name can't be recovered
    from the change in all cases, so it must be stored separately.

    Examples:
    >>> to_identifier('Alice\'s Restaurant') -> 'Alice_s_Restaurant'
    >>> to_identifier('#if') -> 'if' -> QuiltException
    >>> to_identifier('9foo') -> 'n9foo'

    :param string: string to convert
    :returns: `string`, converted to python identifier if needed
    :rtype: string
    """
    # Not really useful to expose as a CONSTANT, and python will compile and cache
    result = re.sub(r'[^0-9a-zA-Z_]', '_', string)

    # compatibility with older behavior and tests, doesn't hurt anyways -- "_" is a
    # pretty useless name to translate to.  With this, it'll raise an exception.
    result = result.strip('_')

    if result and result[0].isdigit():
        result = "n" + result

    if not is_identifier(result):
        raise QuiltException("Unable to generate Python identifier from name: {!r}".format(string))

    return result
Makes a python identifier (perhaps an ugly one) out of any string.

    This isn't an isomorphic change, the original name can't be recovered
    from the change in all cases, so it must be stored separately.

    Examples:
    >>> to_identifier('Alice\'s Restaurant') -> 'Alice_s_Restaurant'
    >>> to_identifier('#if') -> 'if' -> QuiltException
    >>> to_identifier('9foo') -> 'n9foo'

    :param string: string to convert
    :returns: `string`, converted to python identifier if needed
    :rtype: string