0

Есть код на питоне

data = json.loads(urllib2.urlopen("http://...").read())

С сайта скачивается текст:

{"msg":"Text"}

И я никак не могу вытащить значение msg из data. Print data возвращает ошибку. Что я делаю не так и как мне получить свои данные?

ReinRaus
  • 17,873
  • 3
  • 47
  • 86
mikelsv
  • 3,046
  • 1
  • 20
  • 48
  • @mikelsv, вы уверены, что urllib2...read() возвращает именно то, что нужно? – etki Sep 04 '14 at 23:17
  • print json.dumps(urllib2.urlopen... выводит "{'msg':'Text'}" – mikelsv Sep 04 '14 at 23:29
  • @mikelsv, одиночные апострофы - это невалидный json. Если есть доступ к серверу - надо поменять сериализацию, если нет - менять апострофы на кавычки и надеяться на лучшее. – etki Sep 05 '14 at 00:14
  • Всем валидный, питону нет. Ок, replace("'", """). – mikelsv Sep 05 '14 at 00:43
  • @mikelsv, по спеке невалидный. – etki Sep 05 '14 at 01:22
  • print json.dumps(urllib2.urlopen.. выглядит неправильно. Что происходит, если попробовать: print(urllib2.urlopen..? Что печатает: print repr(data['msg'])? – jfs Sep 10 '14 at 20:14

2 Answers2

1

В доках написано, что следуют RFC 4627. В стандарте не нашел упоминание про одинарные кавычки, "все", наверное, не полностью следуют стандарту )

К тому же:

a = "{'msg':'Text'}"
json.loads(a) # ValueError: Expecting property name

но при этом:

a = u"{'msg':'Text'}"
json.loads(a) # ValueError: Expecting property name enclosed in double quotes

Т.е. если бы привели к UTF-8, то ошибка была бы информативнее )

Тем более, что по тому же стандарту:

"A string is a sequence of zero or more Unicode characters".

BOPOH
  • 4,855
  • Ой... я кавычки перепутал ) Но ошибки - верны. – BOPOH Sep 05 '14 at 01:45
  • Несоответствие данных приведённым ошибкам вводит в заблуждение. {"msg":"Text"} - это правильный json текст. OP говорит, что ошибка возникает на этапе print data после успешного json распознавания. – jfs Sep 10 '14 at 20:38
  • @jfs, я же в комментарии поправился - кавычки перепутал. Т.е. надо не '{"msg":"Text"}', а "{'msg':'Text'}". Чтобы не смущало, сейчас поправлю. Это во-первых.

    А во-вторых - вы комментарий ТС выше посмотрите - у него невалидный JSON. Вы же не знаете, как он его получает, он, может, в блок try парсинг вставил. Вот и при парсинге ошибки нет.

    Либо "Print data" у него имеется ввиду: print json.loads

    – BOPOH Sep 11 '14 at 00:10
  • Я читал первый комментарий и не мог понять, почему ответ не был отредактирован. Существует какой-то лимит на редактирование своего ответа? – jfs Sep 11 '14 at 05:49
  • @jfs, вроде как 10 редактирований автором делает ответ "вики-ответом", раньше, по крайней мере, так было. Я как-то не претендую на "вики", поэтому стараюсь лишний раз не редактировать )

    А вообще - лень было )) Комментарий быстрее написать было.

    – BOPOH Sep 11 '14 at 06:01
0

Если ошибка возникает только во время вывода на печать, то проблема может быть в печати Юникодных строк в консоли. repr() может вернуть ascii представление для строки, чтобы помочь отладить проблему:

import json
from contextlib import closing
from urllib2 import urlopen
url = "http://..."
with closing(urlopen(url)) as r:
    data = json.load(r)
print repr(data['msg'])
print data['msg']

Если ошибка возникает только на втором print, то можно установить переменную окружения PYTHONIOENCODING в кодировку, которая понимает все символы в data['msg'], например, utf-8 и перенаправить вывод в файл, если кодировка в консоли не utf-8. Как из Python вывести на Windows-консоль строку в Юникоде? На Unix это проще, достаточно использовать utf-8 локаль, например, C.UTF-8 или ru_RU.utf8.

jfs
  • 52,361