Python API中缺少JSON字段时的防御条件
我正在开发一个小的Python脚本,以便从forecast.io获取天气数据。一旦我获得JSON文档,我就调用一个类,以便创建一个新记录保存在数据库中。问题是有些字段(在我的类中也是属性)并不总是在API中通知,所以我必须包含某种防御代码,否则当找不到字段时脚本将中断 我发现@Alex Martelli的答案非常好: 如果您希望执行与使用默认值不同的操作(例如, 如果没有键,则完全跳过打印),则需要 多一点结构,即:Python API中缺少JSON字段时的防御条件,python,json,api,mongoengine,Python,Json,Api,Mongoengine,我正在开发一个小的Python脚本,以便从forecast.io获取天气数据。一旦我获得JSON文档,我就调用一个类,以便创建一个新记录保存在数据库中。问题是有些字段(在我的类中也是属性)并不总是在API中通知,所以我必须包含某种防御代码,否则当找不到字段时脚本将中断 我发现@Alex Martelli的答案非常好: 如果您希望执行与使用默认值不同的操作(例如, 如果没有键,则完全跳过打印),则需要 多一点结构,即: for r in results: if 'key_name' in
for r in results:
if 'key_name' in r:
print r['key_name']
或
for r in results:
try: print r['key_name']
except KeyError: pass
但我想知道我是否必须在我想保存的每个字段上都包含一个“如果”或“尝试”,或者是否有一个更漂亮的方法来做到这一点?(我想保存27个字段和27个“如果”看起来很难看)
这是我目前掌握的代码:
from datetime import datetime
import tornado.web
import tornado.httpclient
from tornado import gen
from src.db.city import list_cities
from src.db.weather import Weather
from motorengine import *
@gen.coroutine
def forecastio_api():
http_client = tornado.httpclient.AsyncHTTPClient()
base_url = "https://api.forecast.io/forecast/APIKEY"
city yield list_cities()
for city in city:
url = base_url + "/%s,%s" %(str(city.loc[0]), str(city.loc[1]))
response = yield http_client.fetch(url)
json = tornado.escape.json_decode(response.body)
for day in json['daily']['data']:
weather = Weather(city=city,
time = datetime.fromtimestamp(day['time']),
summary = day.get('summary'),
icon = day.get('icon'),
sunrise_time = datetime.fromtimestamp(day.get('sunriseTime')),
sunset_time = datetime.fromtimestamp(day.get('sunsetTime')),
moon_phase = day.get('moonPhase'),
precip_intensity = day.get('precipIntensity'),
precip_intensity_max = day.get('precipIntensityMax'),
precip_intensity_max_time = datetime.fromtimestamp(day.get('precipIntensityMaxTime')),
precip_probability = day.get('precipProbability'),
precip_type = day.get('precipType'),
temperature_min = day.get('temperatureMin'),
temperature_min_time = datetime.fromtimestamp(day.get('temperatureMinTime')),
temperature_max = day.get('temperatureMax'),
temperature_max_time = datetime.fromtimestamp(day.get('temperatureMaxTime')),
apparent_temperature_min = day.get('apparentTemperatureMin'),
apparent_temperature_min_time = datetime.fromtimestamp(day.get('apparentTemperatureMinTime')),
apparent_temperature_max = day.get('apparentTemperatureMax'),
apparent_temperature_max_time = datetime.fromtimestamp(day.get('apparentTemperatureMaxTime')),
dew_point = day.get('dewPoint'),
humidity = day.get('humidity'),
wind_speed = day.get('windSpeed'),
wind_bearing = day.get('windBearing'),
visibility = day.get('visibility'),
cloud_cover = day.get('cloudCover'),
pressure = day.get('pressure'),
ozone = day.get('ozone')
)
weather.create()
if __name__ == '__main__':
io_loop = tornado.ioloop.IOLoop.instance()
connect("DATABASE", host="localhost", port=27017, io_loop=io_loop)
forecastio_api()
io_loop.start()
这是使用Motornegine的天气等级:
from tornado import gen
from motorengine import Document
from motorengine.fields import DateTimeField, DecimalField, ReferenceField, StringField
from src.db.city import City
class Weather(Document):
__collection__ = 'weather'
__lazy__ = False
city = ReferenceField(reference_document_type=City)
time = DateTimeField(required=True)
summary = StringField()
icon = StringField()
sunrise_time = DateTimeField()
sunset_time = DateTimeField()
moon_phase = DecimalField(precision=2)
precip_intensity = DecimalField(precision=4)
precip_intensity_max = DecimalField(precision=4)
precip_intensity_max_time = DateTimeField()
precip_probability = DecimalField(precision=2)
precip_type = StringField()
temperature_min = DecimalField(precision=2)
temperature_min_time = DateTimeField()
temperature_max = DecimalField(precision=2)
temperature_max_time = DateTimeField()
apparent_temperature_min = DecimalField(precision=2)
apparent_temperature_min_time = DateTimeField()
apparent_temperature_max = DecimalField(precision=2)
apparent_temperature_max_time = DateTimeField()
dew_point = DecimalField(precision=2)
humidity = DecimalField(precision=2)
wind_speed = DecimalField(precision=2)
wind_bearing = DecimalField(precision=2)
visibility = DecimalField(precision=2)
cloud_cover = DecimalField(precision=2)
pressure = DecimalField(precision=2)
ozone = DecimalField(precision=2)
create_time = DateTimeField(auto_now_on_insert=True)
@gen.coroutine
def create(self):
yield self.save()
你可以查一下。这个库帮助您定义可以很容易地从dict填充的对象(您可以很容易地将json转换为python dict)。它允许您在每个属性上定义验证规则。当某些属性丢失或格式错误时,对象将抛出
modelvalidateError
错误。Schematics允许您在定义模型时添加默认值和更多更好的内容。对于每个缺少的字段,您希望代码做什么?因为没有任何字段是必需的,所以在创建类记录时,我将不包括它们。该类由Mongoengine使用,Mongodb ODMIt可能有助于提供更多的代码。如果每个领域都不存在,你会为它做一些不同的事情吗?或者它是空的还是无?查看如何将json转换为类会很有帮助。您正在处理的不是json吗?字段(要保存的结果)是否像python字典一样分组在一起,还是有27个json文件?它们都分组在一个json文件中