El módulo fileinput consta de una clase y varias funciones que permiten procesar datos procedentes de varios archivos, incluidos como elementos de una lista o como argumentos de un script. Esta característica es idónea para leer y procesar todas las líneas de un conjunto de archivos como si se tratara de uno solo.
También, el módulo permite procesar múltiples líneas de datos introducidas en la entrada estándar; reescribir archivos modificando el contenido original y obtener los datos directamente de archivos comprimidos.
A continuación, varios ejemplos para mostrar algunas aplicaciones del módulo. Los ejemplos utilizan tres archivos de texto con el siguiente contenido:
También, el módulo permite procesar múltiples líneas de datos introducidas en la entrada estándar; reescribir archivos modificando el contenido original y obtener los datos directamente de archivos comprimidos.
A continuación, varios ejemplos para mostrar algunas aplicaciones del módulo. Los ejemplos utilizan tres archivos de texto con el siguiente contenido:
Título;Dirección;País El clan;Pablo Trapero;Argentina Papeles en el Viento;Juan Taratuto;Argentina El club;Pablo Larraín;Chile El botón de nácar;Patricio Guzmán;Chile |
cine2.txt
Título;Dirección;País Gente de bien;Franco Lolli;Colombia Los hongos;Oscar Ruiz Navia;Colombia Manos sucias;Josef Kubota Wladyka;Colombia Amama;Asier Altuna;España Un día perfecto;Fernando León de Aranoa;España El desconocido;Dani de la Torre;España |
cine3.txt
Título;Dirección;País 600 millas;Gabriel Ripstein;México Archivo 253;Abe Rosenberg;México El cumple de la abuela;Javier Colinas;México Lo que lleva el río;Mario Crespo;Venezuela |
Procesar lista de archivos con fileinput.input()
En el primer ejemplo con la función fileinput.input() se recorren los tres archivos de una lista y se muestran todas sus líneas en la salida estándar (normalmente, la pantalla). También, se antepone el número de línea leída obtenido con la función fileinput.lineno().
fileinput.input(files=None, mode='r')
Por defecto, el modo de apertura de los archivos es 'r', que permite la lectura de los archivos de tipo texto. Sólo en ese caso el argumento mode puede omitirse. En otro caso, para que sea posible la lectura de los archivos binarios, es necesario establecer mode con el valor 'rb'.
fileinput.input(files=None, mode='r')
Por defecto, el modo de apertura de los archivos es 'r', que permite la lectura de los archivos de tipo texto. Sólo en ese caso el argumento mode puede omitirse. En otro caso, para que sea posible la lectura de los archivos binarios, es necesario establecer mode con el valor 'rb'.
#!/usr/bin/env python # -*- coding: utf-8 -*- # import fileinput import sys, glob cines = ["cine1.txt", "cine2.txt", "cine3.txt"] for linea in fileinput.input(cines): ln = str(fileinput.lineno()) sys.stdout.write(ln + " -> " + linea) ''' Salida: 1 -> Título;Dirección;País 2 -> El clan;Pablo Trapero;Argentina 3 -> Papeles en el Viento;Juan Taratuto;Argentina 4 -> El club;Pablo Larraín;Chile 5 -> El botón de nácar;Patricio Guzmán;Chile 6 -> Título;Dirección;País 7 -> Gente de bien;Franco Lolli;Colombia 8 -> Los hongos;Oscar Ruiz Navia;Colombia 9 -> Manos sucias;Josef Kubota Wladyka;Colombia 10 -> Amama;Asier Altuna;España 11 -> Un día perfecto;Fernando León de Aranoa;España 12 -> El desconocido;Dani de la Torre;España 13 -> Título;Dirección;País 14 -> 600 millas;Gabriel Ripstein;México 15 -> Archivo 253;Abe Rosenberg;México 16 -> El cumple de la abuela;Javier Colinas;México 17 -> Lo que lleva el río;Mario Crespo;Venezuela '''
Los archivos anteriores tienen en su primera línea una cabecera que describe el contenido de los mismos: Título;Dirección;País. Si sólo interesan los datos y se quiere omitir esta línea:
for linea in fileinput.input(cines): if not fileinput.isfirstline(): sys.stdout.write(linea) ''' Salida: El clan;Pablo Trapero;Argentina Papeles en el Viento;Juan Taratuto;Argentina El club;Pablo Larraín;Chile El botón de nácar;Patricio Guzmán;Chile Gente de bien;Franco Lolli;Colombia Los hongos;Oscar Ruiz Navia;Colombia Manos sucias;Josef Kubota Wladyka;Colombia Amama;Asier Altuna;España Un día perfecto;Fernando León de Aranoa;España El desconocido;Dani de la Torre;España 600 millas;Gabriel Ripstein;México Archivo 253;Abe Rosenberg;México El cumple de la abuela;Javier Colinas;México Lo que lleva el río;Mario Crespo;Venezuela '''
Procesar con funciones que ayudan a controlar el flujo
Cuando se utilice la función fileinput.input(), que está basada en la clase fileinput.FileInput(), se podrán utilizar varias funciones que devuelven información que se puede usar para controlar el proceso. También, el módulo incluye una función para pasar, en cualquier momento, de un archivo al siguiente y, otra, para forzar la finalización del proceso:
En el siguiente ejemplo se utilizan algunas funciones para obtener información de los archivos y para controlar el proceso. El resultado muestra la información obtenida y la segunda línea de cada archivo (primera línea de datos), excepto del tercer archivo:
- fileinput.filename(): Devuelve nombre del archivo que se está leyendo en un momento dado. Antes de leer la primera línea devuelve None.
- fileinput.fileno(): Devuelve número (descriptor) de archivo. Antes de leer la primera línea y con el proceso entre dos archivos devuelve -1.
- fileinput.lineno(): Devuelve número de línea leída del total de líneas de todos los archivos. Antes de leer la primera línea devuelve 0 y después de la última línea, devuelve el número de dicha línea.
- fileinput.filelineno(): Devuelve el número de línea leída del archivo actual. Antes de leer la primera línea devuelve 0 y después de la última línea leída de un archivo, devuelve el número de dicha línea.
- fileinput.isfirstline(): Devuelve True si la línea leída es la primera y False si no lo es.
- fileinput.isstdin(): Devuelve True si la última línea se ha leído desde la entrada estándar (sys.stdin), de lo contrario devuelve False.
- fileinput.nextfile(): Cierra el archivo actual y salta al siguiente archivo si fuera posible. No se puede utilizar para omitir el primer archivo.
- fileinput.close(): Finaliza el proceso
En el siguiente ejemplo se utilizan algunas funciones para obtener información de los archivos y para controlar el proceso. El resultado muestra la información obtenida y la segunda línea de cada archivo (primera línea de datos), excepto del tercer archivo:
for linea in fileinput.input(cines): if not fileinput.isfirstline(): ar = fileinput.filename() an = str(fileinput.fileno()) al = str(fileinput.filelineno()) nl = str(fileinput.lineno()) linea = linea.rstrip() print(ar, an, al, nl, linea) fileinput.nextfile() if fileinput.filename()== 'cine3.txt': fileinput.close() ''' Salida: cine1.txt 3 2 2 El clan;Pablo Trapero;Argentina cine2.txt 3 2 4 Gente de bien;Franco Lolli;Colombia '''
Procesar lista de archivos obtenida con glob.glob()
Cuando los nombres de archivos siguen un patrón es posible utilizar el módulo glob para obtener del directorio la lista de archivos, como en el siguiente ejemplo. Además, en este caso se utiliza la función split() para dividir cada línea en tres partes equivalentes a sus datos para poder filtrar la información (en este ejemplos se muestran las líneas de las películas de "Colombia"):
archivos = glob.glob("cine*.txt") archivos.sort() for linea in fileinput.input(archivos): if not fileinput.isfirstline(): linea = linea.rstrip() pais = linea.split(";") if pais[2] == "Colombia": print(linea) ''' Salida: Gente de bien;Franco Lolli;Colombia Los hongos;Oscar Ruiz Navia;Colombia Manos sucias;Josef Kubota Wladyka;Colombia '''
Procesar archivos incluidos como argumentos de un script
Asimismo, los nombres de los archivos a procesar se pueden incluir como argumentos de un script Python.
#!/usr/bin/env python # -*- coding: utf-8 -*- # # script: peliculas.py import fileinput, sys cines = sys.argv[1:] print("Archivos:", cines) for linea in fileinput.input(cines): if not fileinput.isfirstline(): sys.stdout.write(linea) ''' Salida: Archivos: ['cine1.txt', 'cine2.txt', 'cine3.txt'] El clan;Pablo Trapero;Argentina Papeles en el Viento;Juan Taratuto;Argentina El club;Pablo Larraín;Chile El botón de nácar;Patricio Guzmán;Chile Gente de bien;Franco Lolli;Colombia Los hongos;Oscar Ruiz Navia;Colombia Manos sucias;Josef Kubota Wladyka;Colombia Amama;Asier Altuna;España Un día perfecto;Fernando León de Aranoa;España El desconocido;Dani de la Torre;España 600 millas;Gabriel Ripstein;México Archivo 253;Abe Rosenberg;México El cumple de la abuela;Javier Colinas;México Lo que lleva el río;Mario Crespo;Venezuela '''
Para ejecutar el script "peliculas.py" desde la línea de comandos:
$ python peliculas.py cine1.txt cine2.txt cine3.txt
$ python peliculas.py cine1.txt cine2.txt cine3.txt
Procesar múltiples líneas de la entrada estándar (stdin)
Como se comentó al comienzo la función fileinput.input() puede procesar múltiples líneas de datos introducidas en la entrada estándar.
Con el siguiente ejemplo se pueden introducir varias líneas utilizando la entrada estándar (teclado, normalmente). Cada vez que se complete una línea presionar la tecla [Return] para avanzar a la siguiente. Para finalizar la entrada presionar [Ctrl+D]. Después, de todas las líneas introducidas sólo se mostrarán las tres primeras. Cuando se alcance la número tres terminará el proceso.
Con el siguiente ejemplo se pueden introducir varias líneas utilizando la entrada estándar (teclado, normalmente). Cada vez que se complete una línea presionar la tecla [Return] para avanzar a la siguiente. Para finalizar la entrada presionar [Ctrl+D]. Después, de todas las líneas introducidas sólo se mostrarán las tres primeras. Cuando se alcance la número tres terminará el proceso.
print("Introducir varias líneas de texto (Finalizar - CTRL+D):") for linea in fileinput.input(): print(linea.rstrip()) if fileinput.lineno() == 3: fileinput.close()
Procesar lista de archivos con la sentencia with
La función fileinput.input() también se puede utilizar con la sentencia with:
with fileinput.input(["cine1.txt", "cine2.txt"]) as archivo: for linea in archivo: if not fileinput.isfirstline(): sys.stdout.write(linea) ''' Salida: El clan;Pablo Trapero;Argentina Papeles en el Viento;Juan Taratuto;Argentina El club;Pablo Larraín;Chile El botón de nácar;Patricio Guzmán;Chile Gente de bien;Franco Lolli;Colombia Los hongos;Oscar Ruiz Navia;Colombia Manos sucias;Josef Kubota Wladyka;Colombia Amama;Asier Altuna;España Un día perfecto;Fernando León de Aranoa;España El desconocido;Dani de la Torre;España '''
Procesar reescribiendo lista de archivos en la salida estándar
El argumento inplace (in situ) de la función fileinput.input() con el valor True permite reescribir los archivos de entrada utilizando la salida estándar. El contenido previo de cada archivo se puede salvar asignando la extensión de los archivos de respaldo al argumento backup.
fileinput.input(files=None, inplace=False, backup='', mode='r')
En el ejemplo que sigue se van se utilizan dos archivos nuevos de texto que contienen datos de varias salas de cine, tanto el nombre de la sala como el aforo que tiene. En el proceso se utiliza la función fileinput.lineno() para obtener el número de línea. Luego, se utiliza print() para anteponer dicho número a cada línea; que en lugar de ser mostrada en la salida estándar (pantalla) será redirigida al archivo original modificando su contenido, que previamente es salvado en otro archivo con la extensión .bck:
fileinput.input(files=None, inplace=False, backup='', mode='r')
En el ejemplo que sigue se van se utilizan dos archivos nuevos de texto que contienen datos de varias salas de cine, tanto el nombre de la sala como el aforo que tiene. En el proceso se utiliza la función fileinput.lineno() para obtener el número de línea. Luego, se utiliza print() para anteponer dicho número a cada línea; que en lugar de ser mostrada en la salida estándar (pantalla) será redirigida al archivo original modificando su contenido, que previamente es salvado en otro archivo con la extensión .bck:
Cinema Paradise (300) Cines Nervión (400) |
sala2.txt
Cine Apolo (260) Corona Center (180) Cine Bécquer (300) |
for linea in fileinput.input(["sala1.txt", "sala2.txt"], inplace=True, backup='.bck'): nl = str(fileinput.lineno()) linea = nl + ": " + linea.rstrip('\n') print(linea) ''' Salida sala1.txt: 1: Cinema Paradise (300) 2: Cines Nervión (400) Salida sala2.txt: 3: Cine Apolo (260) 4: Corona Center (180) 5: Cine Bécquer (300) Los contenidos originales se salvan en los archivos sala1.txt.bck y sala2.txt.bck '''
La clase fileinput.FileInput()
La clase fileinput.FileInput() permite crear objetos FileInput y sus métodos tienen los mismos nombres y funcionalidades que las funciones utilizadas con fileinput.input(). Además, cuenta con el método readline() que devuelve la siguiente línea leída en la entrada y el método __getitem__().
class fileinput.FileInput(files=None, inplace=False, backup='', mode='r', openhook=None)
En relación al argumento openhook (también disponible en fileinput.input()) comentar que permite controlar la forma de abrir los archivos. Para ello, se puede asignar una función a medida con dos argumentos (el nombre del archivo y su modo de apertura) que devuelva un objeto de tipo fichero abierto. Por otra parte, el módulo incorpora de fábrica la función fileinput.hook_encoded() para abrir los archivos utilizando una codificación determinada y la función fileinput.hook_compressed() para abrir archivos comprimidos.
Para finalizar, varios ejemplos que utilizan objetos de la clase fileinput.FileInput().
class fileinput.FileInput(files=None, inplace=False, backup='', mode='r', openhook=None)
En relación al argumento openhook (también disponible en fileinput.input()) comentar que permite controlar la forma de abrir los archivos. Para ello, se puede asignar una función a medida con dos argumentos (el nombre del archivo y su modo de apertura) que devuelva un objeto de tipo fichero abierto. Por otra parte, el módulo incorpora de fábrica la función fileinput.hook_encoded() para abrir los archivos utilizando una codificación determinada y la función fileinput.hook_compressed() para abrir archivos comprimidos.
Para finalizar, varios ejemplos que utilizan objetos de la clase fileinput.FileInput().
Procesar lista de archivos con la clase FileInput()
En el siguiente ejemplo se crea un objeto FileInput a partir de una lista de archivos y se muestra el contenido numerando las líneas:
cines = ["cine1.txt", "cine2.txt", "cine3.txt"] contador = 0 objfi = fileinput.FileInput(cines) for linea in objfi: if not objfi.isfirstline(): contador += 1 sys.stdout.write(str(contador) + ": " + linea)
Procesar lista de archivos con la clase FileInput() y readline()
Crea un objeto FileInput y después utiliza el método readline() para leer las líneas de los archivos de entrada:
objfi=fileinput.FileInput(["cine1.txt", "cine2.txt"]) while True: linea=objfi.readline() if not linea: break if not objfi.isfirstline(): sys.stdout.write(linea)
Procesar archivos con clase FileInput() con una codificación específica
Crea un objeto FileInput abriendo los archivos con la codificación "utf-8" mediante la función fileinput.hook_encoded
print() objfi = fileinput.FileInput(["sala1.txt"], openhook=fileinput.hook_encoded("utf-8")) for linea in objfi: sys.stdout.write(linea)
Procesar archivo comprimido con clase FileInput()
Crea un objeto FileInput obteniendo los archivos "sala1.txt" y "sala2.txt" del archivo comprimido "salacines.gz", mediante la función fileinput.hook_compressed. Las líneas de los archivos son devueltas en binario pero son convertidas a cadenas de texto con la función decode():
objfi = fileinput.FileInput(["salacines.gz"], openhook=fileinput.hook_compressed) for linea in objfi: sys.stdout.write(linea.decode("utf-8"))
Para crear un archivo comprimido .gz en GNU/Linux con los dos archivos que contienen los datos de las salas, ejecutar desde la consola los siguientes comandos:
$ gzip -c sala1.txt > salacines.gz
$ gzip -c sala2.txt >> salacines.gz
$ gzip -c sala1.txt > salacines.gz
$ gzip -c sala2.txt >> salacines.gz
Relacionado:
Ir al índice del tutorial de Python