2016-07-11 1 views
0

У меня есть код ниже, но по какой-то причине он пишет только первую строку для автомобиля и игнорирует каждый автомобиль после.python - не печатать дополнительные строки от json

Редактировать - Я попытался положить print field в строку после for field in required_fields: и по какой-то причине он отображает поле только при разборе первой строки. Каждая дополнительная строка возвращает [] для каждого поля.

Что я вижу в CSV-файл является заголовок и одна строка, а затем ,,,,

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

Поскольку 'attrs.pop (0)' удаляет ваше 'поле' из' required_fields'. Списки передаются по ссылке, а не по значению. –

+0

ах ок. так как я могу получить его для возврата к исходным 'required_fields' в каждом цикле? – whoisearth

ответ

1

Причина это происходит из-за сочетания двух вещей:

  • Списки (и вообще изменяемых объекты) передан по ссылке в Python. Мутирование списка, переданного в качестве аргумента функции, мутирует этот список глобально.

  • Ты мутировавший attrs, поступил в _get_attr по телефону attrs.pop(0). Это удаляет поле повсюду, в том числе в required_fields.

Намного лучше делать то, что вы хотите, используя родную 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) 

Это сразу же берет на себя, возможно, пропущенных значения, используя силу get() на словарях указать значение по умолчанию - '' в этом случае - если отсутствует ключ и не требует бесполезной функции _get_attr.

+0

Я получаю трассировку при попытке - «Traceback (последний последний вызов): Файл« test.py », строка 74, в row_values ​​= [car.get (поле, '') для поля в обязательных_полях] TypeError: unhashable type: 'list'' – whoisearth

+0

@whoisearth Отредактировано. Нет необходимости помещать ваши обязательные имена полей в их собственный специальный список. :) –

+0

должны изменить мои обязательные поля в прямой список. имеет смысл. проблема в том, что если у меня есть значение типа '['Make'] ['Sub-Type']' – whoisearth

0

Данные car_list уже структурирована в виде списка словарей, почему бы не использовать DictWriter вместо этого:

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 

Если вы не уверены в соответствии имен полей в определенном заголовке и cars_list, то вместо одной строки writerows, вы можете использовать writerow в цикле с del убирать строки перед записью в формате CSV:

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

Я могу посмотреть на это, но, как показано, некоторые поля могут не существовать, и пример не показывает его, но заголовки в конечном итоге будут отличаться от ключа в json. – whoisearth

+0

@whoisearth Поля, которые не существуют, написаны как пустые '' '', как у вас есть в вашем коде –

+0

ах круто собираюсь возиться с этим сейчас :) если он работает, я сделаю завершенным. – whoisearth

Смежные вопросы