Hay 2 dictos de parámetros:
fb_config = {
"page_likes" : {
"page_id": "1111",
"metric": "page_fans",
"since": "2019-01-01 00:00:00",
"until": "2019-01-01 00:00:00",
"date_preset" : "yesterday",
"period": "day"},
"page_impressions" : {"page_id": "1111",
"metric": "page_impressions",
"since": "yesterday",
"until": "yesterday",
"date_preset" : "yesterday",
"period": "day"},
"page_engaged_users" : {"page_id": "1111",
"metric": "page_engaged_users",
"since": "today",
"until": "today",
"date_preset" : "yesterday",
"period": "day"}}
Y
ga_config =
{
'view_id_123': {'view_id': '123',
'start_date': "2019-01-01 00:00:00",
'end_date': "2019-01-01 00:00:00",
'metrics': [{'expression': 'ga:sessions'}, {'expression':'ga:pageviews'}, {'expression':'ga:users'}, {'expression':'ga:bounces'},
{'expression':'ga:avgSessionDuration'}],
'dimensions': [{'name': 'ga:year'}, {'name': 'ga:userType'}, {'name': 'ga:sessionCount'}, {'name': 'ga:browser'},
{'name': 'ga:source'}]},
'view_id_456': {'view_id': '456',
'start_date': "today",
'end_date': "today",
'metrics': [{'expression': 'ga:bounces'}, {'expression':'ga:users'}],
'dimensions': [{'name': 'ga:mobileDeviceModel'}, {'name': 'ga:dataSource'}]},
'view_id_789': {'view_id': '789',
'start_date': "yesterday",
'end_date': "yesterday",
'metrics': [{'expression': 'ga:bounces'}, {'expression':'ga:users'}],
'dimensions': [{'name': 'ga:mobileDeviceModel'}, {'name': 'ga:dataSource'}]}
}
En el código no puedo mantener los parámetros y quiero extraerlos de un archivo json. Después de cargar el archivo, todas las fechas deben convertirse del formato str a datetime.
Este proceso se logra a través de varios bucles:
for values in params.values():
if 'since' in values:
if values['since'] == 'today':
values['since'] = datetime.now()
elif values['since'] == 'yesterday':
values['since'] = datetime.now() - timedelta(1)
else:
values['since'] = dt.datetime.strptime(values['since'], '%Y-%m-%d %H:%M:%S')
for values in params.values():
if 'until' in y:
if values['until'] == 'today':
values['until'] = datetime.now()
elif values['until'] == 'yesterday':
values['until'] = datetime.now() - timedelta(1)
else:
values['until'] = dt.datetime.strptime(y['until'], '%Y-%m-%d %H:%M:%S')
for values in params.values():
if 'start_date' in values:
if values['start_date'] == 'today':
values['start_date'] = datetime.now()
elif values['start_date'] == 'yesterday':
values['start_date'] = datetime.now() - timedelta(1)
else:
values['start_date'] = dt.datetime.strptime(values['start_date'], '%Y-%m-%d %H:%M:%S')
for values in params.values():
if 'end_date' in values:
if values['end_date'] == 'today':
values['end_date'] = datetime.now()
elif values['end_date'] == 'yesterday':
values['end_date'] = datetime.now() - timedelta(1)
else:
values['end_date'] = dt.datetime.strptime(values['end_date'], '%Y-%m-%d %H:%M:%S')
Pero el código es realmente feo y DRY es violado. ¿Hay mejores formas de iterar a través de dics anidados y cambiar los valores de ciertas claves?
4 respuestas
Esto es un poco más compacto:
for values in params.values():
for k in ('since','until','start_date','end_date'):
if k in values:
if values[k] == 'today':
values[k] = datetime.now()
elif values[k] == 'yesterday':
values[k] = datetime.now() - timedelta(1)
else:
values[k] = dt.datetime.strptime(values[k], '%Y-%m-%d %H:%M:%S')
Considere una comprensión de diccionario anidada y una función de mapeo dict para la conversión de tiempo:
def time_conversion(arg):
switcher = {
'today': datetime.now(),
'yesterday': datetime.now() - timedelta(1)
}
output = (datetime.strptime(arg, '%Y-%m-%d %H:%M:%S')
if arg not in switcher.keys() else switcher.get(arg))
return output
new_params = {outer_k:{inner_k: time_conversion(inner_v)
if inner_k in ('since', 'until', 'date_preset') else inner_v
for inner_k, inner_v in outer_v.items()}
for outer_k, outer_v in params.items()}
No soy un desarrollador de Python, pero puedo ver que está haciendo un bucle 4 veces sobre los mismos datos, cuando debe hacerlo solo una vez:
def formatDate(value, default):
if value == 'today':
date = datetime.now()
elif value == 'yesterday':
date = datetime.now() - timedelta(1)
else:
date = default
return date
def your_function():
for values in params.values():
if 'since' in values:
values['since'] = formatDate(values['since'], dt.datetime.strptime(values['since'], '%Y-%m-%d %H:%M:%S'))
if 'until' in values:
values['until'] = formatDate(values['until'], dt.datetime.strptime(y['until'], '%Y-%m-%d %H:%M:%S'))
if 'start_date' in values:
values['start_date'] = formatDate(values['start_date'], dt.datetime.strptime(values['start_date'], '%Y-%m-%d %H:%M:%S'))
if 'end_date' in values:
values['end_date'] = formatDate(values['end_date'], dt.datetime.strptime(values['end_date'], '%Y-%m-%d %H:%M:%S'))
Código no probado, pero extraería la lógica común a una función y solo tendría un bucle foreach.
En lugar de iterar sobre un dict anidado después de cargar json, debe usar el método object_hook de json.loads () para deserializar las fechas en la importación (supongo que está usando la biblioteca json incorporada para analizar json).
Esto ya ha sido respondido, por favor, eche un vistazo a este hilo: Cómo convertir a un objeto de fecha y hora de Python con JSON .loads?
Preguntas relacionadas
Preguntas vinculadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.