Контекст
У меня есть питон код, который я использую для чтения метаданных из видеофайла с помощью ffprobe. Я запускаю команду ffprobe в качестве подпроцесса, собирая stdout (который находится в формате JSON), а затем преобразовываю его в словарь python. Код выглядит примерно так:набор символов преобразования Python
query = FFprobeQuery()
stdout, stderr = query.run(video)
Это работает в ffprobe команду в качестве подпроцесса вызова. Команда ffprobe является:
ffprobe -print_format json -show_streams "video.mov"
стандартный вывод является:
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264/AVC/MPEG-4 AVC/MPEG-4 part 10",
"codec_type": "video",
"codec_time_base": "1/2000000",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 960,
"height": 540,
"has_b_frames": 0,
"pix_fmt": "yuv420p",
"level": 31,
"is_avc": "1",
"nal_length_size": "4",
"r_frame_rate": "1000000/41667",
"avg_frame_rate": "55000000/2291667",
"time_base": "1/1000000",
"start_time": "0.000000",
"duration": "2.291667",
"bit_rate": "2090617",
"nb_frames": "55",
"tags": {
"creation_time": "2013-11-04 09:38:31",
"language": "eng",
"handler_name": "Apple ╠µ╔Ý╩²¥¦┤ª└Ý│╠ð‗"
}
}
]
Затем преобразовать вышеупомянутую строку (стандартный вывод) в словарь питона, используя json пакет:
video_data = json.loads(stdout)
Ошибка
Процесс, описанный выше, обычно работает нормально, но в этом случае UnicodeDecodeError
поднят по вызову json.loads(stdout)
. Я не включил всю трассировку стека, но ошибка выглядит примерно так.
UnicodeDecodeError: 'utf8' codec can't decode byte 0xcc in position 6: invalid continuation byte
Важно отметить, что в данном конкретном случае, видеофайл был отправлен из Китая, поэтому я предполагаю, есть символы в строке стандартного вывода, которые вызывают ошибку, поднятую json.loads(stdout)
вызова. Мое предположение - это значение имени обработчика Apple ╠µ╔Ý╩²¥¦┤ª└Ý│╠ð‗
.
Решения
Моей теории в том, что стандартный выводе строка нужно быть преобразована из некоторых китайского кодека в какой-то другой кодек. После ковыряться немного я обнаружил, что следующий код (преобразование стандартного вывода GB2312
в ascii
с использованием chardet) на самом деле работает:
import json
import chardet
detection = chardet.detect(stdout)
encoding = detection.get('encoding')
decoded_stdout = stdout.decode(encoding)
video_data = json.loads(decoded_stdout)
Вопросы
Я ничего не знаю о наборах символов, так что я пытаюсь:
1. Определите, применил ли я правильный подход?
2. Поймите, почему код преобразования, который я написал, действительно работает?
3. Определить, может ли проблема быть решена с использованием стандартной библиотеки python?
Все комментарии высоко оценены.
Сначала прочтите следующее: http://www.joelonsoftware.com/articles/Unicode.html –
@ Peter DeGlopper. Очень информативно! Благодаря! Я всегда буду стремиться включать определение Content-Type или какой-либо другой тег, описывающий кодировку набора символов для текстовых данных. – Yani