Leer y escribir ficheros CSV con python

De ChuWiki

El módulo csv de python nos permite leer y escribir ficheros CSV fácilmente. Veamos cómo usarlo. Tienes todo el código de ejemplo en python-csv

Leer ficheros CSV con python[editar]

Lo primero es importar el módulo csv. A partir de ahí, abrir el fichero para lectura de la forma habitual y simplemente ir leyendo líneas con csv.reader(). Veamos el código completo

import csv

if __name__ == '__main__':
    with open("username.csv", newline='') as csv_input_file:
        reader = csv.reader(csv_input_file, delimiter=";", quotechar=None)
        for row in reader:
                print(row)

Comentemos algunos detalles.

Al abrir el fichero, debemos poner la opción newline='' para evitar que el retorno de carro de cada línea forme parte de nuestros datos.

A la función csv.reader() le pasamos el fichero recién abierto y con parámetros podemos indicar cuales son los delimitadores. delimiter nos indica cual es el separador de los campos, habitualmente una coma o un punto y coma. También suele ser relativamente habitual el uso de tabulador como separador de campos. quotechar indica si los campos van con comillas de alguna forma. Habitualmente sin comillas, comillas simples o comillas dobles.

Sobre quotechar conviene comnetar algo más. Hay ficheros CSV que ponen todos los campos entre comillas. Otros ficheros CSV no ponen ningún campo entre comillas. Pero otros hacen mezclas extrañas. Por ejemplo, los de texto sí, pero los numéricos no. Y otro caso más adicional, no poner comillas salvo que el dato contenga el caracter separador de campo, como puede ser la coma o el punto y coma.

Para estos casos, existe el parámetro adicional quoting que le podríamos pasar. Los posibles valores de quoting son:

  • csv.QUOTE_ALL Todos los campos van con comillas.
  • csv.QUOTE_MINIMAL Solo llevan comillas aquellos campos que tienen el separador como parte del dato.
  • csv.QUOTE_NONNUMERIC Solo llevan comillas los campos que no son numéricos. Si ponemos esta opción, el reader nos devolverá números flotantes en estos casos en vez de textos string.
  • csv.QUOTE_NONE Ningún campo lleva comillas.

Una vez tenemos el reader, solo necesitamos un bucle para ir leyendo las líneas. reader nos devolverá una lista con los campos de cada línea. En el ejemplo anterior, si pasamos el fichero username.csv, tendremos la siguiente salida

['Username', ' Identifier', 'First name', 'Last name']
['booker12', '9012', 'Rachel', 'Booker']
['grey07', '2070', 'Laura', 'Grey']
['johnson81', '4081', 'Craig', 'Johnson']
['jenkins46', '9346', 'Mary', 'Jenkins']
['smith79', '5079', 'Jamie', 'Smith']

Escribir ficheros CSV con python[editar]

La escritura es similar. El fichero se debe abrir de escritura en vez de lectura. En vez de cvs.reader() debemos usar cvs.writer() para obtener el writer y usar writer.writerow() para ir escribiendo las filas CSV en el fichero. Veamos código de ejemplo

with open("output.csv", "w", newline='') as csv_output_file:
    writer = csv.writer(csv_output_file, delimiter=",", quotechar="'", quoting=csv.QUOTE_ALL)
    writer.writerow(["header1", "header2", "header3"])
    writer.writerow(["data_1_1", "data_1_2", "data_1_3"])
    writer.writerow(["data_2_1", "data_2_2", "data_2_3"])
    writer.writerow(["data_3_1", "data_3_2", "data_3_3"])

El ejemplo es simple. Abrimos el fichero para escritura. Un datalle, indicamos que no queremos que se añadan newline, porque write.writerow() ya las añade. Si no ponemos esta opción, tendríamos doble nueva línea en cada fila. Obtenemos el writer con csv.writer() indicando como parámetros qué separdores y comillas queremos, así como cuando poner comillas según explicamos en quoting

Y ya solo queda ir escribiendo datos en el fichero, usando writer.writerow(). Pasamos como parámetro una lista con lo que queramos que se escriba en el fichero.

La salida de este programa será un fichero "output.csv" cuyo contenido es

'header1','header2','header3'
'data_1_1','data_1_2','data_1_3'
'data_2_1','data_2_2','data_2_3'
'data_3_1','data_3_2','data_3_3'

Leer y escribir fichero CSV con cabecera en python[editar]

Lo que hemos hecho hasta ahora no contempla la cabecera del fichero CSV, si la hay, de ninguna forma espacial. No deja de ser una fila más del fichero CSV. Sin embargo, el módulo csv de python tiene las clases csv.Dictreader y csv.Dicwriter que tratan cada fila del CSV como un dict de python. Las key serían los textos de la cabecera y los value los datos de la fila CSV. Veamos un ejemplo tanto de lectura como de escritura

with open("username.csv", newline='') as csv_file:
    dict_reader = csv.DictReader(csv_file, delimiter=";")
    for row in dict_reader:
        print(row)

El mecanismo es muy similar al que usamos para leer anteriormente el fichero CSV, pero esta vez, cada fila, en vez de una lista, será un dict como hemos comentado. La salida de este programa sería la siguiente

{'Username': 'booker12', ' Identifier': '9012', 'First name': 'Rachel', 'Last name': 'Booker'}
{'Username': 'grey07', ' Identifier': '2070', 'First name': 'Laura', 'Last name': 'Grey'}
{'Username': 'johnson81', ' Identifier': '4081', 'First name': 'Craig', 'Last name': 'Johnson'}
{'Username': 'jenkins46', ' Identifier': '9346', 'First name': 'Mary', 'Last name': 'Jenkins'}
{'Username': 'smith79', ' Identifier': '5079', 'First name': 'Jamie', 'Last name': 'Smith'}

Vemos que es un dict donde las cabeceras del fichero se usan como key. Es decir, tenemos "Username", "Identifier", "First name" y "Last Name" como keys. Esto nos facilita el tratamiento de los datos. En el primer ejemplo de lectura para acceder al "Username" usaríamos row[0]. Al leerlo como dict, podemos usar row["Username"] que es más amigable a la hora de leer código.

Para la escritura, debemos indicar cual es la cabecera y luego ir escribiendo filas pasando un dict cada vez. El código sería el siguiente

with open("output.csv", "w", newline='') as csv_outuput_file:
    header = ["column1", "column2", "column3"]
    dict_writer = csv.DictWriter(csv_outuput_file, header, delimiter=",", quotechar="'", quoting=csv.QUOTE_ALL)
    dict_writer.writeheader()
    dict_writer.writerow({"column1": "data_1_1"})
    dict_writer.writerow({"column1": "data_2_1", "column2": "data_2_2", "column3": "data_2_3"})

El fichero de escritura se abre de la forma habitual. Definimos una lista con la cabecera header. Obtenemos el csv.Docwriter(). Los parámetros a pasar son el fichero de salida, la cabecera que acabamos de crear y la paramétrica que indica el separador que queremos usar y el entrecomillado. Luego con dict_writer.writeheader() se escribe la cabecera en el fichero y con dict_writer.writerow() se escriben las filas.

Fíjate que el parámetro de dict_writer.writerow() en a su vez un dict con los textos de cabecera como key y los valores que queramos. Tenemos la opción de no poner todas lso valores en cada fila, ya que al indicar la cabecera, csv.Dictwriter sabe dónde va cada dato. La salida de este programa es

'column1','column2','column3'
'data_1_1','',''
'data_2_1','data_2_2','data_2_3'

Fíjate en la primera fila de datos que se han rellenado en blanco los dos campos que faltaban en código.

csv.Dialect[editar]

Hasta ahora hemos ido indicando los separadores y entrecomillados usando los parámetros delimiter, quotechar y quoting. Sin embargo, suelen ser siempre los mismos y cada sistema operativo/aplicación puede tener preferencia por algo concreto. Aunque como comentamos, suele haber pocas variantse: comas, punto y comas o tabuldadores. Comillas simples, dobles o nada en absoluto.

El módulo csv permite que en vez de los parámetros uno a uno pasemos un parámetro dialect con una instancia de csv.Dialect que tiene dentro todos estos parámetros ya definidos. Y python tiene unos cuantos Dialect ya preparados. El siguiente código nos muestra los nombres de los disponibles y luego saca los detalles de cada uno de ellos

print(csv.list_dialects())
for dialect_name in csv.list_dialects():
    dialect = csv.get_dialect(dialect_name)
    print(dialect_name+" "+dialect.delimiter+" "+dialect.quotechar+" "+str(dialect.quoting)+" ")

El primera línea saca los nombres (como texto) de cada Dialect disponible. El bucle posterior los va obteniendo todos con csv.get_dialect() y saca por pantalla nombre y parámetros más importantes. La salia de este programa es

['excel', 'excel-tab', 'unix']
excel , " 0 
excel-tab 	 " 0 
unix , " 1 

Vemos que hay

  • "excel" con separador coma, comillas dobles y quoting valor 0, equivalente a csv.QUOTE_MINIMAL
  • "excel-tab" como el anteiror, pero el separador es un tabulador en vez de uan coma.
  • "unix" con separador coma, comillas dobles y quoting a 1, equivalente a csv.QUOTE_ALL.

Los valores de quoting son los siguientes

    print(csv.QUOTE_MINIMAL)      # 0
    print(csv.QUOTE_ALL)          # 1
    print(csv.QUOTE_NONNUMERIC)   # 2
    print(csv.QUOTE_NONE)         # 3

Así que si tenemos claro el Dialect, podemos pasarlo sin más en los ejemplos anteriores como dialect='unix' en los reader, writer, etc. Debemos hacerlo pon nombre. Si queremos crear nuestros propios Dialect, debemos registrarlos con un nombre con csv.register_dialect() de la siguiente forma

    csv.register_dialect("my_dialect", delimiter=",", quotechar="'", quoting=csv.QUOTE_ALL)
    my_dialect = csv.get_dialect("my_dialect")
    print("my_dialect " + my_dialect.delimiter + " " + my_dialect.quotechar + " " + str(my_dialect.quoting) + " ")

Vemos que una vez registrado, podemos obtenerlo con csv.get_dialect(). Podríamos usarlo en los métodos de reader, writer, etc por su nombre con dialect="my_dialect"