Herramientas de usuario

Herramientas del sitio


python:archivos

¡Esta es una revisión vieja del documento!


Conceptos básicos de archivos y directorios

Definición de direcciones de archivo o directorio

Un archivo tiene habitualmente dos key properties: un nombre de archivo o filename, y un directorio o path donde se encuentra.

La estructura de archivos y directorios es diferente en distintos Sistemas Operativos, debemos conocer cómo se organiza en el que estamos trabajando.

Además, el símbolo para separar directorios y subdirectorios, también cambia entre Windows (\) y Linux o Mac (/).
Para que nuestro programa funcione en cualquier Sistema Operativo, podemos usar la función Path() de la biblioteca pathlib.

Path() devuelve un objeto de tipo Path, que al pasarlo a string, devolverá la cadena en función del Sistema Operativo en el que se esté ejecutando el programa. Al definir direcciones en el programa (usando Path), se usa / por convención, ya que entre los desarrolladores, suele ser linux el Sistema Operativo preferente.

from pathlib import Path
myFiles = ['accounts.txt', 'details.csv', 'invite.docx']
for filename in myFiles:
    print(Path(r'C:/Users/Al', filename))  # Con Path() se pueden concatenar cadenas que definan el directorio. 
 
# C:\Users\Al\accounts.txt
# C:\Users\Al\details.csv
# C:\Users\Al\invite.docx

La biblioteca pathlib fue introducida en Python 3.4, reemplazando al viejo os.path de versiones anteriores.

Concatenar directorios con /

Del mismo modo que se pueden concatenar strings con el símbolo +, se pueden concatenar paths con el símbolo /.

from pathlib import Path
homeFolder = Path('C:/Users/Al')
subFolder = Path('spam')
homeFolder / subFolder       # WindowsPath('C:/Users/Al/spam') # Objeto tipo Path
str(homeFolder / subFolder)  # 'C:\\Users\\Al\\spam' # Hay dobles backlashes, ya que estamos en Windows y el primer \ es el carácter de escape

Sólo hay que tener en cuenta al unir paths con /, es que uno de los dos primeros valores que se pasan deben ser de tipo Path. Si son strings, por ejemplo, se produce un error TypeError.

El operador / reemplaza al viejo os.path.join() de versiones de Python anteriores.

Direcciones absolutas y relativas

Hay dos formas de especificar un directorio:

  • Dirección absoluta: Comienza en el directorio raíz.
  • Dirección relativa: Comienza en el directorio de trabajo.

Además se puede indicar:

  • ./ Se indica “Este directorio” o directorio “en el que nos encontramos”, el directorio de trabajo.
  • ../ Se indica el directorio “padre”

Directorio de trabajo y directorio de usuario

El directorio de trabajo es el directorio desde el que estamos trabajando, también denominado Current Working Directory o cwd.

  • Comprobar diectorio de trabajo: Path.cwd().
  • Cambiar el directorio de trabajo: os.chdir().

El directorio de usuario depende del Sistema Operativo, y es donde se guarda la información del usuario. Se recomienda usar este directorio para poner nuestros programas, ya que así nos aseguramos de tener todos los permisos necesarios.

Creación y manejo de directorios

Creación de directorios

Se pueden crear directorios, así como los directorios intermedios definifos si no existen, con la función os.makedirs(). Se pasa como argumento un string con la dirección completa.

También pueden crearse directorios con el método de Path, mkdir():

from pathlib import Path
Path(r'C:\Users\Al\spam').mkdir() # mkdir() no crea directorios intermedios, para eso usar os.makedirs()

Trabajar con direcciones absolutas y relativas

El módulo (biblioteca) pathlib proporciona los siguientes métodos para comprobar si un path es absoluto o relativo:

  • is_absolute() True si es absoluto.
  • Path.cwd() / Path('my/relative/path') Creación de una dirección absoluta a partir de una relativa.
  • Path.home() / Path('my/relative/path') Creación decuna dirección absoluta a partir de una relativa, tomando como base el diectorio de trabajo.

Otras funciones útiles:

  • os.path.abspath(path) Retornará un string con el string absoluto de los argumentos.
  • os.path.isabs(path) True si el argumentos es absoluto.
  • os.path.relpath(path, start) Retornará una dirección relativa desde start hasta path. Si start no está indicada, tomará en su lugar el directorio de trabajo.

Partes de una dirección de archivo

Un objeto tipo Path se compone de diferentes partes, que constituyen sus atributos:
c:\Users\Al\spam.txt

  • C: Drive Letra que denota la partición o dispositivo físico.
  • C:\ Anchor Directorio raíz.
  • \Users\Al\ Parent Directorio que contiene el archivo.
  • spam.txt Name Archivo, formado a su vez:
    • spam Stem Tallo, nombre del archivo sin la extensión.
    • .txt Suffix Extensión, define el tipo de archivo.

Para obtener cada atributo, es tan fácil como indicarlo:

p = Path('C:/Users/Al/spam.txt')
p.anchor  # 'C:\\'
p.parent  # WindowsPath('C:/Users/Al')  # parent es el único que es de tipo Path en lugar de string
p.name    # 'spam.txt'
p.stem    # 'spam'
p.suffix  # '.txt'
p.drive   # 'C:'

También se puede utilizar el módulo viejo os:

  • os.path.dirname(path) Devuelve un string con todo lo que hay antes del último \ en el argumento.
  • os.path.basename(path) Devuelve un string con todo lo que hay después del último \ en el argumento.
  • os.path.split(path) Devuelve una tupla con dos elementos, correspondiente al dirname y al basename.
  • os.sep Si se pasa como argumento del método split os.sep, devuelve cada elemento de la dirección como strings dentro de una lista:
calcFilePath = 'C:\\Windows\\System32\\calc.exe'
calcFilePath.split(os.sep)
# ['C:', 'Windows', 'System32', 'calc.exe']

Buscando tamaños de archivo y contenido de directorios

Se pueden buscar tamaños de archivo y contenido de directorios usando el módulo os:

  • Obtener el tamaño en bytes de un archivo: os.path.getsize(path)
  • Obtener una lista de los nombres de archivo de un directorio: os.listdir(path) Se puede usar en un bucle for en lugar de range() para recorrer los archivos de un directorio.

También se pueden usar patrones Glob para obtener archivos de un directorio. Los patrones Glob pueden realizar búsquedas de forma similar a la de las expresiones regulares, aunque es más sencillo:

p = Path('C:/Users/Al/Desktop')
p.glob('*') # <generator object Path.glob at 0x000002A6E389DED0> Devuelve un objeto generador
list(p.glob('*')) # Crea una lista de los archivos que se encuentran en el directorio definido en p, en formato absoluto

como argumentos de glob() se especifica el patrón de forma similar a una expresión regular:

  • Será tomado en consideración cualqueir texto que se indique.
  • '*' Uno o varios caracteres, cualesquiera. Ejemplo: glob('*.txt') buscaría todos los archivos de texto.
  • '?' Unúnico carácter cualquiera.
  • Se pueden mezclar para obtener patrones más complejos.

Validación de paths

Muchas funciones dan un error si la dirección indicada no funciona. Algunos métodos útiles de tipos de objeto Path, son (asumiendo p como objeto tipo Path):

  • p.exists() True si la dirección existe.
  • p.is_file() True si la dirección existe y es un archivo.
  • p.is_dir() True si la dirección existe y es un directorio.

Para estos mismos cometidos podrían usarse los viejos métodos os.path.exists(path), os.path.isfile(path), y os.path.isdir(path).

Proceso de lectura/escritura de archivos

En este apartado se verá la forma de leer y escribir en archivos de texto plano.

Lectura/escritura básica

Los métodos de la clase pathlib más sencillos y directos para leer/escribir con archivos son path.read_text() y path.write_text(string).

  • path.read_text() devuelve un string con el contenido completo del archivo de texto.
  • path.write_text(string) devuelve el número de caracteres escritos, crea un nuevo archivo, si no existe, y si existe, lo sobreescribe, ojo con esto.

Lectura/escritura con open()

Proceso a seguir:

  1. Se llama a la función open(), que devuelve un objeto de tipo File: archivo = open(dirección del archivo)
  2. Se llama a los métodos read() o write() del objeto File.
  3. Se cierra el archivo con el método close() del objeto File.

Lectura

La función open() permite un segundo argumento en el que se indica el modo en el que se abre el archivo, por defecto en modo lectura (argumento: 'r').

El método read() devuelve en un único string el contenido de todo el archivo. Con el método readlines() se obtiene una lista en la que cada elemento es el string correspondiente a cada línea del archivo (cada string termina con \n, salvo el último, lógicamente).

Escritura

Para escribir texto en un archivo de texto plano, éste debe de abrirse con open() indicando el modo:

  • 'w': Si no existe en archivo, se crea. Comienza a escribir desde el inicio del documento y si hay algo ya escrito, se sobreescribe.
  • 'a': Si no existe en archivo, se crea. Comienza a escribir desde el final del documento.

En ambos casos, siempre se escribe la cadena que se pasa como argumento del método write(). Devuelve el número de caracteres escritos.

Guardar variables

Guardar variables en archivos binarios

Con el módulo shelve se pueden guardar variables en un archivo binario, para después recuperar sus valores. De ese modo, no se pierde informaión al cerrar el programa (las variables normales son destruidas).

La forma de usar esta funcionalidad es similar a la de leer/escribir en un archivo:

  1. Importamos la biblioteca: import shelve
  2. Damos un nombre a los archivos binarios que se crearán ('mydata'), los abrimos (con shelve se permite tanto leer como escribir) y asignamos el valor devuelto a una variable: shelfFile = shelve.open('mydata')
  3. Trabajamos con la información que contiene:
    1. Para escribir (guardar) información, se guarda como se haría en un diccionario.
    2. Para leer (recuperar) información, también se hace como en un diccionario: atendiendo a la clave entre corchetes.
    3. Es posible listar la información con la función list()
  4. Cerramos el binario con close(): ShelfFile.close()
import shelve
shelfFile = shelve.open('mydata')
cats = ['Zophie', 'Pooka', 'Simon']
shelfFile['cats'] = cats
shelfFile['cats']        # ['Zophie', 'Pooka', 'Simon']
list(shelfFile.keys())   # ['cats']
list(shelfFile.values()) # [['Zophie', 'Pooka', 'Simon']]
shelfFile.close()

Guardar variables en archivos de texto .py

En este caso la idea es guardar las variables en un archivo de python (.py), de forma que pueda importarse como una biblioteca, y de ese modo recuperar los dartos.
Para ello se utiliza el método pformat() de la biblioteca pprint (Pretty Print), que devuelve una variable tal y cmo se escribe en código.

import pprint
cats = [{'name': 'Zophie', 'desc': 'chubby'}, {'name': 'Pooka', 'desc': 'fluffy'}]
pprint.pformat(cats)  # "[{'desc': 'chubby', 'name': 'Zophie'}, {'desc': 'fluffy', 'name': 'Pooka'}]"
fileObj = open('myCats.py', 'w')
fileObj.write('cats = ' + pprint.pformat(cats) + '\n')  # 83
fileObj.close()
import myCats
myCats.cats             # [{'name': 'Zophie', 'desc': 'chubby'}, {'name': 'Pooka', 'desc': 'fluffy'}]
myCats.cats[0]          # {'name': 'Zophie', 'desc': 'chubby'}
myCats.cats[0]['name']  # 'Zophie'

Con esta funcionalidad los datos se guardan en texto plano, fácil de editar por cualquiera.
De este modo se pueden guardar variables de tipos básicos (string, enteros, listas, diccionarios, etc), pero no de tipos más complejos (como Files).
Para guardar datos más complejos es necesario usar el módulo shelve.

Trabajar con archivos y directorios

Acciones sobre archivos y directorios

Para realizar acciones sobre archivos y directorios, como mover, copiar, renombrar o borrar, vamos a utilizar la biblioteca shutil shell utilities.

Copiar

Para copiar un único archivo se utiliza el método shutil.copy(source, destination).

  • source: Dirección del archivo, incluído, puede ser de tipo Path o string.
  • destination: Dirección donde se copiará archivo, también puede ser de tipo Path o string. Si se indica un nombre de archivo, además será renombrado con éste.
  • retorna un dato Path con el dirección del archivo copiado, incuído éste.

Para copiar un directorio completo, con todos sus subdirectorios y archivos, se utiliza del mismo modo la función shutil.copytree(source, destination). Devuelve un dato Path con el dirección del directorio copiado.

Mover y renombrar

Para mover un archivo o un directorio, se utiliza el método shutil.move(source, destination):

  • source: Dirección del archivo, incluído, puede ser de tipo Path o string.
  • destination: Dirección donde se moverá el archivo, también puede ser de tipo Path o string. Si se indica un nombre de archivo, además será renombrado con éste. OJO, si el último directorio especificado no existe, y no se renombra el archivo, éste será renombrado con el nombre del directorio inexistente ¡no diferencia entre nombre de archivo y nombre de directorio!
  • Si algún valor de los directorios intermedios donde se desea transferir el archivo o directorio no existe, se producirá un error FileNotFound.
  • Devuelve la dirección del directorio o archivo movido.

Borrado de directorios y archivos

Borrado permanente

  • Para borrar permanentemente un único archivo: os.ulink(path)
  • Para borrar permanentemente un directorio completamene vacío: os.rmdir(path)
  • Para borrar permanentemente un directorio y todo su contenido: shutil.rmtree(path)
import os
from pathlib import Path
for filename in Path.home().glob('*.rxt'):
    #os.unlink(filename)  # Para ver los próximos archivos a eliminar, se comenta esta línea. Si estamos seguros, entonces se descomenta.
    print(filename)

Borrado "seguro"

La idea es enviar los archivos a la papelera de reciclaje, en lugar de borrarlos directamente. Para ellos usamos el método send2trash() del módulo send2trash.
Es un módulo de terceros que debe instalarse con pip install –user send2trash.

>>> import send2trash
>>> baconFile = open('bacon.txt', 'a')   # creates the file
>>> baconFile.write('Bacon is not a vegetable.')
25
>>> baconFile.close()
>>> send2trash.send2trash('bacon.txt')

Recorrer un árbol de directorios

La biblioteca os nos proporciona la función os.walk(string), que usada en conjunto con un bucle for (en lugar de range()), en cada iteración se mueve por los directorios del árbol, lo que permite recorrer el arbol de directorios:

En cada iteración del bucle for, la función walk() devuelve:

  • String con el directorio actual.
  • Una lista de strings con sus subdirectorios.
  • Una lista de strings con sus archivos.
'''
C:/
    delicius
        cats
            catnames.txt
            zophie.jpg
        walnut
            waffles
                butter.txt
        spam.txt
 
'''
import os
 
for folderName, subfolders, filenames in os.walk('C:\\delicious'):
    print('The current folder is ' + folderName)
 
    for subfolder in subfolders:
        print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
 
    for filename in filenames:
        print('FILE INSIDE ' + folderName + ': '+ filename)
 
    print('')
The current folder is C:\delicious
SUBFOLDER OF C:\delicious: cats
SUBFOLDER OF C:\delicious: walnut
FILE INSIDE C:\delicious: spam.txt
 
The current folder is C:\delicious\cats
FILE INSIDE C:\delicious\cats: catnames.txt
FILE INSIDE C:\delicious\cats: zophie.jpg
 
The current folder is C:\delicious\walnut
SUBFOLDER OF C:\delicious\walnut: waffles
 
The current folder is C:\delicious\walnut\waffles
FILE INSIDE C:\delicious\walnut\waffles: butter.txt

Trabajar con archivos comprimidos ZIP

Comprimir ZIP

Leer ZIP

Extraer ZIP

Crear y añadir a ZIP

python/archivos.1649331739.txt.gz · Última modificación: por alberto

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki