Bibliotecas para manejo avanzado de archivos en GNU/Linux
Cita con formato IEEE:
E. Bahit, "Bibliotecas para manejo avanzado de archivos en
GNU/Linux", in
Python Aplicado, 4th ed., EBRC Publisher, 2022, pp.
140-145.
Cita con formato APA 7:
Bahit, E. (2022). Bibliotecas para manejo avanzado de archivos
en GNU/Linux. In
Python Aplicado (4th ed., pp. 140-145). EBRC Publisher.
Cita en línea:
(Bahit, 2022)
En este capítulo:
- Aprende a comprimir y descomprimir archivos con Python
- Aprende a crear archivos temporales con Python
- Aprende a buscar archivos con Python
Compresión y descompresión de archivos con ltarfile y zipfile
La biblioteca tarfile
puede utilizarse para leer,
comprimir y descomprimir archivos .tar, .tar.gz. tar.bz2 y tar.xz,
mientras que la biblioteca zipfile
se utiliza para los
archivos .zip
La biblioteca tarfile
Bien sea para leer un archivo comprimido, o bien para comprimir o
descomprimir, un objeto TarFile
, se crea mediante la
función open
del módulo. A diferencia de una apertura
estándar, los modos lectura y escritura, se acompañan del formato
deseado, mediante la sintaxis <modo>:<formato>
,
donde <modo>
puede ser
r
(lectura) o w
(escritura), y
<formto>
,
gz
(gzip), bz2
(bzip2) o, solo en Python 3, xz
(lzma).
Modo de apertura | Comando tar |
---|---|
[r|w]:gz | tar -[c|x]z |
[r|w]:bz2 | tar -[c|x]j |
[r|w]:xz | tar -[c|x]J |
El formato lzma (xz) solo está disponible a partir de la rama 3 del lenguaje |
Descomprimir archivos
from tarfile import open as tar_open with tar_open("origen.tar.bz2", "r:bz2") as tar: tar.extractall('carpeta/destino')
Comprimir archivos
from tarfile import open as tar_open with tar_open("carpeta/destino.tar.gz", "w:gz") as tar: tar.add('foo.txt') tar.add('bar.txt') tar.add('baz.txt')
Observaciones generales sobre el código:
Se utiliza un alias para que el métodoopen
de la bibliotecatarfile
, no sobrescriba la función incorporadaopen
. Se emplea la estructurawith
, para no utilizar el métodoclose
.
Observaciones de seguridad:
No deben descomprimirse archivos sin verificar el nombre de los mismos. Un nombre de archivo, podría contener una/
o..
, que provocarían que los archivos se almacenasen en un directorio no esperado.
Observaciones de compatibilidad entre versiones:
El formato lzma solo está disponible en la rama 3 del lenguaje. Para que un script o herramienta sea compatible con ambas versiones, la única opción es utilizar los formatos gzip o bzip2.
La biblioteca zipfile
La extracción y compresión de archivos zip se realiza de la siguiente forma:
from zipfile import ZipFile # Escritura de archivos zip with ZipFile('carpeta/destino.zip', 'w') as z: z.write('foo.txt') z.write('bar.txt') z.write('baz.txt') # Lectura de archivos zip with ZipFile('carpeta/origen.zip', 'r') as z: z.extractall('carpeta/destino', pwd='clave') # el parámetro pwd (contraseña) es opcional
Para los archivos zip, aplican las mismas observaciones de seguridad que para los archivos tar.
Manejo de archivos temporales con la biblioteca tempfile
Cuando sea necesario que un script, guarde temporalmente
archivos, no es una buena práctica que el mismo script los
guarde y luego los elimine, ni que intente escribir directamente en el
directorio /tmp
. Para este caso, se debe emplear la
biblioteca tempfile
.
Lectoescritura de archivos temporales
Cuando se crean objetos de archivos temporales mediante la clase
TemporaryFile
del módulo tempfile
, los mismos
se crean y destruyen en tiempo de ejecución. La destrucción se lleva a
cabo al cerrar el archivo. Esto implica que si se trabaja con la
estructura with
, al finalizar dicha estructura, el archivo
se habrá eliminado.
from tempfile import TemporaryFile with TemporaryFile() as tmp: # aquí el archivo existe # Aquí el archivo ya no existe
Todo archivo temporal escrito, para ser escrito, requiere que el contenido se pase como un objeto tipo bytes (y no una cadena). Este requerimiento es exigencia de Python 3, sin embargo, en Python 2 está perfectamente soportado. Para que una cadena sea convertida a bytes, basta con especificar su tipo:
from tempfile import TemporaryFile with TemporaryFile() as tmp: tmp.write(b"Cadena de texto que será pasada a bytes")
Finalmente, se debe tener en cuenta que una vez escrito, el cursor estará al final del archivo, por lo que si se lo quiere leer, retornará una cadena nula. Por lo tanto, habrá que mover el cursor al byte 0 a fin de poder leerlo:
from tempfile import TemporaryFile with TemporaryFile() as tmp: tmp.write(b"Cadena de texto que será pasada a bytes") # … acciones intermedias tmp.seek(0) # Se mueve el cursor al byte 0 contenido = tmp.read()
Observaciones importantes: es necesario
aclarar que los archivos temporales creados con, no son archivos
persistentes en memoria, sino en disco. De hecho, se almacenan en el
directorio temporal del sistema, independientemente de la plataforma. Es
posible conocer este directorio invocando a la función
gettempdir()
:
from tempfile import TemporaryFile, gettempdir with TemporaryFile() as tmp: tmp.write(b"Cadena de texto") tmp_dir = gettempdir()
Búsqueda de archivos con las bibliotecas glob y fnmatch
Estas bibliotecas permiten buscar archivos que coincidan con un
patrón, con el mismo estilo empleado en sistemas *nix. Mientras
que el módulo glob
busca archivos que coincidan con un
patrón, fnmatch
verifica si un patrón coincide con
el nombre de un archivo.
Símbolos interpretados
Símbolo | Significado |
---|---|
* | Cualquier coincidencia |
? | Coincidencia con un único carácter |
[secuencia] | Coincidencia con cualquier carácter de la secuencia |
[!secuencia] | Coincidencia con cualquier carácter, excepto los de la secuencia |
Uso de glob
>>> from glob import glob >>> glob('*.txt') ['foo.txt', 'baz.txt', 'bar.txt'] >>> glob('*[!of].txt') ['baz.txt', 'bar.txt']
Uso de fnmatch con os.listdir
>>> from os import listdir >>> from fnmatch import fnmatch >>> for archivo in listdir('.'): ... archivo, fnmatch(archivo, '*[!0-9].txt') ... ('3.r', False) ('foo.gif', False) ('.bar', False) ('carpeta', False) ('foo.txt', True) ('baz.txt', True) ('origen.tar.xz', False) ('.foo', False) ('2.r', False) ('bar.txt', True) ('.baz', False) ('origen.tar.bz2', False) ('a.r', False) ('1.r', False) ('origen.tar.gz', False)