Python: Encuentre pares sustitutos equivalentes de caracteres unicode que no sean BMP

La respuesta presentada aquí: ¿Cómo trabajar con pares sustitutos en Python? le dice cómo convertir un par suplente, como '\ud83d\ude4f' en un solo carácter Unicode que no sea BMP (la respuesta es "\ud83d\ude4f".encode('utf-16', 'surrogatepass').decode('utf-16') ). Me gustaría saber cómo hacer esto a la inversa. ¿Cómo puedo, usando Python, encontrar el par suplente equivalente de un carácter no BMP, convirtiendo '\U0001f64f' (🙏) de nuevo a '\ud83d\ude4f' . No pude encontrar una respuesta clara a eso.

Tendrá que reemplazar manualmente cada punto que no sea BMP con el par suplente. Podrías hacer esto con una expresión regular:

 import re _nonbmp = re.compile(r'[\U00010000-\U0010FFFF]') def _surrogatepair(match): char = match.group() assert ord(char) > 0xffff encoded = char.encode('utf-16-le') return ( chr(int.from_bytes(encoded[:2], 'little')) + chr(int.from_bytes(encoded[2:], 'little'))) def with_surrogates(text): return _nonbmp.sub(_surrogatepair, text) 

Manifestación:

 >>> with_surrogates('\U0001f64f') '\ud83d\ude4f' 

Es un poco complejo, pero aquí hay una sola línea para convertir un solo personaje:

 >>> emoji = '\U0001f64f' >>> ''.join(chr(x) for x in struct.unpack('>2H', emoji.encode('utf-16be'))) '\ud83d\ude4f' 

Para convertir una mezcla de caracteres se requiere que rodee esa expresión con otra:

 >>> emoji_str = 'Here is a non-BMP character: \U0001f64f' >>> ''.join(c if c <= '\uffff' else ''.join(chr(x) for x in struct.unpack('>2H', c.encode('utf-16be'))) for c in emoji_str) 'Here is a non-BMP character: \ud83d\ude4f'