итерация по нескольким линиям json

button('hey') вызывает функцию, а не устанавливает ее как обратный вызов.

1
задан U9-Forward 14 July 2018 в 00:40
поделиться

1 ответ

У меня есть файл с сотнями строк JSON в нем.

Нет, вы этого не сделали, и в этом проблема.


Сотни текстов JSON не являются допустимым файлом JSON. Действительный файл JSON - это всего лишь один текст. Вот почему json.load возвращает ошибку.


Сотни текстов JSON, каждая из которых соответствует только одной строке с символами новой строки между ними , является действительным файлом в другом форматы, такие как JSONlines или NDJ. Он все еще не является допустимым файлом JSON, поэтому вы не можете использовать json.load, но вы можете использовать JSONlines или библиотеку NDJ или просто разбирать его следующим образом:

with open('fixed.json') as f:
    for line in f:
        data = json.loads(line)
        # do stuff

Для записи файла JSONlines , опять же, вы можете использовать библиотеку JSONlines, или вы можете просто убедиться, что в каждом тексте JSON нет встроенных новых строк, что фактически происходит по умолчанию, если вы не укажете параметры, отличные от параметров по умолчанию ensure_ascii или indent, и просто напишите json.dumps(data) + "\n" для каждого значения.


Но сотни текстов JSON, каждая из которых занимает несколько строк, не является допустимым файлом.

Это на самом деле , объясненный в модуле json docs :

Примечание. В отличие от pickle и marshal, JSON не является фрейм-протоколом, поэтому попытка сериализации нескольких объектов с повторением вызовы на dump() с использованием того же fp приведут к недопустимому файлу JSON.

Что означает «не связанный с кадром протокол», это в основном то, что формат будет неоднозначный. Например, если вы сделали json.dump(2, f), а затем json.dump(3, f), то, что вы получили в вашем файле, - 23. Это то же самое, что вы получаете от json.dump(23, f).


Если вы можете исправить ваш файл как нечто действительное, например JSONlines, это простое решение.


Если вы не можете ...

Ну, перед стандартизацией была концепция «документа JSON», что означало в основном текст JSON, который является либо массивом, либо объектом. И поток документов JSON not неоднозначен.

Поскольку это не стандартный формат, вы, вероятно, не найдете для него синтаксический анализатор, так что вы будете должен написать один.

Один из способов сделать это - использовать метод raw_decode в модуле json. Это попытается декодировать текст JSON, возможно, после него, после чего добавит лишний материал, а также вернет индекс для этого дополнительного материала. Что, в вашем случае, является следующим документом JSON.

Поскольку сотни объектов такого размера не слишком велики, вероятно, проще просто прочитать весь файл в памяти, а затем проанализировать его, поэтому мы не нужно беспокоиться о буферизации:

with open('fixed.json') as f:
    contents = f.read()
decoder = json.JSONDecoder()
while contents:
    data, idx = decoder.raw_decode(contents)
    do_stuff(data)
    contents = contents[idx:].lstrip()

Помните, что это будет работать, только если ваш файл является потоком документов JSON, то есть значения верхнего уровня всегда представляют собой Array или Object. Кроме того, если вы редактируете эти файлы вручную, в отличие от JSONlines, которые могут пропустить один плохой текст и продолжать разбирать остальные, теперь можно восстановить из-за ошибки здесь, потому что вы понятия не имеете, где начинается следующий документ.

1
ответ дан abarnert 17 August 2018 в 12:04
поделиться
  • 1
    Спасибо за ответ, но ваше предложение json.loads(line) не работает :(, я получаю сообщение об ошибке – cerr 14 July 2018 в 01:52
  • 2
    @cerr Во-первых, ответ не предполагает, что это объясняет, почему это не сработает, если вы не исправите свои данные. Во-вторых, «я получаю сообщение об ошибке» - это не то, от чего вы можете отлаживать вас. в этом случае я могу угадать, какую ошибку вы получите, потому что я уже знаю, почему этот код не будет работать для ваших данных, но в целом, если вы хотите, чтобы люди вам помогали, вам нужно предоставить им достаточную информацию, чтобы помочь. – abarnert 14 July 2018 в 02:05
  • 3
    Я понимаю, но я буквально получаю Traceback (most recent call last):\nFile "read.py", line 9, in <module>\ndata= json.loads(line), затем File "/usr/lib/python2.7/json/__init__.py", line 339, in loads\nreturn _default_decoder.decode(s) – cerr 14 July 2018 в 03:17
  • 4
    проблема заключается в следующем: у меня есть файл журнала с целым рядом информации и некоторые строки JSON чередуются. Затем я grepped строки JSON и помещал их в один файл для извлечения данных, которые меня интересуют ... – cerr 14 July 2018 в 03:20
  • 5
    @cerr Показывает мне часть трассировки, которая даже не содержит тип ошибки или сообщение, не очень полезно, но это не имеет значения. Первая строка вашего файла не является текстом JSON. Поэтому, если вы назовете json.loads(line) на нем, вы получите JSONDecodeError. То, что у вас есть, - это не файл JSONlines, не более, чем файл JSON, поэтому он пытается декодировать его, поскольку он будет терпеть неудачу. Я не знаю, как это объяснить. – abarnert 14 July 2018 в 03:22
Другие вопросы по тегам:

Похожие вопросы: