Python: erstellen Sie eine Liste generator JSON serialisierbar
Wie kann ich mit concat eine Liste von JSON-Dateien in eine riesige JSON-array? Ich habe 5000 Dateien und 550 000 Einträge.
Meine Faust versuchen zu nutzen, um die jq, aber es sieht aus wie jq -s ist nicht optimiert für einen großen Eingang.
jq -s -r '[.[][]]' *.js
Dieser Befehl funktioniert, aber es dauert viel zu lange, um abzuschließen, und ich möchte wirklich, diese zu lösen mit Python.
Hier ist mein Derzeitiger code:
def concatFiles(outName, inFileNames):
def listGenerator():
for inName in inFileNames:
with open(inName, 'r') as f:
for item in json.load(f):
yield item
with open(outName, 'w') as f:
json.dump(listGenerator(), f)
Ich bin immer:
TypeError: <generator object listGenerator at 0x7f94dc2eb3c0> is not JSON serializable
Jeder Versuch, laden Sie alle Dateien in den ram ausgelöst wird der OOM-killer von Linux. Haben Sie irgendwelche Ideen?
Wie sieht es genau inhaltlich in der Verknüpfung der Dokumente, das einfügen von Kommata zwischen?
Sie müssen entfernen Sie das äußere array die einzelnen Dateien. Entfernen Sie die Faust und letzten Zeichen jeder Datei sollte funktionieren, aber ich würde gerne Steuern (und entfernen) die json-Einzug.
wie groß sind die Dateien eigentlich? könnte es sein, dass die Durchführung der kompletten serialisierten Daten ist größer als Ihr Gedächtnis ?
Ja, das ist der Grund, warum Anrufliste(..) ist nicht zur Arbeit gehen.
Sie müssen auch Validierung der JSON-vor der Verarbeitung? Wenn nicht, gibt es keine Notwendigkeit, zu konvertieren string -> JSON -> Zeichenfolge. Setzen Sie einfach Kommas zwischen den einzelnen filestream-und surround mit
Sie müssen entfernen Sie das äußere array die einzelnen Dateien. Entfernen Sie die Faust und letzten Zeichen jeder Datei sollte funktionieren, aber ich würde gerne Steuern (und entfernen) die json-Einzug.
wie groß sind die Dateien eigentlich? könnte es sein, dass die Durchführung der kompletten serialisierten Daten ist größer als Ihr Gedächtnis ?
Ja, das ist der Grund, warum Anrufliste(..) ist nicht zur Arbeit gehen.
Sie müssen auch Validierung der JSON-vor der Verarbeitung? Wenn nicht, gibt es keine Notwendigkeit, zu konvertieren string -> JSON -> Zeichenfolge. Setzen Sie einfach Kommas zwischen den einzelnen filestream-und surround mit
[]
.InformationsquelleAutor Sebastian Wagner | 2014-02-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollten Sie stammen aus
list
und überschreiben__iter__
Methode.Ergebnis ist
[1, [1, 2, 3], [20, 30, 40]]
.StreamArray
- Klasse hat auch das überschreiben der__len__
- Methode und liefert einen Wert größer als 0 (1 zum Beispiel). Ansonsten ist die json-encoder nicht selbst nennen sich die__iter__
MethodeBitte beachten Sie, dass diese Lösung schafft ungültige JSON verwendet werden, wenn mit Einzug - parameter und die iterierbar ist "leer".
json.dumps({"products": StreamArray()}, indent=2) # {"products": ]}
Ich glaube, wir sollten nicht
return 1
für die Länge, wenn die iterierbar ist "leer".das ist toll - prost
InformationsquelleAutor Vadim Pushtaev
Als der simplejson 3.8.0, können Sie die
iterable_as_array
- option, um jede iterierbar serializable in ein arrayErgebnis ist
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
InformationsquelleAutor Nick Babcock
Einen kompletten einfacher lesbar-Lösung, die die Serialisierung einen generator, der aus einer normalen oder leer iterierbar arbeiten kann .encode() oder .iterencode(). Schriftliche Prüfungen. Getestet mit Python 2.7, 3.0, 3.3, 3.6
Verwendete Lösungen: Vadim Pushtaev (unvollständig), user1158559 (unnötig kompliziert) und Claude (in einer anderen Frage, die auch kompliziert).
Nützliche Vereinfachung sind:
__init__
weil wir erwarten können, dass die SerializableGenerator können sofort abgerufen werden, bevor json.dumps. (gegen user1158559 Lösung)__repr__
. Es ist besser, zu speichern, den generator auch auf die Liste, um aussagekräftige Ergebnisse wie[<generator object ...>]
. (gegen Claude). Standard-Methoden__len__
und__bool__
funktioniert nun richtig zu erkennen, eine leere und nicht leere Objekt.Vorteil dieser Lösung ist, dass ein standard-JSON-serializer verwendet werden können, ohne Parameter. Wenn geschachtelte Generatoren unterstützt werden sollte oder wenn die Kapselung von
SerializableGenerator(iterator)
unerwünscht ist, dann empfehle ich IterEncoder Antwort.InformationsquelleAutor hynekcer
Basierend auf der akzeptierten Antwort, hier ist die StreamArray ich ging schließlich für. Es enthält zwei Lügen:
self.__tail__
möglicherweise unveränderlichlen(StreamArray(some_gen))
ist entweder 0 oder 1.
Nur einmal verwenden!
Deins sieht gut aus! Für meinen use-case, träge Bewertung das erste Element ist ein feature. Im Nachhinein könnte es eine Vereinfachung dadurch erreicht werden
itertools
. Sehr froh zu wissen, dass das funktioniert.InformationsquelleAutor user1158559