Python 在事先不知道代码页的情况下,将原始字节字符串转换为Unicode

Python 在事先不知道代码页的情况下,将原始字节字符串转换为Unicode,python,windows,unicode,rawbytestring,Python,Windows,Unicode,Rawbytestring,使用右键单击菜单上下文时,windows将文件路径作为原始(字节)字符串类型传递 例如: path = 'C:\\MyDir\\\x99\x8c\x85\x8d.mp3' 我的应用程序中的许多外部包需要unicode类型字符串,因此我必须将其转换为unicode 如果我们事先知道原始字符串的编码(在本例中,它是cp1255),那就很容易了。然而,我不知道世界各地的每台计算机都会在本地使用哪种编码 如何将字符串转换为unicode?也许需要使用win32api?通常我使用自己的util函数来安全

使用右键单击菜单上下文时,windows将文件路径作为原始(字节)字符串类型传递

例如:

path = 'C:\\MyDir\\\x99\x8c\x85\x8d.mp3'
我的应用程序中的许多外部包需要
unicode
类型字符串,因此我必须将其转换为
unicode

如果我们事先知道原始字符串的编码(在本例中,它是
cp1255
),那就很容易了。然而,我不知道世界各地的每台计算机都会在本地使用哪种编码


如何将
字符串
转换为
unicode
?也许需要使用
win32api

通常我使用自己的util函数来安全地将常用代码页转换为unicode。对于读取默认操作系统编码,locale.getpreferredencoding函数可能会有所帮助()

尝试通过迭代一些预定义编码转换为unicode的util函数示例:

# 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đšđč枎ŠĐ"))
可以使用unicode函数参数errors=“replace”启用回退。参考文献


对于转换回某些代码页,您可以检查。

通常我使用自己的util函数将普通代码页安全地转换为unicode。对于读取默认操作系统编码,locale.getpreferredencoding函数可能会有所帮助()

尝试通过迭代一些预定义编码转换为unicode的util函数示例:

# 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đšđč枎ŠĐ"))
可以使用unicode函数参数errors=“replace”启用回退。参考文献


要转换回某些代码页,您可以检查。

不知道为什么您可能会得到DOS代码页(862)而不是ANSI(1255)-右键单击选项是如何设置的

无论哪种方式-如果您需要在参数中接受任意Unicode字符,则不能从Python2的
sys.argv
中接受。此列表由Win32 API的非Unicode版本(
GetCommandLineA
)返回的字节填充,并且该编码从来都不是Unicode安全的

包括Java和Ruby在内的许多其他语言都在同一条船上;该限制来自Microsoft C运行时对C标准库函数的实现。要解决这个问题,可以在Windows上调用Unicode版本(
GetCommandLineW
),而不是依赖于跨平台标准库。Python3就是这样做的

同时,对于Python2,您可以自己调用
GetCommandLineW
来实现这一点,但它并不特别漂亮。如果需要Windows样式参数splittng,也可以使用命令行argvw。您可以使用win32扩展名执行此操作,也可以使用普通的
ctypes


(尽管最好跳过将Unicode字符串编码回UTF-8字节的步骤)。

不知道为什么您可能会得到DOS代码页(862)而不是ANSI(1255)-右键单击选项是如何设置的

无论哪种方式-如果您需要在参数中接受任意Unicode字符,则不能从Python2的
sys.argv
中接受。此列表由Win32 API的非Unicode版本(
GetCommandLineA
)返回的字节填充,并且该编码从来都不是Unicode安全的

包括Java和Ruby在内的许多其他语言都在同一条船上;该限制来自Microsoft C运行时对C标准库函数的实现。要解决这个问题,可以在Windows上调用Unicode版本(
GetCommandLineW
),而不是依赖于跨平台标准库。Python3就是这样做的

同时,对于Python2,您可以自己调用
GetCommandLineW
来实现这一点,但它并不特别漂亮。如果需要Windows样式参数splittng,也可以使用命令行argvw。您可以使用win32扩展名执行此操作,也可以使用普通的
ctypes


(尽管最好跳过将Unicode字符串编码回UTF-8字节的步骤)。

ASCII是一种始终可以转换为Unicode的编解码器;只需
。解码('ASCII')
。你的意思不是ASCII,而是编码的字节。一般来说,你不能在不知道编码的情况下将字符串解码为unicode。您的文本不是ASCII,而是一些未知的编码。您的示例不是cp1255,使用该编解码器解码失败。它也不是UTF-16,这是令人惊讶的,因为Windows内部使用UTF-16作为文件名;path.decode(locale.getpreferredencoding())可能有用吗?根据您的断言,这是
cp1255
(希伯来语),我尝试了一些其他编解码器;这实际上是所有的
cp856
cp862
;两者都将您提供的字节解码为:
C:\MyDir\שלום。mp3
ASCII是一种始终可以转换为Unicode的编解码器;只需
。解码('ASCII')
。你的意思不是ASCII,而是编码的字节。一般来说,你不能在不知道编码的情况下将字符串解码为unicode。您的文本不是ASCII,而是一些未知的编码。您的示例不是cp1255,使用该编解码器解码失败。它也不是UTF-16,这是令人惊讶的,因为Windows内部使用UTF-16作为文件名;path.decode(locale.getpreferredencoding())可能有用吗?根据您的断言,这是
cp1255
(希伯来语),我尝试了一些其他编解码器;这实际上是所有的
cp856
cp862
;两者都将您提供的字节解码为:
C:\MyDir\שלום.mp3