Python、Windows、ANSI编码——再次

16

你好

即使我真的尝试过,但当涉及到PythonWindowsAnsi字符编码时,我仍然卡住并感到绝望。我需要帮助,非常认真地...在过去的几个小时里搜寻网络没有任何帮助,只是让我疯狂。

我是Python的新手,所以我几乎不知道正在发生什么。我即将学习这门语言,因此我的第一个程序——几乎做完了——应该会从包含mp3的给定文件夹自动生成音乐播放列表。这除了一个问题之外都运行正常...

...我无法将Umlaute(äöü)写入播放列表文件中。

在找到解决sys.argv中“错误编码”的数据的方法后,我可以处理它。当阅读MP3的元数据时,我使用某种简单的字符替换来摆脱所有那些国际特殊字符,例如法语重音或这个奇怪的斜杠 (我甚至不知道如何输入它...) 的斯堪的纳维亚语字母“o”。一切都很好。

但是我至少想将提到的Umlaute写入播放列表文件中,这些字符在德国非常普遍。与元数据不同,我不关心一些缺失的字符或拼错的单词,这是相关的-因为现在我正在写文件的路径。

我尝试了许多不同的编码和解码方法,无法在此列出...该死,我甚至无法告诉自己一个半小时前尝试的哪些设置。我在网上找到了代码,在这里以及其他地方,它们似乎可以用于某些目的。只是对我来说无效。

我认为棘手的部分是:似乎问题在于我需要写入文件的 Ansi 格式。确实,我需要这个Ansi相关的东西。大约两个小时前,我成功地将内容写入了一个UTF-8的文件中,效果很好...直到我意识到我的播放器(Winamp,旧版本)以某种方式无法使用这些UTF-8播放列表文件。即使在编辑器中看起来正确,播放器也无法解析路径。

如果我将文件格式改回Ansi,则包含特殊字符的路径将被破坏。我只是猜测,但如果Winamp将这些UTF-8文件读取为Ansi,则会导致我目前正在经历的问题。

所以...

  1. 我必须在路径中写入äöü,否则它不会工作
  2. 它必须是ANSI-"编码"文件,否则它不会工作
  3. line.write(str.decode('utf-8'))这样的语句会破坏文件的功能
  4. 类似于# -*- coding: iso-8859-1 -*-的神奇注释在这里无效 (虽然当涉及到元数据和允许其中的字符时它很有帮助...)
  5. 哦,我正在使用Python 2.7.3。第三方模块依赖关系,你知道的...

有没有人能够指导我找到一条摆脱这种编码困境的路?任何帮助都是受欢迎的。如果我需要500行代码来编写其他功能或类,我会打出它们的。如果有用于处理此类事情的模块,请让我知道!我会购买它!任何有用的东西都将被测试。

感谢您的阅读,感谢任何评论,

问候!


3
请展示你正在使用的代码和样本数据,否则无法确定你出了什么问题。同时,你需要更清晰地解释你的问题。你说你遇到了很多问题,但又没有具体说明你遇到了哪些错误,你试图改变什么行为等等。 - BrenBarn
1
缩短问题的长度,否则很少有人会完全阅读。 - asheeshr
1
你使用的是哪个版本的Windows?如果我没记错的话,不是所有版本的Windows都支持路径中的非ASCII字符。此外,正如你所发现的那样,即使操作系统兼容,有些软件也无法与非ASCII路径很好地协作。 - Silas Ray
@sr2222:Windows一直支持8位路径名(包括代码页);完整的Unicode路径名从XP开始支持。 - Chris Morgan
@AshRj:...这通常是我告诉别人的,当然你是对的。因此,如果遇到问题无法用自己想要的方式表达自己,我会更加讨厌。哦,讽刺啊... - xph
显示剩余3条评论
3个回答

30

如评论中提到的,您的问题不是非常具体,因此我将尝试为您提供有关字符编码的一些提示,看看您是否可以将其应用于您的特定情况!

Unicode和编码

以下是有关编码的简要介绍。基本上,Python中表示文本的方法有两种:

  • unicode。您可以认为unicode是最终的编码方式,应该在任何地方都使用它。在Python 2.x源文件中,unicode字符串看起来像u'some unicode'
  • str。这是已编码的文本 - 为了能够阅读它,您需要知道编码(或猜测)。在Python 2.x中,这些字符串看起来像'some str'

这在Python 3中发生了改变(unicode现在称为str,而str现在称为bytes)。

那会产生什么影响?

通常,确保您的代码在执行时使用unicode并使用str进行I/O非常简单:

  • 您接收的所有内容都是已编码的,因此您需要使用input_string.decode('encoding')将其转换为unicode
  • 您需要输出的所有内容都是unicode,但需要进行编码,因此您需要使用output_string.encode('encoding')

最常见的编码是Windows上的cp-1252(在美国或欧盟系统上),以及Linux上的utf-8

将此应用于您的情况

我确实必须在路径中写入äöü,否则它将无法正常工作

Windows本地使用unicode来表示文件路径和名称,因此您实际上应该始终使用unicode来表示这些内容。

必须是ANSI编码的文件,否则它将无法正常工作

当写入文件时,请确保始终将输出通过output.encode('cp1252')(或在您的系统上可能使用的任何ANSI编码)进行处理。

像line.write(str.decode('utf-8'))这样的内容会破坏文件的功能

现在你可能已经意识到:

  • 如果str确实是一个str实例,Python将尝试使用utf-8编码将其转换为unicode,但然后会尝试再次对其进行编码(可能是ascii),以便将其写入文件中。
  • 如果str实际上是一个unicode实例,则Python首先会将其编码(可能是ascii,并且很可能会崩溃),然后才能对其进行解码。

底线是,您需要知道str是否是unicode,如果是,则应该对其进行encode处理。 如果它已经被编码,请不要触动它(或者如果编码不是您想要的编码,则进行decode,然后encode)。

像 # -- coding: iso-8859-1 -- 这样在脚本开头的神奇注释对此无济于事(尽管在涉及元数据和其中允许的字符时很有帮助...)

毫不意外,这只是告诉Python应该使用哪种编码来读取源文件,以便能够正确识别非ASCII字符。

哦,我正在使用Python 2.7.3。 第三方模块依赖项,你知道的...

Python 3可能是unicode和编码方面的重大更新,但这并不意味着Python 2.x不能使其正常工作!

这会解决你的问题吗?

你无法确定问题出在你的代码上,可能是你使用的播放器有问题。

一旦你输出了它,你应该确保你的脚本输出可以使用参考工具(如Windows资源管理器)进行读取。如果可以,但播放器仍然无法打开它,那么你应该考虑升级到更新的版本。


谢谢!我打算将它打印出来用作参考,这是我迄今为止找到的最好的解释。而且:它可行了!:-)...output.encode('cp1252')正是我所需要的。完美地工作!我真的不明白为什么我使用iso-8859...时会遇到麻烦,但在我的Win7上,cp1252就能解决问题。如果可以避免,我不想深入研究这种编码方式。此外,新版播放器可能能够更好地处理这些差异,但我不喜欢臃肿的软件,并且我有点陷入了这个播放器中......让它工作起来真的很棒。非常感谢! - xph
1
顺便说一句:所有以英语为母语的国家都应该感谢他们的字母表没有这么混乱。这是值得一提的优势。 - xph

6
在Windows中,有一种特殊的编码称为mbcs,它可以在当前默认的ANSI代码页和UNICODE之间进行转换。 例如,在西班牙语语言的PC上:
u'ñ'.encode('mbcs') -> '\xf1'
'\xf1'.decode('mbcs') -> u'ñ'

在Windows中,ANSI指的是当前默认的多字节代码页。对于西欧语言,Windows使用ISO-8859-1编码的字节串;对于东欧语言,Windows使用ISO-8859-2编码的字节串;对于其他语言,Windows使用相应的编码方式。更多信息请参见:

https://docs.python.org/2.4/lib/standard-encodings.html

另请参阅:

https://docs.python.org/2/library/sys.html#sys.getfilesystemencoding


1
它适用于使用ANSI编码的文件中的土耳其字符。谢谢。 - lonesomecodeboy

0

# -*- coding 注释声明源代码的字符编码(因此也是字节字符串文字,如'abc')。

假设您所说的“播放列表”是m3u文件,则根据此规范,您可能会受到使用的mp3播放器软件的限制。该规范仅说明文件包含文本,没有提及字符编码。

我个人观察到,各种mp3编码软件将使用不同的编码方式进行mp3元数据编码。有些使用UTF-8,而其他则使用ISO-8859-1。因此,您可能需要允许在配置中指定编码并将其保留在那里。


他在询问如何编写路径和文件名,而不是元数据。 - Silas Ray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接