J'ai un fichier composé de JSON, chacun une ligne, et je veux trier le fichier par update_time inversé.
exemple de fichier JSON:
{ "page": { "url": "url1", "update_time": "1415387875"}, "other_key": {} }
{ "page": { "url": "url2", "update_time": "1415381963"}, "other_key": {} }
{ "page": { "url": "url3", "update_time": "1415384938"}, "other_key": {} }
veulent une sortie:
{ "page": { "url": "url1", "update_time": "1415387875"}, "other_key": {} }
{ "page": { "url": "url3", "update_time": "1415384938"}, "other_key": {} }
{ "page": { "url": "url2", "update_time": "1415381963"}, "other_key": {} }
mon code:
#!/bin/env python
#coding: utf8
import sys
import os
import json
import operator
#load json from file
lines = []
while True:
line = sys.stdin.readline()
if not line: break
line = line.strip()
json_obj = json.loads(line)
lines.append(json_obj)
#sort json
lines = sorted(lines, key=lambda k: k['page']['update_time'], reverse=True)
#output result
for line in lines:
print line
Le code fonctionne correctement avec un exemple de fichier JSON, mais si un JSON n'a pas de 'update_time', il déclenchera une exception KeyError. Existe-t-il des moyens sans exception de procéder?
Écrivez une fonction qui utilise try...except
pour gérer le KeyError
, puis utilisez-le comme argument key
au lieu de votre lambda.
def extract_time(json):
try:
# Also convert to int since update_time will be string. When comparing
# strings, "10" is smaller than "2".
return int(json['page']['update_time'])
except KeyError:
return 0
# lines.sort() is more efficient than lines = lines.sorted()
lines.sort(key=extract_time, reverse=True)
Vous pouvez utiliser dict.get()
avec une valeur par défaut:
lines = sorted(lines, key=lambda k: k['page'].get('update_time', 0), reverse=True)
Exemple:
>>> lines = [
... {"page": {"url": "url1", "update_time": "1415387875"}, "other_key": {}},
... {"page": {"url": "url2", "update_time": "1415381963"}, "other_key": {}},
... {"page": {"url": "url3", "update_time": "1415384938"}, "other_key": {}},
... {"page": {"url": "url4"}, "other_key": {}},
... {"page": {"url": "url5"}, "other_key": {}}
... ]
>>> lines = sorted(lines, key=lambda k: k['page'].get('update_time', 0), reverse=True)
>>> for line in lines:
... print line
...
{'other_key': {}, 'page': {'url': 'url1', 'update_time': '1415387875'}}
{'other_key': {}, 'page': {'url': 'url3', 'update_time': '1415384938'}}
{'other_key': {}, 'page': {'url': 'url2', 'update_time': '1415381963'}}
{'other_key': {}, 'page': {'url': 'url4'}}
{'other_key': {}, 'page': {'url': 'url5'}}
Cependant, je suivrais toujours le principe EAFP
que Ferdinand a suggéré - de cette façon, vous géreriez également les cas où la clé page
est également manquante. Il est beaucoup plus facile de le laisser échouer et de le gérer que de vérifier toutes sortes de cas d'angle.
# sort json
lines = sorted(lines, key=lambda k: k['page'].get('update_time', 0), reverse=True)