Mostrando entradas con la etiqueta Python. Mostrar todas las entradas
Mostrando entradas con la etiqueta Python. Mostrar todas las entradas

martes, 18 de noviembre de 2025

Textos. Python

Aplicación práctica

Extracción de texto a partir de imágenes




Presento en esta entrada la primera aplicación práctica de los procedimientos tratados en esta subsección relativa al trabajo con textos mediante Python. Primero nos situaremos en contexto, después mostraré el script y finalmente lo explicaré.

Me planteo crear una aplicación que facilite la evaluación del grado de adquisición del sistema fonológico. Para ello selecciono la prueba PLON-R Fonología y necesito estudiar su fundamentación teórica, por lo que accedo a su manual. Dado que se ese manual es un documento en papel, caben dos opciones: copiar manualmente la información que considere necesaria o capturarla en imágenes (vg. en png).

Dado que la primera opción lleva cierto tiempo, opto por la segunda, pero para acceder al contenido necesito convertir esas imágenes en texto. Para ello creo un directorio (Textos) donde copio las imágenes ordenadas según la lógica de su contenido y creo un script Python para acceder al texto que contienen las imágenes.

import os
import pytesseract
from PIL import Image

#Ruta a Tesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

'''
Acceder al listado de documentos png del directorio Textos
'''
lista_img = []
#Listado imágenes . Acceso al directorio
directorio = 'Textos/'
os.chdir(directorio)
lista_archivos = os.listdir('.')

for elemento in lista_archivos:
    lista_img.append(elemento)

'''
Acceder a las imágenes para extraer el texto y copiarlo en documento txt
'''
for elemento in lista_img:
    img = Image.open(elemento)
    # Extraer texto
    texto = pytesseract.image_to_string(img, lang ='spa')
    #Escribir el texto en el archivo .txt
    archivo = open('plon_fono.txt','a', encoding='utf-8')
    archivo.write(texto+'\n')
    archivo.close()

Explico a continuación este script que, como puedes ver, requiere trabajar con tres bibliotecas Python:
  • os (import os) para generar el listado del contenido del directorio Textos y automatizar el acceso a esos documentos (imágenes png)
  • Pillow (from PIL import Image) para acceder a cada una de las imágenes
  • Pytesseract (import pytesseract) para trabajar con el programa OCR Tesseract.
En primer lugar establecemos la ruta para acceder al programa OCR (pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'), paso necesario para el procesamiento OCR de las imágenes.

En segundo lugar accedemos al directorio Textos mediante las funciones os y listamos los archivos que contiene como textos para su posterior uso en el bucle de acceso a las imágenes.

Para ello identificamos el directorio (directorio = 'Textos/') y nos ubicamos en él (os.chdir(directorio)) para extraer su contenido (lista_archivos = os.listdir('.')) y pasarlo a una lista (lista_img = []) de string mediante la función append() (lista_img.append(elemento)) dentro de un bucle que recorre el contenido del directorio (for elemento in lista_archivos:). Sobre esa lista de nombres de archivos desarrollaremos la segunda parte del script.

Dicha segunda parte consiste en recorrer los archivos, acceder a su contenido y convertirlo en texto mediante procedimiento OCR. Todo ello se desarrolla dentro de un segundo bucle for (for elemento in lista_img:) que accede secuencialmente a cada imagen usando la librería Pillow (img = Image.open(elemento)) que pasa la imagen la función image_to_string() de la biblioteca pytesseract (que conecta con el programa OCR Tesseract (texto = pytesseract.image_to_string(img, lang ='spa')) que convierte el contenido de la imagen en un texto editable.

Simultáneamente, en el mismo bucle, se desarrolla la tercera fase que consiste en aplicar las funciones de creación, escritura y cierre de documentos externos txt con que cuenta Python.

Esta parte del script repite cíclicamente el proceso de crear/acceder al documento txt (archivo = open('plon_fono.txt','a', encoding='utf-8')) y escribir el contenido obtenido mediante el procedimiento identificado como segunda parte del script...

(texto = pytesseract.image_to_string(img, lang ='spa')) -> (archivo.write(texto+'\n'))

... y finaliza, ya fuera del bucle, con el cierre del documento (archivo.close()).

El resultado de la aplicación de este script es un documento txt, un tanto "desmadejado" para perfectamente útil para incorporar el contenido de esos documentos obtenidos inicialmente como imágenes a nuestro análisis del documento.

Documentos. A efectos de facilitarte el acceso al resultado y la réplica de esta práctica de dejo a continuación algunos materiales que deberás descargar desde este enlace: textos_imagenes y descomprimirlo. Contiene la carpeta Textos, que a su vez contiene unas imágenes y el documento txt resultante (plon_fono.txt), y el script textos_plon.py.


sábado, 15 de noviembre de 2025

Expedientes. Análisis


Análisis de datos (IX)

Expedientes Excel (b)



Parece que ya tenemos definido el concepto de expediente SEO digitalizado, tanto en términos cuantitativos como cualitativos, así que ahora toca pasar al análisis en función de los objetivos indicados en la [entrada anterior]. Pero se nos presentan varios problemas que habrá que solucionar antes de empezar con el análisis propiamente dicho.


El primero es disponer de datos que consultar, o mejor dicho, determinar cuáles son las fuentes de datos, ya que no podemos utilizar el listado inicial (no nos aporta más que el total de elementos (archivos) por directorio (expediente) ni podemos usar el procedimiento que nos sirvió para identificar y extraer los datos que nos sirvió para realizar el análisis de los repositorios de documento único.

En este caso, por diferentes motivos prácticos (ya están disponibles) pero también por avanzar en el aprendizaje de procedimientos (acceso secuencial al contenido de múltiples archivos), me propongo trabajar con una colección de archivos sobre hoja de cálculo, resultantes de un DocAp que se expone en esta misma sección del blog, que contienen datos cuantitativos y de estructura de un conjunto amplio de expedientes SEO.

El problema que nos encontramos es que estos archivos están en formato Calc y por motivos que no tengo claros, no me es posible acceder a su contenido mediante la [biblioteca ezodf], así que me veo obligado a buscar una solución que facilite el posterior acceso a los archivos desde Python. Esto es necesario tanto por las limitaciones de OOo Basic para trabajar con múltiples documentos como por el interés que tiene el uso de Python en el análisis de datos.

Y digo esto como planteamiento inicial, porque la solución encontrada bien podría considerarse una demostración práctica de la potencia de OOo Basic para automatizar el manejo de un conjunto amplio de documentos; lo que no nos  lleva a modificar el proyecto inicial de usar Python como herramienta fundamental para el análisis de datos.

Empecemos por clarificar algunas cuestiones. Dispongo de un total de 244 archivos Calc, resultantes de la aplicación de [este DocAp]. Este total es suficientemente elevado como para considerarlo acorde con el volumen total de expedientes disponible (483). Sabiendo que esos documentos no recogen loa datos de los expedientes de 1 y 2 documentos, podemos considerarlos además, representativos de aquellos que caen dentro del concepto amplio de expedientes, aunque algunos de ellos puedan estar dentro del subgrupo de expedientes fallidos. 

A efectos prácticos vamos a considerar este dato como desconocido; en realidad podremos identificarlos visualmente o por análisis cruzados del listado con la visualización del contenido del directorio donde se encuentran. Precisamente es este trabajo "visual" el que pretendemos evitar.

Así que, aunque ya tenemos identificada nuestra fuente de datos, y podemos considerarla ajustada a nuestro objetivo, es necesario transformar el tipo de documento de Calc a Excel, para poder desarrollar después procedimientos de acceso a datos basados en Python y en su [biblioteca OpenPyxl]. Si queremos evitar realizar manualmente esta conversión desde Calc, deberemos recurrir un script o a una macro OOo Basic; si bien antes es conveniente aportar a ese soporte el listado de los documentos Calc que vamos a convertir en Excel, y para ello necesitamos recurrir a Python, concretamente a su [librería os]. Como puedes ver, todo un complejo enredo de interdependencia . En realidad una complejidad más aparente que real. Veremos por qué. 

Dado que se impone como necesidad la conversión de archivos Calc a Excel (recuerda que Calc lee .xls/xlsx, pero Excel no lee .ods), la solución que se me ocurre es utilizar Calc para realizar esa conversión, automatizando el procedimiento mediante un script basado en una macro. Ello lleva (como veremos) a desarrollar un procedimiento basado en tres subrutinas enlazadas en tándem: la primera llama a la segunda y la segunda a la tercera.

Esta solución, que requiere explicación específica, implica automatizar el proceso en parte, pero deja pendiente hacerlo a su inicio, dado que no dispongo de solución OOo Basic que facilite el acceso a los nombres de todos los archivos del directorio. Sin embargo esto es posible hacerlo sin dificultad mediante Python, concretamente usando su módulo os.

Resuelvo, pues, la automatización del acceso a la colección de documentos Calc mediante un script Python…

import os

directorio = "ExpedCalc/"

contenido = os.listdir(directorio)

n_elem = 0

print('Listado de componentes \n')

for elemento in contenido:
    n_elem = n_elem +1
    print (f'Elemento número {str(n_elem)} -> {elemento}')

print(f'\n TOTAL elementos del directorio {str(n_elem)}')

archivo = open('listaExped.txt','x', encoding='utf-8')

for elemento in contenido:
    archivo.write(elemento+'\n')

archivo.close()

… que accede al directorio que contiene los documentos Calc (directorio = "ExpedCalc/"), extrae el contenido (contenido = os.listdir(directorio)) y después de mostrarlo en pantalla lo copia en un documento txt (archivo = open('listaExped.txt','x', encoding='utf-8')) mediante un bucle (for elemento in contenido: -> archivo.write(elemento+'\n'))...



A continuación copio el contenido de este documento txt en un archivo Calc en blanco y obtengo un listado parecido a éste.


 Como puedes ver se reproduce perfectamente el listado obtenido con el script Python, por lo que nos sirve para generar el código OOo Basic necesario para realizar la transformación de documentos Calc en Excel

Pero el desarrollo de este procedimiento (te ahorro ese recorrido fallido) permite considerar que no es buena idea incluir la extensión del archivo como parte del texto a manejar (ya veremos el motivo), así que necesitamos trabajar con este listado para quedarnos sólo con el nombre y prescindir de la extensión .ods.

Para ello recurro a funciones built-in de Calc, concretamente a dos del grupo Texto: LARGO() e IZQUIERDA(). La primera calcula la longitud (n caracteres) de una cadena de texto y la segunda permite extraer una parte de esa cadena empezando desde la izquierda. Así que primero calculamos la longitud de cada uno de los elementos del listado y después aplicamos la función IZQUIERDA() pasando como primer parámetro la cadena y como segundo la diferencia (LARGO(Ax)-4), siendo 4 la longitud de la extensión más el punto (.ods).


Lo que obtenemos es un documento Calc que contiene una triple lista: la de los nombres íntegros de los archivos, la de la longitud de cada nombre y la de los identificadores de los archivos (nombres sin la extensión). Esta última (columna C) es la que nos interesa para desarrollar los script OOo Basic.



Partiendo de esta nueva lista sin las extensión .ods puedo aplicar un conjunto de tres script (en realidad un script y dos subrutinas) que trabajan en tandem y que (esto es muy importante) es necesario ubicar en el directorio Mis macros y diálogos, biblioteca Standard del IDE (no en  el directorio de script del documento).

El primero de estos tres script OOo Basic (acceso_lista) permite tomar cada elementos del listado para automatizar el acceso a los archivos Calc. Por ello es necesario activarlo desde el documento Calc sobre el que creamos la lista que vemos en la imagen anterior (podemos llamarlo lista_al.ods, por ejemplo). Aquí tienes el código de este primer script:

Sub acceso_lista

Dim  oHoja As Object
Dim oCelda As Object
Dim oDato As Object
Dim i As Integer
Dim n As Integer
Dim Archivo As String

n = 244

oHoja = ThisComponent.getSheets().getByName("lista") 
for i = 1 To n
oCelda = oHoja.getCellRangeByName( "C" & i)
Archivo = oCelda.getString()
AbrirDocumento(Archivo)
Next

End Sub
Como puedes ver, este script permite acceder a la lista Calc mediante el procedimiento conocido de acceso a libro->hoja->celda. Utiliza un bucle For…Next para recorrer dicha lista, entregando cada uno de los datos obtenidos a la subrutina AbrirDocumento() encargada de acceder al documento Calc.

Sub AbrirDocumento (alumno)

Dim sRuta As String
Dim mOpciones(0) As New "com.sun.star.beans.PropertyValue"
Dim oDoc As Object
mOpciones(0).Name = "MacroExecutionMode"
mOpciones(0).Value = 4
Dim ruta As String
ruta = "D:/EXPEDIENTES/ExpedientesOriginales/" & alumno & ".ods"

sRuta = ConvertToUrl(ruta)
oDoc = StarDesktop.loadComponentFromURL( sRuta, "_blank", 0, mOpciones() )

Dim oHoja As Object
Dim oCelda As Object
Dim iDato As Integer
Dim archivo As String
oHoja = ThisComponent.getCurrentController.getActiveSheet()
oCelda = oHoja.getCellRangeByName("C10")
iDato=oCelda.getValue()

if iDato <= 4 Then
oDoc.close(True)
Else
archivo = alumno
grabar_excel (archivo)
End If

End Sub

Esta subrutina permite acceder al archivo Calc, capturar el valor de la celda C10 que contiene el dato del total de documentos del expediente y, en función del (in)cumplimiento de una condición (if iDato <= 4 Then) llamar a la subrutina siguiente (grabar_excel (archivo)) pasando como parámetro el mismo dato que recibió ella también como parámetro (Sub AbrirDocumento (alumno)), antes de convertirla en una URL (sRuta = ConvertToUrl(ruta)), lo que garantiza el acceso al documento con independencia de la plataforma, pero también con total seguridad (evidentemente esa dirección debe existir y contar con los documentos Calc a los que se desea acceder).

Finalizamos el procedimiento haciendo entrar en escena la segunda subrutina y tercer componente del tandem (grabar_excel (documento)), que se encarga de grabar el archivo como Excel y en su correspondiente directorio. 

Sub grabar_excel (documento)

dim document   as object
dim dispatcher as object

document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dim archivo As String
archivo = "file:///D:/EXPEDIENTES/ExpedientesExcel/" & documento & ".xlsx"

dim args1(1) as new com.sun.star.beans.PropertyValue
args1(0).Name = "URL"
args1(0).Value = archivo
args1(1).Name = "FilterName"
args1(1).Value = "Calc MS Excel 2007 XML"

dispatcher.executeDispatch(document, ".uno:SaveAs", "", 0, args1())
document.close(True)

end sub
Como puedes ver, esta subrutina se basa en código macro posteriormente modificado. Esta modificación se concreta como transformación de la macro en subrutina y como sustitución de la ruta absoluta directa por una variable string previamente modificada (archivo = "file:///D:/EXPEDIENTES/ExpedientesExcel/" & documento & ".xlsx") para ajustarla a los valores múltiples que va a presentar a lo lago del proceso, ya que todo ello (y en ambas subrutinas) está dentro del bucle For definido en el script principal.

El resultado es que obtenemos una copia de archivos Excel que cumplen el criterio de contener datos sobre expedientes SEO con 5 y más documentos. Estos archivos quedan ahora a disposición de script Python, objetivo último de esta fase del proceso. El directorio en el que se encuentran es el establecido en la segunda subrutina ("D:/EXPEDIENTES/ExpedientesExcel/"), siendo el de procedencia el indicado en la primera ("D:/EXPEDIENTES/ExpedientesOriginales/"). Ambas son direcciones ficticias y ambas deberán ser adaptadas a la realidad concreta de tu organización de los archivos. Cada documento queda identificado por su nombre (aquí utilizamos claves de identificación), coincidiendo éste con el que consta en el listado Calc que sirve de base de datos al conjunto del proceso y que es consultada sistemática y sucesivamente en el script inicial y principal (Sub acceso_lista) mediante el bucle For que enmarca el resto del procedimiento

for i = 1 To n
oCelda = oHoja.getCellRangeByName( "C" & i)
Archivo = oCelda.getString()
AbrirDocumento(Archivo)
Next

En la entrada que sigue explicaré el acceso al contenido de los documentos (ahora) Excel mediante Python y su librería OpenPyXL. Eso y alguna cosa más.

domingo, 9 de noviembre de 2025

Expedientes. Análisis.

Análisis de datos (VII)

Repositorios (d)



Como prometí en la [entrada anterior], ahora toca mostrar el script Python empleado en el análisis de la tipología de documentos que contienen los repositorios más característicos de esta categoría, los de documento único. Evidentemente también nos toca ahora analizar los resultados obtenidos con esa herramienta.


Veamos primero el script, que lo prometido es deuda:

import os

directorio = "D:/EXPEDIENTES_SEO"

contenido = os.listdir(directorio)

n_doc = 0
n_conten = 0
n_dir = 0

#Extensiones a identificar
exten_doc = 0
exten_pdf = 0
exten_xls = 0
exten_ods = 0
doc_texto = 0

#Recorrido del listado de archivos

for exped in contenido:
    dir_exped = directorio + "/" + exped
#Seleccionar directorios de un único elemento
    n_conten = len(os.listdir(dir_exped))
    if n_conten == 1:
         with os.scandir(dir_exped) as entradas:
            for entrada in entradas:
                if entrada.is_file():
                    nombre_sin_extension, extension = os.path.splitext(entrada)
                    print(f"Nombre original: {entrada}")
                    print(f"Nombre sin extensión: {nombre_sin_extension}")
                    print(f"Extensión: {extension}")
                    print('\n')
                    if extension == '.doc' or extension == '.docx' or extension == '.odt':
                        exten_doc = exten_doc + 1
                    elif extension == '.pdf':
                        exten_pdf = exten_pdf + 1
                    elif extension == '.xls' or extension == '.xlsx' or extension == '.ods':
                        exten_xls = exten_xls + 1

#Resultados

doc_texto = exten_doc + exten_pdf

print(f'\nRESUMEN DE LOS DATOS OBTENIDOS. Tipo de documento\n')

print("Número de documentos Procesador de texto " ,str(exten_doc))
print("Número de documentos de tipo PDF " ,str(exten_pdf))
print("Total documentos de texto: " , str(doc_texto))
print("Número de documentos Hoja de cálculo " ,str(exten_xls))

El objetivo de este script es identificar los archivos por su extensión para conocer el peso relativo de cada tipo de archivo en los directorios de documento único. Se trata de un script ya visto [en esta entrada], aunque con alguna diferencia. Cómo aquel se basa en el uso del módulo os del que utilizamos fundamentalmente la función os.listdir() y la función os.scandir() dentro de estructuras anidadas de bifurcación y de iteración, que son el núcleo del script.

En esto coincide este script y el que sirvió de fuente, aunque se diferencian en que en el actual es posible visualizar también el directorio original (print(f"Nombre original: {entrada}")) y el nombre del archivo (print(f"Nombre sin extensión: {nombre_sin_extension}")), además de la lista de extensiones (print(f"Extensión: {extension}")). Todo esto es posible gracias a la expresión (nombre_sin_extension, extension = os.path.splitext(entrada)).

Estos datos, que se ofrecen como listados, se complementan con los resultantes del cálculo, mediante conteo (vg. exten_doc = exten_doc + 1) y en el marco de un condicional (if extension == '.doc' or extension == '.docx' or extension == '.odt':) de una determinada categoría de archivo, definida por la extensión del documento.

Los listados permiten realizar un análisis más detallado de la naturaleza del documento, aplicando los criterios presentados en la [entrada anterior]. Al menos parcialmente podría haber planteado hacer esto mediante código, pero no lo he desarrollado hasta no disponer de los conocimientos necesarios para resolver los distintos problemas que se plantean. He preferido, como alternativa, ofrecer la lista de documentos como salida de monitor para que tú, si te interesa, puedas hacer ese tipo de análisis. Por mi parte me limitaré a realizar algunas comprobaciones.

Para que tú puedas realizar tu propio análisis es necesario, por supuesto, que dispongas de una colección de expedientes del mismo tipo de los que yo analizo aquí y que identifiques adecuadamente la ruta absoluta en la que se encuentran (los míos en directorio = "D:/EXPEDIENTES_SEO").

Pasemos ahora a exponer los datos cuantitativos del recuento: Tipología de los documentos de repositorios de documento único:
  • Número de documentos Procesador de texto  91
  • Número de documentos de tipo PDF  5
  • Total documentos de texto:  96
  • Número de documentos Hoja de cálculo  4
El número total de documentos, que resulta de sumar los anteriores, es 100; alguno más de los que recogía el análisis de frecuencias realizado sobre el primer cómputo de directorios (en ese caso eran 97), pero la diferencia es tan pequeña que podemos considerarla irrelevante.

Lo que no es es el total de documentos que pertenecen a la categoría 1: la que está formada por los documentos derivados directamente del uso de un procesador de texto, que suponen el 91% del total. frente a ellos, el resto (PDF y Hojas de datos) son absolutamente minoritarios (juntos suman el 9%). Si además sumamos los primeros con los PDF (en el supuesto que se explicó como causa principal en la [entrada anterior]), el sumatorio de documentos en encajan inicialmente en  la casuística repositorio suma un total del 96% de los directorios de documento único. Sólo 4%, las hojas de cálculo, podrían considerarse ajenas a ese criterio.

No obstante caben algunas matizaciones a lo anterior, las cuales resultan del análisis del listado de datos que nos ofrece el script:
  • No todos los documentos de procesador de texto son informes o dictámenes. Aunque éstos son la mayoría (60), también tenemos documentos-procesador que son informes de intervenciones de PSC (informes SISE, 8) o de especialistas de apoyo (PT o AL) (14). Incluso otros se recogen documentos ACI-PTI (4), o de otro tipo (incluyendo de evaluación (6).
  • Las hojas de cálculo se ajustan al criterio esperado (recogen procesos de evaluación, las 4)
  • Los PDF, presentan un comportamiento mixto (el esperado), aunque con menos peso como concreción de informes (2/5) frente a documentos de más relacionados con la conformación del expediente (2) o con la evaluación (1).
De lo anterior se deduce que el peso de la evaluación es mayoritario (70%), pero no tanto como podría esperarse de los cómputos iniciales que lo situaba en el 96%).

Cobra importancia en el contenido de los directorios de documento único lo que podríamos llamar intentos fallidos de desarrollo de expedientes (o expedientes degradados o perdidos), que, si interpretamos como tales el sumatorio de documentos diversos, suponen el 38% del total. Podemos poner en duda que impliquen este proyecto (y no un simple guardar para después más simple) los informes SISE de PSC (8), pero no veo motivo para no hacerlo con el registro de informes de otros profesionales, los documentos ACI-PTI y, más aun los documentos de pruebas de evaluación. Todos ellos ascienden a un nada despreciable 30%.

Es posible que tampoco sea acertado considerar todos estos 30 documentos como intentos fallidos de formalizar conscientemente un expediente, pero tampoco podemos considerarlos meros repositorios de documentos disponibles en papel o que, como las pruebas de evaluación, guardarlas digitalizadas implica haber desarrollado previamente un soporte informático. 

En resumen, la realidad se muestra más compleja de lo supuesto al inicio del análisis, aunque, aun así, aquellas suposiciones se cumplen, con menor peso cuantitativo y mayor complejidad de lo previsto, pero se cumple. Hasta el momento.




viernes, 7 de noviembre de 2025

Python. Directorios


Acceso a un directorio




Sintetizo en esta entrada los diferentes modos de acceso a directorios y a su contenido que he ido conociendo mientras buscaba solucionar algunos problemas que implicaban el manejo de directorios. Puede que no sean los únicos disponibles, así que si encuentro alguno más realizaré las modificaciones que correspondan en esta entrada.


Lo que pretendo con ella es exponer los procedimientos más simples y cómo se concretan mediante código; por ello sólo sirven como punto de partida para el logro de objetivos de mayor complejidad o más específicos que lo que implica este planteamiento genérico.

Además algunos procedimientos que aquí se explica es posible que ya hayan sido expuestos en otras entrada, o que se vuelvan a plantear en entradas posteriores a esta. En parte es inevitable dado el carácter básico y genérico que tienen estos procedimiento. Espero, no obstante, que este esfuerzo de síntesis y por facilitar el acceso a código básico compense el trabajo de hacer esta entrada... y de leerla.

Para acceder a los directorios y a contenido necesitamos importar (al menos por ahora) dos bibliotecas básicas de Python, las mismas que he comentado en el inicio de esta subsección: la [biblioteca os] y la [biblioteca pathlib]. Es por ello que debemos importarlas al inicio del script:

import os
from pathlib import Path

También necesitamos identificar la ruta absoluta del directorio con el que deseamos trabajar, en nuestro caso...

directorio = 'D:/BasesDatosTest'

A partir de aquí expongo cada una de las opciones, empezando por la más básica, la que proporciona la función os.listdir()

lista_dir1 = os.listdir(directorio)

print(lista_dir1)

for elem in lista_dir1:

    print(elem)

La primera respuesta que obtenemos (print(lista_dir1)) aplicar esa función (lista_dir1 = os.listdir(directorio)) es un lista de los elementos presentes en el directorio, tanto documentos como subdirectorios...

['ALBOR_emle.pdf', 'BasesDatosPROLECR', 'EXPEDIENTES', 'ITPA-CA', 'TEA_BASIIa.pdf', 'TEA_BASIIb.pdf', 'TEA_InfoDP3.pdf', 'TEA_Matrices.pdf', 'TEA_MatricesManual.pdf', 'WISC_BaseDatos']

... pero si queremos observarla de forma más accesible, podemos utilizar la segunda fórmula, mediante un ciclo que recorre la lista: (for elem in lista_dir1:) -> (print(elem)), nos devuelve...

ALBOR_emle.pdf
BasesDatosPROLECR
EXPEDIENTES
ITPA-CA
TEA_BASIIa.pdf
TEA_BASIIb.pdf
TEA_InfoDP3.pdf
TEA_Matrices.pdf
TEA_MatricesManual.pdf
WISC_BaseDatos

La segunda forma de listar los elementos que componen un directorio pasa por usar la función os.walk(), y presenta la siguiente sintaxis...

for carpeta,subcarpeta, archivo in os.walk(directorio):

    print(carpeta)
    print(subcarpeta)
    print(archivo)

... que devuelve un complejo listado de listas, que a simple vista parece complicado descifrar, pero que con paciencia y trabajo podemos convertir en un sistema funcional de acceder a cualquiera de los diferentes niveles o nodos que contenga y estructure el directorio principal. Aquí únicamente hemos los visualizado. 

D:/BasesDatosTest

['BasesDatosPROLECR', 'EXPEDIENTES', 'ITPA-CA', 'WISC_BaseDatos']

['ALBOR_emle.pdf', 'TEA_BASIIa.pdf', 'TEA_BASIIb.pdf', 'TEA_InfoDP3.pdf', 'TEA_Matrices.pdf', 'TEA_MatricesManual.pdf']

D:/BasesDatosTest\BasesDatosPROLECR

['Prolec_CtCo', 'prolec_r_Completo']

['PROLECComprensionTextos.fmp12', 'PROLECComprensionTextos2.fmp12', 'PROLECComprensionTextos2b.fmp12', 'PROLECComprensionTextual.fmp12', 'PROLECEstructurasGramaticales.fmp12', 'PROLECEstructurasGramaticales2.fmp12']

Este ejemplo es una mínima muestra del conjunto, pero permite observar cómo se han identificado:

  • La estructura y composición del directorio principal (print(carpeta)), su ruta (D:/BasesDatosTest) y las dos colecciones de componentes que contiene:
    • Los subdirectorios (['BasesDatosPROLECR', 'EXPEDIENTES', 'ITPA-CA', 'WISC_BaseDatos'])
    • Y los archivos que se encuentran en el directorio principal

['ALBOR_emle.pdf', 'TEA_BASIIa.pdf', 'TEA_BASIIb.pdf', 'TEA_InfoDP3.pdf', 'TEA_Matrices.pdf', 'TEA_MatricesManual.pdf']

  • Y el segundo nivel, sólo el subdirectorio D:/BasesDatosTest\BasesDatosPROLECR y una mínima parte de lo que contiene...
    • Sus dos subdirectorios secundarios (['Prolec_CtCo', 'prolec_r_Completo'])
    • Y la lista de los documentos que se encuentran ubicados directamente en ese mismo nivel

['PROLECComprensionTextos.fmp12', 'PROLECComprensionTextos2.fmp12', 'PROLECComprensionTextos2b.fmp12', 'PROLECComprensionTextual.fmp12', 'PROLECEstructurasGramaticales.fmp12', 'PROLECEstructurasGramaticales2.fmp12']

Esto nos da una idea de cómo funciona esta función, de la complejidad de la información que aporta y del potencial que tiene su uso en proyecto que requieran, por ejemplo, conocer el contenido y la estructura de directorios complejos.

El tercer modo de obtener información sobre la composición de un directorio implica el uso de la función os.scandir()...

with os.scandir(directorio) as archivos:

    for archivo in archivos:

        print(archivo.name)

... y que, como vemos, requiere el uso de la estructura with (with os.scandir(directorio) as archivos:), a partir de la cual accedemos (aquí sólo con la función de mostrar el contenido del directorio->  print(archivo.name)) mediante un ciclo for que recorre el iterable que resulta de with (archivos -> for archivo in archivos:), gracias al cual obtenemos un resultado...

ALBOR_emle.pdf
BasesDatosPROLECR
EXPEDIENTES
ITPA-CA
TEA_BASIIa.pdf
TEA_BASIIb.pdf
TEA_InfoDP3.pdf
TEA_Matrices.pdf
TEA_MatricesManual.pdf
WISC_BaseDatos

... aparentemente idéntico al que obtenemos con os.listdir() cuando aplicamos un bucle, pero que en realidad contiene otras funcionalidades, ya que con os.scandir() estamos trabajando con objetos, no con cadenas de texto. Es testigo de ello el modo en que se formula la instrucción de impresión (print(archivo.name)), diferente al modo en que se formula desde os.listdir (print(elem))

De hecho os.scandir() permite obtener respuestas similares a las que proporciona la cuarta y última forma de acceder al directorio. Esta es la única de las vistas que emplea la biblioteca pathlib, concretamente su módulo Path. Y también permite obtener un objeto, con las funcionalidades que esto conlleva, y que ahora no podemos apreciar por lo limitado de nuestro objetivo: 

archivos = Path(directorio)

for archivo in archivos.iterdir():

    print(archivo.name)

El interés de esta opción no es tanto el resultado (que es el mismo que la anterior: un listado de elementos (subdirectorios y archivos) como la simplicidad con la que se formula. Por ejemplo, ahora no es necesario usar la estructura with ya que el uso de la función (archivos = Path(directorio)) posibilita identificar a la estructura de contenidos que genera como iterable (for archivo in archivos.iterdir():) en la propia formulación del for.