#python #json #iterator
#python #json #итератор
Вопрос:
[{"attributes": {"type": "Silo__c", "url": "/services/data/v38.0/sobjects/Silo__c/b0L36000007xRItEAM"}, "Id": "a0M36000007xRItEAM", "OwnerId": "00536000002yKlTAAU", "IsDeleted": false, "Name": "Fresh", "Landing_Stop_Date__c": null, "Service_Exit_Date__c": null},{"attributes": {"type": "Silo__c", "url": "/services/data/v38.0/sobjects/Silo__c/b0L36000007xRItEAM"}, "Id": "a0M36000007xRItEAM", "OwnerId": "00536000002yKlTAAU", "IsDeleted": false, "Name": "Fresh", "Landing_Stop_Date__c": null, "Service_Exit_Date__c": null},{"attributes": {"type": "Silo__c", "url": "/services/data/v38.0/sobjects/Silo__c/b0L36000007xRItEAM"}, "Id": "a0M36000007xRItEAM", "OwnerId": "00536000002yKlTAAU", "IsDeleted": false, "Name": "Fresh", "Landing_Stop_Date__c": null, "Service_Exit_Date__c": null},{"attributes": {"type": "Silo__c", "url": "/services/data/v38.0/sobjects/Silo__c/b0L36000007xRItEAM"}, "Id": "a0M36000007xRItEAM", "OwnerId": "00536000002yKlTAAU", "IsDeleted": false, "Name": "Fresh", "Landing_Stop_Date__c": null, "Service_Exit_Date__c": null},{"attributes": {"type": "Silo__c", "url": "/services/data/v38.0/sobjects/Silo__c/b0L36000007xRItEAM"}, "Id": "a0M36000007xRItEAM", "OwnerId": "00536000002yKlTAAU", "IsDeleted": false, "Name": "Fresh", "Landing_Stop_Date__c": null, "Service_Exit_Date__c": null}]
Приведенное выше очень похоже на JSON, который я получаю из запроса из simple salesforce.
Предполагается, что приведенное ниже превращает его в jsonl, а также исправляет проблемы с датой и временем.
Проблема в том, что мне нужно избавиться от раздела атрибутов, поскольку он не используется. приведенный ниже код является последней попыткой, но все, что приводит к одной и той же записи снова и снова. (приведенные выше данные повторяются, поэтому я бы ожидал, что они будут такими же, если вы их прогоните)
for element in data :
item = data.pop()
item.pop('attributes', None)
tempdict = OrderedDict({})
for k,v in item.items() :
if 'date' in k.lower() or 'stamp' in k.lower() :
if not v is None :
d = d_parse(v)
v = d.strftime('%Y-%m-%d %I:%M:%S')
tempdict[k.lower()] = v
else :
tempdict[k.lower()] = v
with open(localFilePath fileName.format(nextObj,fileCount), 'a') as outfile :
outfile.write(json.dumps(tempdict))
outfile.write('n')
Проблема в том, что по какой-то причине теряется 1/2 записей. Я получаю только 384 из 767 записей в файл. Я подозреваю, что проблема связана с pop и где это происходит в коде. Как я могу избавиться от раздела атрибутов, не потеряв 1/2 записей в pop?
Редактировать:
Следующий код выдает ошибку (на основе комментария):
for element in data :
data.pop('attributes', None)
tempdict = OrderedDict({})
for k,v in data.items() :
if 'date' in k.lower() or 'stamp' in k.lower() :
if not v is None :
d = d_parse(v)
v = d.strftime('%Y-%m-%d %I:%M:%S')
tempdict[k.lower()] = v
else :
tempdict[k.lower()] = v
with open(localFilePath fileName.format(nextObj,fileCount), 'a') as outfile :
outfile.write(json.dumps(tempdict))
outfile.write('n')
Traceback (most recent call last):
File "child_sfdc_etl.py", line 417, in <module>
sfToS3(fileCount, sf, nextObj)
File "child_sfdc_etl.py", line 206, in sfToS3
send_temp_jsonl_to_s3(data, nextObj, s3, s3Destination, fileCount, s3Path)
File "child_sfdc_etl.py", line 254, in send_temp_jsonl_to_s3
data.pop('attributes', None)
TypeError: pop() takes at most 1 argument (2 given)
Код без None также выдает ошибку:
for element in data :
data.pop('attributes')
tempdict = OrderedDict({})
for k,v in data.items() :
if 'date' in k.lower() or 'stamp' in k.lower() :
if not v is None :
d = d_parse(v)
v = d.strftime('%Y-%m-%d %I:%M:%S')
tempdict[k.lower()] = v
else :
tempdict[k.lower()] = v
with open(localFilePath fileName.format(nextObj,fileCount), 'a') as outfile :
outfile.write(json.dumps(tempdict))
outfile.write('n')
Traceback (most recent call last):
File "child_sfdc_etl.py", line 417, in <module>
sfToS3(fileCount, sf, nextObj)
File "child_sfdc_etl.py", line 206, in sfToS3
send_temp_jsonl_to_s3(data, nextObj, s3, s3Destination, fileCount, s3Path)
File "child_sfdc_etl.py", line 254, in send_temp_jsonl_to_s3
data.pop('attributes')
TypeError: 'str' object cannot be interpreted as an integer
Комментарии:
1. Зачем вы
item = data.pop()
вообще это делаете? Я думаю, проблема в том, что вы изменяете коллекцию, которую повторяете, во время итерации по ней. Я бы просто удалил первый всплывающий вызов.2. Если я попробую data.pop(‘attributes’, None), он выдает ошибку. Обратная трассировка опубликована в edit.
3. Вы перебираете вызываемую коллекцию
data
, для которой на каждый элемент ссылается переменнаяelement
, объявленная вами в цикле for , поэтому вам нужно сделатьelement.pop()
, а неdata.pop()
.
Ответ №1:
Это связано с тем, как итерация реализована в Python. Как указывали другие, виновником является
for element in data :
item = data.pop()
<...>
Итератор последовательности в Python сохраняет индекс текущего элемента, чтобы определить, что возвращать следующим (в общем случае невозможно корректно выполнить итерацию по последовательности, если она изменяется в процессе, так что это не ошибка).
Вы берете один элемент (начиная с начала списка) как element
. Затем вы берете и удаляете последний элемент в списке как item
и полностью игнорируете element
. Следующая итерация element
будет элементом после предыдущей element
. И так далее. Как следствие, вы будете обрабатывать только вторую половину исходного списка в обратном порядке.
Удалите data.pop()
и используйте element
.
Комментарии:
1. Спасибо вам обоим; Я ценю урок.