Wiki Python para dados
CSV e JSON com a biblioteca padrão
Ler CSV com aspas e vírgula no meio, converter tipos com cuidado e achatar JSON aninhado, sem dependência nenhuma.
CSV parece trivial até a primeira vírgula dentro de um campo. Nunca separe com split(","): use o módulo csv, que segue as regras de aspas.
import csv
import io
texto = 'id,nome,valor\n1,"Silva, Ana",230.50\n2,Bruno,\n'
for linha in csv.DictReader(io.StringIO(texto)):
print(linha)Saída (conferida)
{'id': '1', 'nome': 'Silva, Ana', 'valor': '230.50'}
{'id': '2', 'nome': 'Bruno', 'valor': ''}Tudo chega como texto, e o campo vazio é '', não None. A conversão de tipo é trabalho seu, e é onde mora a decisão de qualidade: o que fazer com o vazio?
def para_numero(texto):
texto = texto.strip()
if not texto:
return None
if "," in texto:
texto = texto.replace(".", "").replace(",", ".")
return float(texto)
print([para_numero(x) for x in ["230.50", "1.234,56", "", " 7 "]])Saída (conferida)
[230.5, 1234.56, None, 7.0]
JSON aninhado
json.loads devolve dicionários e listas. Achatar um registro aninhado é o que um select("cliente.cidade") faz no Spark.
import json
bruto = '{"id": 7, "cliente": {"nome": "Ana", "cidade": null}, "itens": [{"sku": "A1", "qtd": 2}, {"sku": "B2", "qtd": 1}]}'
r = json.loads(bruto)
plano = {"id": r["id"], "cliente_nome": r["cliente"]["nome"], "cidade": r["cliente"]["cidade"],
"qtd_total": sum(i["qtd"] for i in r["itens"])}
print(plano)
print(json.dumps({"cidade": "São Paulo"}), json.dumps({"cidade": "São Paulo"}, ensure_ascii=False))Saída (conferida)
{'id': 7, 'cliente_nome': 'Ana', 'cidade': None, 'qtd_total': 3}
{"cidade": "S\u00e3o Paulo"} {"cidade": "São Paulo"}nullviraNone,trueviraTrue; número sem ponto viraint.ensure_ascii=Falsegrava "São Paulo" como texto; o padrão escapa os acentos.
Fontes
Conhecimento compartilhado pela Genesis Innovation.