Convierta la cadena de bytes sin procesar a Unicode sin conocer la página de códigos de antemano

Cuando se usa el contexto del menú contextual, Windows pasa la ruta del archivo como tipo de cadena sin procesar (byte).

Por ejemplo:

path = 'C:\\MyDir\\\x99\x8c\x85\x8d.mp3' 

Muchos paquetes externos en mi aplicación esperan cadenas de tipo unicode , así que tengo que convertirlos en unicode .

Eso sería fácil si hubiéramos sabido de antemano la encoding de la cadena en bruto (en el ejemplo, es cp1255 ). Sin embargo, no puedo saber qué encoding se utilizará localmente en cada computadora en todo el mundo.

¿Cómo puedo convertir la string en unicode ? Tal vez el uso de win32api es necesario?

No tengo idea de por qué podría estar obteniendo la página de códigos DOS (862) en lugar de ANSI (1255). ¿Cómo se configura la opción de clic derecho?

De cualquier manera, si necesita aceptar cualquier carácter Unicode arbitrario en sus argumentos, no puede hacerlo desde sys.argv de Python 2. Esta lista se rellena con los bytes devueltos por la versión no Unicode de la API de Win32 ( GetCommandLineA ), y esa encoding nunca es segura para Unicode.

Muchos otros idiomas, incluidos Java y Ruby, están en el mismo barco; la limitación proviene de las implementaciones de Microsoft C runtime de las funciones estándar de la biblioteca de C. Para solucionarlo, uno llamaría a la versión Unicode ( GetCommandLineW ) en Windows en lugar de confiar en la biblioteca estándar multiplataforma. Python 3 hace esto.

Mientras tanto para Python 2, puede hacerlo llamando a GetCommandLineW usted mismo, pero no es especialmente bonito. También puede usar CommandLineToArgvW si desea la división de parámetros al estilo de Windows. Puede hacer esto con las extensiones de win32 o también simplemente con ctypes .

Ejemplo (aunque se omite el paso de codificar la cadena Unicode de nuevo a bytes UTF-8).

Usualmente uso una función util para la conversión segura de páginas de códigos habituales a Unicode. Para leer la encoding predeterminada del sistema operativo, probablemente la función locale.getpreferredencoding podría ayudar ( http://docs.python.org/2/library/locale.html#locale.getpreferredencoding ).

Ejemplo de función util que intenta convertir a Unicode mediante la iteración de algunas codificaciones predefinidas:

 # coding: utf-8 def to_unicode(s): if isinstance(s, unicode): return s from locale import getpreferredencoding for cp in (getpreferredencoding(), "cp1255", "cp1250"): try: return unicode(s, cp) except UnicodeDecodeError: pass raise Exception("Conversion to unicode failed") # or fallback like: # return unicode(s, getpreferredencoding(), "replace") print (to_unicode("addđšđč枎ŠĐ")) 

El retroceso podría habilitarse utilizando los errores de argumento de función Unicode = “reemplazar”. Consulte http://docs.python.org/2/library/functions.html#unicode

Para volver a convertir a una página de códigos, puedes verificar esto .