Python: 从EXIF中提取Cyrillic字符串

5
我是Python的完全新手,想通过实践来学习它。特别是,我想纠正一些我拥有的大量家庭照片中的EXIF信息。首先,我想正确地从JPEG文件中获取此信息。 其中一些文件中有EXIF中写的标题。可以通过以下方式获取该标题:
import pyexiv2
metadata = pyexiv2.ImageMetadata(filename)
metadata.read()
title = metadata['Exif.Image.XPTitle'] 

这是我目前为止的进展。现在遇到了问题。一些标题包含西里尔字母。如果我执行print title.human_value,例如,我会得到
`Милой Мамуле от Майи, 11 ÑÐ½Ð²Ð°Ñ€Ñ 1944.`

当使用print title时,它是这样的:
<Exif.Image.XPTitle [Byte] = 28 4 56 4 59 4 62 4 57 4 32 0 28 4 48 4 60 4 67 4 59 4 53 4 32 0 62 4 66 4 32 0 28 4 48 4 57 4 56 4 44 0 32 0 49 0 49 0 32 0 79 4 61 4 50 4 48 4 64 4 79 4 32 0 49 0 57 0 52 0 52 0 46 0 0 0>

The actual string I'd love to see is

Милой Мамуле от Майи, 11 января 1944.

看起来是一个Unicode问题,但是在这里和其他地方尝试了十几种不同的方法后,我就是无法解决它。是否有可能在控制台中看到俄文字母?我正在使用Windows 7(英语)上的python(xy),所以我的IDE是spyder2。只是默认安装,我添加了pyexiv2。谢谢!


让我们弄清楚我们的数据到底是什么。type(title.human_value)[ord(x) for x in title.human_value]分别返回什么? - Russell Borogove
@RussellBorogove: <type 'str'>[208, 156, 208, 184, 208, 187, 208, 190, 208, 185, 32, 208, 156, 208, 176, 208, 188, 209, 131, 208, 187, 208, 181, 32, 208, 190, 209, 130, 32, 208, 156, 208, 176, 208, 185, 208, 184, 44, 32, 49, 49, 32, 209, 143, 208, 189, 208, 178, 208, 176, 209, 128, 209, 143, 32, 49, 57, 52, 52, 46] - texnic
2个回答

4

这些字节是UTF-16编码。

在Python 3中:

>>> b = [28, 4, 56, 4, 59, 4, 62, 4, 57, 4, 32, 0, 28, 4, 48, 4, 60, 4, 67, 4, 59, 4, 53, 4, 32, 0, 62, 4, 66, 4, 32, 0, 28, 4, 48, 4, 57, 4, 56, 4, 44, 0, 32, 0, 49, 0, 49, 0, 32, 0, 79, 4, 61, 4, 50, 4, 48, 4, 64, 4, 79, 4, 32, 0, 49, 0, 57, 0, 52, 0, 52, 0, 46, 0, 0, 0]
>>> bytes(b).decode("utf-16")
'Милой Мамуле от Майи, 11 января 1944.\x00'

在Python 2中:

>>> b = [28, 4, 56, 4, 59, 4, 62, 4, 57, 4, 32, 0, 28, 4, 48, 4, 60, 4, 67, 4, 59, 4, 53, 4, 32, 0, 62, 4, 66, 4, 32, 0, 28, 4, 48, 4, 57, 4, 56, 4, 44, 0, 32, 0, 49, 0, 49, 0, 32, 0, 79, 4, 61, 4, 50, 4, 48, 4, 64, 4, 79, 4, 32, 0, 49, 0, 57, 0, 52, 0, 52, 0, 46, 0, 0, 0]
>>> "".join(chr(c) for c in b).decode("utf-16")
u'\u041c\u0438\u043b\u043e\u0439 \u041c\u0430\u043c\u0443\u043b\u0435 \u043e\u04
42 \u041c\u0430\u0439\u0438, 11 \u044f\u043d\u0432\u0430\u0440\u044f 1944.\x00'

它只能在Python 3中工作吗?我有2.7.2,但我得到了Traceback(最近的调用最后):文件“<stdin>”,第1行,在<module>文件“C:\ Python27 \ lib \ encodings \ utf_16.py”,第16行,在解码返回codecs.utf_16_decode(输入,错误,True) UnicodeDecodeError:'utf16'编解码器无法解码位置264中的字节0x5d:截断数据 - texnic
经过几天的搜索,我相信IDLE应该被设置为进行Unicode输出。但是我无法使其这样做。我的IDLE编码为'cp1252',Spyder编码为'none'。我尝试创建Windows环境变量PYTHONIOENCODING=utf-8,但它没有改变任何东西。你使用Mac,而默认编码可能是一些Unicode。 - texnic
我在Windows XP Pro(32位)上使用了IDLE。 - MRAB
你在Windows中的位置设置是什么? - texnic
我现在已经安装了Python 3,并且它的运行效果与你的第一个示例相同。我认为我们已经对这个问题进行了足够的阐述。在我看来,如果想要广泛使用非英语符号并使用控制台,那么应该尽可能地尝试切换到Python 3。非常感谢您的帮助! - texnic
显示剩余4条评论

1

我认为标题.human_value数据是以UTF-8格式编码的,已经从标题的原始UTF-16字节中解码出来。

在OSX上运行的终端窗口中的Python shell中:

>>> # this should be the same as your title.human_value:
>>> print ''.join( chr(x) for x in [208, 156, 208, 184, 208, 
              187, 208, 190, 208, 185, 32, 208, 156, 208, 
              176, 208, 188, 209, 131, 208, 187, 208, 181, 
              32, 208, 190, 209, 130, 32, 208, 156, 208, 
              176, 208, 185, 208, 184, 44, 32, 49, 49, 32, 
              209, 143, 208, 189, 208, 178, 208, 176, 209, 
              128, 209, 143, 32, 49, 57, 52, 52, 46])

Милой Мамуле от Майи, 11 января 1944.

您的控制台可能不支持 Cyrillic 字符。您可以尝试将命令提示符中的字体设置为“Lucida Console”——更现代的矢量字体比 cmd 默认使用的历史位图字体更有可能正确支持它。


没有帮助。使用 print u'привет' 我得到了 ??????。您的代码显示为 Милой Мамуле от Майи, 11 ÑÐ½Ð²Ð°Ñ€Ñ 1944.,与我的一样。这个问题可以通过 MRAB 的解决方案解决,但我仍然无法获得俄语符号。 - texnic
我认为这不是Python 2的问题(我正在使用Python 2.6),而是终端编码问题。在Python提示符下,尝试import sys; print sys.stdout.encoding - Russell Borogove
尝试将其设置为“utf-8”,然后再次打印字符串?我不确定我的系统编码是如何设置的... - Russell Borogove
我感到无助。我不知道如何设置它。此外,一些在帮助页面中提到的函数(例如sys.getdefaultencoding)在我的Python中没有出现!也许我应该先获得一些Python经验,然后再回到这个问题。与此同时,我正在使用一个解决方法:使用PyQt显示Unicode字符串。 - texnic

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