2016-07-11 4 views
0

Ich habe den folgenden Code, aber aus irgendeinem Grund ist es nur die erste Zeile für das Auto schreiben und ignorieren jedes Auto nach.Python - keine zusätzlichen Zeilen von JSON

bearbeiten - Ich habe versucht, eine print field in die Zeile nach for field in required_fields: und aus irgendeinem Grund zeigt es nur das Feld bei der Analyse der ersten Zeile. Jede weitere Zeile gibt [] für jedes Feld zurück.

Was ich in der csv sehen, ist der Header und eine Zeile und dann ,,,,

import csv 
import json 

car_list = [ 
    { 
    "Year": 1997, 
    "Make": "Ford", 
    "Model": "E350", 
    "Description": "ac, abs, moon", 
    "Price": 3000 
    }, 
    { 
    "Year": 1999, 
    "Make": "Chevy", 
    "Model": "Venture \"Extended Edition\"", 
    "Price": 4900 
    }, 
    { 
    "Year": 1999, 
    "Model": "Venture \"Extended Edition, Very Large\"", 
    "Description": "", 
    "Price": 5000 
    }, 
    { 
    "Year": 1996, 
    "Make": "Jeep", 
    "Model": "Grand Cherokee", 
    "Description": "MUST SELL!air, moon roof, loaded", 
    "Price": 4799 
    } 
] 


def _get_attr(dict_, attrs): 
    try: 
     src = attrs[:] 
     root = attrs.pop(0) 
     node = dict_[root] 
     null = object() 
     for i, attr in enumerate(attrs[:]): 
      try: 
       node = node.get(attr, null) 
      except AttributeError: 
       node = null 
      if node is null: 
       # i+2 pop and last element 
       raise ValueError("%s not present (level %s)" % (attr, '->'.join(src[: i+2]))) 
     return node 
    except KeyError: 
     raise ValueError("%s not present" % root) 

required_fields = [ 
    ['Year'], 
    ['Make'], 
    ['Model'], 
    ['Description'], 
    ['Price'] 
] 

f = csv.writer(open('test.csv', 'wb+')) 

f.writerow(['Year', 
      'Make', 
      'Model', 
      'Description', 
      'Price']) 

for car in car_list: 
    row_values = [] 
    for field in required_fields: 
     try: 
      row_values.append(_get_attr(car, field)) 
     except: 
      row_values.append('') 
    f.writerow(row_values) 
+0

Weil 'attrs.pop (0)' dein 'Feld' von' required_fields' entfernt. Listen werden als Referenz übergeben, nicht als Wert. –

+0

ah ok. Wie bekomme ich es auf die ersten "erforderlichen Felder" in jeder Schleife zurückgesetzt? – whoisearth

Antwort

1

Der Grund dafür ist, weil aus einer Kombination von zwei Dingen geschieht:

  • Listen (und allgemeiner wandelbar Objekte) sind in Python als Referenz übergeben. Das Mutieren einer Liste, die als Argument an eine Funktion übergeben wird, mutiert diese Liste global.

  • Sie mutieren attrs übergeben an _get_attr durch den Aufruf attrs.pop(0). Dies entfernt das Feld überall, einschließlich in required_fields.

Ein viel besserer Weg, was Sie tun wollen, während nativen Python:

required_fields = ['Year', 'Make', 'Model','Description','Price'] 

for car in car_list: 
    row_values = [car.get(field, '') for field in required_fields] 
    f.writerow(row_values) 

Dies geschieht sofort betreut möglicherweise fehlende Werte durch die Kraft der get() auf Wörterbücher mit einem Standardwert zu liefern - '' in diesem Fall - wenn ein Schlüssel fehlt, und erfordert keine unordentliche _get_attr Funktion entweder.

+0

Ich bekomme eine Traceback bei diesem Versuch - "Traceback (zuletzt letzten Anruf): Datei" test.py ", Zeile 74, in row_values ​​= [car.get (Feld, '') für Feld in erforderlichen Feldern] TypeError: nicht hashbarer Typ: 'list'' – whoisearth

+0

@whoisearth Edited. Sie müssen Ihre erforderlichen Feldnamen nicht in eine eigene spezielle Liste aufnehmen. :) –

+0

müssen meine required_fields zu einer geraden Liste ändern. macht Sinn. Problem ist, wenn ich einen Wert habe wie '['Make'] ['Sub-Type']' – whoisearth

0

Die Daten in car_list ist bereits als Liste der Wörterbücher strukturiert, verwenden warum nicht ein DictWriter statt dessen:

import csv 

fieldnames = ['Year', 
      'Make', 
      'Model', 
      'Description', 
      'Price'] 
f = csv.DictWriter(open('test.csv', 'wb+'), fieldnames=fieldnames) 
f.writeheader() 

f.writerows(car_list) # write all rows at once 

Wenn Sie nicht sicher sind, über Feldnamen in der definierten Kopf- und cars_list, dann anstelle einer einzelnen Zeile writerows passend, können Sie writerow in einer Schleife mitverwendenaufzuräumen Reihen, bevor sie an die csv schreiben:

for car in car_list: 
    for field in car: 
     if field not in fieldnames: 
      del car[field] 
    f.writerow(car) 
+0

Ich kann in das schauen, aber wie gezeigt einige Felder möglicherweise nicht existieren und Beispiel zeigt es nicht an, aber die Überschriften unterscheiden sich schließlich als der Schlüssel im json. – whoisearth

+0

@whoisearth Felder, die nicht vorhanden sind, werden als leeres '' '' geschrieben, wie Sie in Ihrem Code haben –

+0

ah cool gehen mit diesem jetzt basteln :) Wenn es funktioniert, mache ich abgeschlossen. – whoisearth

Verwandte Themen