Examinar archivo o carpeta en Tk (tkinter)

Examinar archivo o carpeta en Tk (tkinter)

Examinar archivo en Tk

Tk provee funciones para desplegar diálogos para examinar archivos o carpetas en Windows, Linux (o cualquier otro sistema basado en Unix) y macOS. En Python las funciones son accesibles a través del módulo tkinter.filedialog. Las principales son:

  • askopenfilename() / askopenfilenames()
  • askdirectory()
  • asksaveasfilename()

Las funciones askopenfilename() y askopenfilenames() muestran un diálogo para abrir uno o más archivos. askdirectory() hace lo propio para examinar una carpeta (no es posible seleccionar más de una carpeta). asksaveasfilename() despliega un cuadro similar al de las primeras dos funciones, pero para guardar un archivo en lugar de abrirlo. Veremos sus diferencias en seguida.

En Windows y macOS las funciones trabajan internamente con cuadros nativos del sistema operativo, lo cual nos asegura que siempre obtendremos una herramienta actualizada y moderna para examinar archivos o carpetas. En el sistema de Microsoft, Tk hace uso de las interfaces nativas IFileDialog, IFileOpenDialog e IFileSaveDialog disponibles a partir de Windows Vista. En Windows XP y versiones anteriores emplea las funciones GetOpenFileName() y GetSaveFileName(). La implementación puede observarse en el archivo tkWinDialog.c del código de fuente de Tk. En macOS, Tk trabaja asimismo con las interfaces nativas NSOpenPanel y NSSavePanel. La implementación está disponible en el archivo tkMacOSXDialog.c (escrito en Objective-C). En sistemas Unix los diálogos simulan la ventana de Windows (95) y están escritos directamente en Tcl en el archivo tkfbox.tcl.

Todas las funciones tienen una interfaz similar. Pueden llamarse sin argumentos y retornan una cadena (a excepción de askopenfilenames(), que retorna una tupla de cadenas). Por ejemplo, para mostrar un diálogo para abrir un archivo usamos:

from tkinter import filedialog

# Mostrar el diálogo para abrir un archivo.
filename = filedialog.askopenfilename()
# Imprimir la ruta del archivo seleccionado por el usuario.
print(filename)

El diálogo permite recorrer todo el sistema de archivos y seleccionar un archivo de él. Los textos del diálogo se presentan en el idioma configurado en el sistema operativo. La ruta del archivo seleccionado por el usuario es retornada como una cadena y guardada, en este caso, en la variable filename. Si el usuario cancela o cierra el diálogo, el resultado es una cadena o tupla vacía (dependiendo del sistema operativo), por lo cual generalmente querremos hacer un condicional luego de llamar a la función. Puesto que tanto tuplas como cadenas vacías se evalúan como False, no es necesario distinguir un caso del otro. Por ejemplo:

from pathlib import Path
from tkinter import filedialog

filename = filedialog.askopenfilename()
if filename:
    # Leer e imprimir el contenido (en bytes) del archivo.
    print(Path(filename).read_bytes())
else:
    print("No se ha seleccionado ningún archivo.")

La función askopenfilenames() (nótese la «s» al final) permite al usuario seleccionar más de un archivo en la misma carpeta. El resultado es en este caso una tupla que contiene las rutas de los archivos seleccionados. Aquí también se retorna una cadena o tupla vacía cuando el diálogo es cancelado.

filenames = filedialog.askopenfilenames()
if filenames:
    print("Archivos seleccionados:")
    for filename in filenames:
        print(filename)
else:
    print("No se ha seleccionado ningún archivo.")

askdirectory() es similar a askopenfilename(), pero solo permite seleccionar carpetas:

directory = filedialog.askdirectory()
print(directory)

Nótese que en estas tres funciones las carpetas o los archivos seleccionados deben existir. Si el usuario escribe el nombre de un archivo o de una carpeta inexistente, el diálogo muestra un mensaje de error.

La función asksaveasfilename(), en cambio, sirve para seleccionar un archivo aún inexistente escribiendo su nombre en la caja de texto, típicamente para implementar una funcionalidad de guardado de archivos. Si el archivo seleccionado por el usuario ya existe, el diálogo muestra un mensaje al usuario solicitándole su confirmación para reemplazar el archivo. El valor de retorno tiene el mismo comportamiento que en askopenfilename().

# Diálogo para guardar archivo.
filename = filedialog.asksaveasfilename()
print(filename)

Por defecto, los diálogos producidos por las tres funciones para examinar archivos muestran todo tipo de archivos. Podemos configurar el diálogo para mostrar solo determinados tipos de archivos vía el argumento filetype:

filename = filedialog.askopenfilename(
    filetypes=(
        ("Archivos de texto", "*.txt"),
        ("Archivos de Python", ("*.py", "*.pyx")),
        ("Todos los archivos", "*.*")
    )
)

El argumento recibe una tupla de tuplas de dos elementos. El primer elemento de las tuplas interiores indica el nombre del tipo de archivo que será mostrado al usuario. El segundo puede ser una cadena o una tupla de cadenas indicando los patrones a utilizar. Por ejemplo, la cadena *.txt muestra solo los archivos que terminan con .txt, mientras que la tupla ("*.py", "*.pyx") muestra archivos que terminan con .py o .pyx. El patrón *.* sirve para mostrar archivos con cualquier nombre y extensión. Cuando el argumento filetypes está presente, el diálogo incluye una lista desplegable con la cual el usuario puede indicar el tipo de archivo que quiere visualizar:

Examinar archivo en Tk con filtro de tipos de dato

En todas las funciones puede indicarse el argumento intialdir para definir la ruta inicial en la que aparecerá el diálogo. Por ejemplo:

# Iniciar en la raíz del disco.
filename = filedialog.askopenfilename(initialdir="C:/")

O para iniciar en la carpeta donde se encuentra el intérprete de Python:

from pathlib import Path
from tkinter import filedialog
import sys

filename = filedialog.askopenfilename(
    initialdir=Path(sys.executable).parent
)

Si intialdir no es indicado, la ruta inicial depende del sistema operativo. En sistemas Unix y macOS es el directorio actual de trabajo, que por lo general coincide con la ruta donde se encuentra nuestro archivo de Python. En Windows es la última ruta desde la cual se seleccionó un archivo en esa misma aplicación. En macOS a veces el valor de initialdir es ignorado, según la configuración del usuario.

Por último, el título y la ventana padre del diálogo pueden indicarse vía los parámetros title y parent, respectivamente. El diálogo se cierra automáticamente si la ventana padre es destruida.

from tkinter import filedialog
import tkinter as tk

ventana_principal = tk.Tk()
ventana_principal.title("Ventana principal")
ventana_secundaria = tk.Toplevel()
ventana_secundaria.title("Ventana secundaria")
filename = filedialog.askopenfilename(
    parent=ventana_secundaria,
    title="Examinar archivo"
)
ventana_principal.mainloop()

Donar ❤️

¿Te gusta nuestro contenido? ¡Ayudanos a seguir creciendo con una donación!

Deja una respuesta