Cómo llamar funciones o clases de otros archivos en Python | De import básico a estructura de paquetes

目次

1. Razones y ventajas de llamar archivos separados en Python

A medida que el programa crece, la división del código se vuelve más importante

Cuando estás empezando a aprender Python, no hay problema en escribir todo el procesamiento en un solo archivo. Sin embargo, a medida que el código aumenta, el procesamiento se vuelve complejo y se hace difícil gestionarlo en un solo archivo.

Por eso, se vuelve importante el enfoque de estructuración dividiendo funciones o clases en archivos separados y llamándolos según sea necesario. De esta manera, el código se vuelve más legible, y la mantenibilidad y la reutilización mejoran considerablemente.

Se puede mejorar la reutilización del código

Por ejemplo, hay muchas operaciones que se desean usar repetidamente en múltiples scripts, como funciones para formatear cadenas o para formatear fechas. Si se agrupan estas operaciones en un archivo separado, se pueden usar fácilmente en otros scripts simplemente importándolos.

# Definido en utils.py
def format_date(date):
    return date.strftime('%Y-%m-%d')

# Llamado desde main.py
from utils import format_date

De esta manera, el código escrito una vez se puede reutilizar cuantas veces sea necesario, lo que aumenta drásticamente la eficiencia del trabajo.

Mejora de la mantenibilidad y la legibilidad

Si se escribe todo el procesamiento en un solo archivo, cuando ocurre un error, es difícil identificar la causa. Además, resulta difícil de entender para otras personas que leen el código.

Si se divide y gestiona los archivos por funcionalidad,

  • «El procesamiento de base de datos en este archivo»
  • «La validación de entrada de usuario en este archivo»

de esta manera, la responsabilidad se vuelve clara.

Como resultado,

  • La corrección de errores se acelera
  • En el desarrollo en equipo, se reducen los conflictos
  • Se facilita la revisión de código

se obtienen estas ventajas.

Habilidad esencial para proyectos serios

En casos como la creación de aplicaciones web con Python o proyectos que gestionan múltiples modelos de aprendizaje automático, la división de archivos para organizar funciones es lo básico de lo básico. Incluso al usar frameworks (como Django o FastAPI), es un requisito entender la estructura de directorios y el concepto de importación.

Por lo tanto, incluso para principiantes en Python, «el método para llamar funciones o clases desde archivos separados» es un conocimiento que se debe adquirir en una etapa temprana.

2. Uso básico de la sentencia import en Python

¿Qué es la sentencia import?

En Python, cuando quieres usar funciones o clases de otros archivos (módulos), se utiliza la import sentencia.
Al usarla, puedes llamar a los procesos definidos en archivos separados como si estuvieran en el archivo actual.

En Python, con este mecanismo puedes cargar funciones de la biblioteca estándar o usar módulos creados por ti mismo.

Importación básica de archivos en la misma carpeta

La forma más básica de uso es importar otro archivo en el mismo directorio.

Por ejemplo, consideremos una estructura como la siguiente.

project/
├── main.py
└── utils.py

Si quieres usar una función definida en utils.py desde main.py, descríbela de la siguiente manera.

# utils.py
def greet(name):
    return f"¡Hola, {name}!"
# main.py
import utils

print(utils.greet("Sagawa"))

De esta manera, simplemente especificando el nombre del archivo, puedes usar las funciones o variables dentro de él.
Cuando accedes a la función, descríbela en el formato «nombre_del_módulo.nombre_de_función».

Sintaxis from-import para cargar solo funciones específicas

Si solo quieres usar una función específica, puedes describirlo en el formato from nombre_del_módulo import nombre_de_función.

# main.py
from utils import greet

print(greet("Sagawa"))

De esta manera, puedes escribir utils.greet() no, sino greet() de forma simple.

Además, para importar varias funciones a la vez, puedes describirlas separadas por comas.

from utils import greet, farewell

Usar alias (nombre alternativo) en import

Si el nombre del módulo es largo o quieres simplificarlo, puedes especificar un alias (nombre alternativo) usando as.

import utils as ut

print(ut.greet("Sagawa"))

De esta manera, puedes mantener el código conciso y evitar conflictos con otros módulos.

Presta atención al lugar donde escribes la sentencia import

En Python, básicamente se recomienda escribir la import sentencia al principio del archivo.
Sin embargo, en casos excepcionales donde solo se necesita en un momento específico para usar ciertas bibliotecas, también es posible escribirla dentro de una función.

def use_numpy_temporarily():
    import numpy as np
    return np.array([1, 2, 3])

Sin embargo, considerando la legibilidad y el mantenimiento, básicamente es la mejor práctica describirlas todas al principio.

RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

3. Llamada de archivos desde subdirectorios u otras carpetas

En Python, el método de importación cambia según la estructura de carpetas

En Python, cuando los scripts se dividen en múltiples carpetas, surgen casos en los que no se puede leer el archivo con una simple instrucción import.
En esos casos, es necesario especificar la ruta correcta y entender el mecanismo.

En esta sección, se explica cómo llamar funciones y clases de archivos en subdirectorios u otras carpetas, con ejemplos concretos.

Importar archivos de subdirectorios

Primero, asumamos una estructura de directorios como la siguiente.

project/
├── main.py
└── tools/
    └── formatter.py

formatter.py Si se desea llamar una función de main.py, básicamente se escribe de la siguiente manera.

# tools/formatter.py
def shout(text):
    return text.upper() + "!"
# main.py
from tools import formatter

print(formatter.shout("hello"))

O, si solo se desea usar la función:

from tools.formatter import shout

print(shout("hello"))

De esta manera, para llamar archivos de subdirectorios, se especifica con la sintaxis «nombre_del_directorio.nombre_del_archivo».

Para tratarlo como un paquete, a veces se necesita init.py

En Python antiguo (3.2 o anterior) o en algunas herramientas, para que el subdirectorio sea reconocido como un módulo (paquete), se necesita __init__.py.

tools/
├── __init__.py
└── formatter.py

En este caso, basta con colocar un archivo __init__.py vacío. No es obligatorio en Python 3.3 o posterior, pero es recomendable incluirlo para mayor seguridad.

Importar archivos de directorios padre o carpetas hermanas

Ahora, consideremos el caso de llamar archivos de otra carpeta. Pensemos en una estructura como la siguiente:

project/
├── main.py
└── modules/
    └── helper.py

En este caso, Python no busca por defecto en el directorio modules/, por lo que se necesitan medidas como las siguientes.

Medida ①: Agregar la ruta usando sys.path

# main.py
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'modules'))

import helper

print(helper.some_function())

De esta manera, se puede agregar una carpeta arbitraria a la ruta de búsqueda de módulos de Python.
Es especialmente efectivo cuando se ejecuta el script desde la raíz del proyecto.

Medida ②: Prestar atención a la ubicación de ejecución de Python

La importación de Python se ve afectada por el lugar de ejecución (directorio actual).
main.py Se está ejecutando dentro del directorio project/, o desde modules/, lo que puede cambiar el éxito o fracaso de la importación.

# Método de ejecución correcto
cd project
python main.py

Además, en editores como VSCode, la acción del botón «Ejecutar como archivo Python» puede afectar la ruta de ejecución del script, por lo que se debe tener cuidado.

Prestar atención a la diferencia entre rutas absolutas y relativas

  • from modules.helper import func Una descripción como esta es una importación absoluta
  • from ..modules import helper Una descripción como esta es una importación relativa

La importación relativa es conveniente, pero tiende a generar errores dependiendo de la ubicación del archivo de ejecución.
Básicamente, se recomienda usar importaciones absolutas.

4. Diferencia y uso entre importación relativa e importación absoluta

Hay dos tipos de import en Python

Al llamar a otro archivo en Python, hay principalmente dos métodos.

  • Importación absoluta (absolute import)
  • Importación relativa (relative import)

Estos dos tienen el mismo propósito, pero difieren en la forma de escribirlos y en su uso, por lo que es importante usarlos correctamente según la situación.

¿Qué es la importación absoluta?

La importación absoluta es un método para especificar módulos usando la ruta desde el directorio raíz del proyecto. Es la forma más común y recomendada en muchos proyectos.

from tools.formatter import shout

Como se muestra arriba, se especifica en el formato «nombre_directorio.nombre_archivo.nombre_función».

Ventajas

  • Fácil de leer y claro
  • Funciona de manera estable incluso si cambia el entorno de ejecución
  • Fácil para otros desarrolladores entender la estructura

Desventajas

  • Puede volverse largo (complicado en jerarquías profundas)

¿Qué es la importación relativa?

La importación relativa es un método para especificar módulos basándose en la posición del archivo actual. Se usa principalmente para llamar módulos internos dentro de un paquete.

from . import formatter          # Mismo directorio
from ..tools import formatter   # Un directorio arriba

. (punto) indica el directorio actual, .. (dos puntos) indica el directorio un nivel arriba.

Ventajas

  • La relación dentro del paquete es clara
  • Permite movimiento flexible dentro del mismo paquete

Desventajas

  • Fácil de generar errores dependiendo de la posición del archivo de ejecución
  • No adecuado para scripts ejecutados directamente desde el exterior
  • Se vuelve difícil de leer en configuraciones complejas

¿Cuál usar? Cómo diferenciar en la práctica

En general, la documentación oficial de Python también recomienda lo siguiente:

  • Cuando se asume que se llama desde el exterior de la biblioteca o proyecto: importación absoluta
  • Para enlaces simples de módulos dentro del paquete: importación relativa

Además, para principiantes o proyectos pequeños a medianos, usar importación absoluta como base reduce los problemas.

Ejemplo de error real: ¿La importación relativa no funciona?

# example.py (ejecutado de forma independiente)
from .module import func  # ValueError: attempted relative import beyond top-level package

Como se muestra arriba, la importación relativa puede generar un error cuando se ejecuta como un script independiente.
Esto se debe a que Python no reconoce ese archivo como un paquete.

En este caso, se puede evitar ejecutándolo como un módulo de la siguiente manera.

python -m package.module

Conclusión: básicamente importación absoluta, relativa según la situación

  • Básicamente importación absoluta (simple y claro, resistente al uso desde el exterior)
  • Usar importación relativa solo cuando hay muchas referencias dentro del mismo paquete

La importación relativa es conveniente, pero tiende a ser inestable dependiendo del método de ejecución del script o el entorno de desarrollo, por lo que es importante discernir su uso.

5. Empaquetado para la gestión de módulos

Para organizar múltiples archivos, el «empaquetado» es efectivo

Al desarrollar programas a gran escala en Python, es muy importante dividir y organizar adecuadamente los archivos.
En este momento, el concepto útil es el de «empaquetado».

Un paquete es una colección de módulos (archivos Python) organizada por directorio. Al agrupar múltiples funciones, la legibilidad, el mantenimiento y la reutilización mejoran considerablemente.

El rol de init.py

En el directorio que constituye el paquete, en principio, es necesario colocar un archivo llamado __init__.py.

project/
└── tools/
    ├── __init__.py
    └── formatter.py

Este __init__.py es un marcador para que reconozca ese directorio como «un paquete para Python».
El contenido puede estar vacío, pero también se puede escribir el procesamiento de inicialización del módulo como a continuación, o especificar explícitamente las funciones a exponer externamente.

# tools/__init__.py
from .formatter import shout

De esta manera, el lado que llama puede importar de manera concisa como se muestra a continuación.

from tools import shout

Ejemplo de estructura de directorios

Veamos un ejemplo de la estructura de un proyecto empaquetado.

my_project/
├── main.py
└── tools/
    ├── __init__.py
    ├── formatter.py
    └── validator.py

En este caso, todos los módulos bajo tools se pueden llamar desde main.py.

# main.py
from tools import formatter, validator

print(formatter.shout("Hello"))
print(validator.is_valid("12345"))

Resumen de los beneficios del empaquetado

VentajasContenido
Estructura fácil de gestionarSe pueden organizar los archivos por función, mejorando la visibilidad
Se evitan colisiones de nombresSe reduce la superposición de nombres de módulos
Reutilización más fácilSe puede reutilizar el paquete completo en otros proyectos
Pruebas unitarias y automatización más fácilesEs más fácil dividir las pruebas por módulo

Desde Python 3.3, ¿es opcional init.py?

Desde Python 3.3, se puede tratar un directorio como paquete incluso sin __init__.py (Implicit Namespace Package).
Sin embargo, en la práctica, se recomienda incluir __init__.py por las siguientes razones.

  • Algunas herramientas o bibliotecas no lo soportan
  • A veces se desea realizar un procesamiento de inicialización explícito dentro del paquete
  • Mejora la legibilidad y la claridad (es más comprensible para los humanos)

Por lo tanto, usar __init__.py sigue siendo la mejor práctica estándar de la industria.

6. Errores comunes de importación y cómo manejarlos

Las razones por las que fallan las importaciones suelen ser la falta de comprensión de las rutas y la estructura

Al intentar llamar a otro archivo en Python, «el módulo no se encuentra» «el nombre no está definido» u otros errores similares es una experiencia por la que pasan muchos principiantes.

Aquí introducimos específicamente los errores comunes de importación y cómo manejarlos.

ModuleNotFoundError: No se encuentra el módulo

Ejemplo de error:

ModuleNotFoundError: No module named 'utils'

Causa y solución:

Este error ocurre cuando el módulo especificado no existe en la ruta de búsqueda de Python. Las causas comunes son las siguientes:

  • El archivo objetivo de importación no existe en el mismo directorio o en la posición adecuada
  • La ubicación del archivo que se está ejecutando no coincide con la estructura del paquete
  • sys.path no incluye la ruta del módulo

Solución:

  1. Verificar la ruta donde existe el módulo
  2. Unificar el directorio de ejecución en la raíz
  3. Si es necesario, agregar la ruta con sys.path.append()
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'modules'))

ImportError: El módulo existe pero no se puede cargar su contenido

Ejemplo de error:

ImportError: cannot import name 'greet' from 'utils'

Causa y solución:

Este error ocurre cuando el módulo en sí se encuentra, pero no se encuentra la función, clase, variable u otro elemento especificado.

Causas principales:

  • Error de tipeo en el nombre del archivo
  • En realidad, no existe una función o clase con ese nombre
  • En __init__.py no se ha escrito from .module import greet, por lo que no es visible desde fuera

Solución:

  • Verificar si el nombre especificado existe correctamente dentro del módulo
  • Prestar atención a mayúsculas y minúsculas (Python las distingue)
  • Especificar explícitamente los elementos a publicar en __init__.py

Errores de importación relativa: ValueError o ImportError

Ejemplo de error:

ValueError: attempted relative import beyond top-level package

Causa:

Este error ocurre cuando se ejecuta directamente un archivo que usa importación relativa. Python, al ejecutarlo de forma independiente, no lo reconoce como parte de un paquete.

Solución:

  • Si se usa importación relativa, es necesario ejecutarlo como módulo.
# NG: Ejecución directa
python script.py

# OK: Ejecución como módulo
python -m package.script

Mejores prácticas para evitar errores de importación

PuntosExplicación
Unificar la ubicación de ejecución de los scriptsproject/ como raíz, y configurar el «directorio de trabajo» en VSCode, etc.
Escribir las sentencias import con rutas absolutasEspecialmente para principiantes, es más seguro evitar importaciones relativas
__init__.py para configurar explícitamenteEl reconocimiento del paquete se vuelve seguro
Si se agrega sys.path temporalmente, especificar dinámicamente con os.pathSe puede evitar fallos de funcionamiento debido a diferencias en el entorno

7. Ejemplo de código práctico: Intentemos llamar y usar una función de un archivo diferente

Entendámoslo practicando realmente

Con la explicación hasta aquí, creo que has adquirido los conocimientos básicos para llamar archivos separados en Python.
Sin embargo, «entender» y «poder usar» son cosas diferentes.

En esta sección, mientras movemos las manos en la práctica,

  • la división de archivos
  • la forma de usar la sentencia import
  • la forma de llamar funciones
    aprendámoslo.

Paso 1: Crear el archivo con la función que se va a llamar

Primero, creamos el archivo Python del lado que se llama.

project/
├── main.py
└── utils.py

utils.py , definimos una función simple.

# utils.py

def greet(name):
    return f"¡Hola, {name}!"

En este archivo, se define una función llamada greet().
Es una función simple que toma un nombre como argumento y devuelve un mensaje de saludo.

Paso 2: Importar desde el archivo de origen de la llamada

A continuación, creamos main.py, que realiza el procesamiento principal.

# main.py

import utils

message = utils.greet("Sagawa")
print(message)

De esta manera, importamos el módulo utils con import y llamamos la función greet() dentro de él.
Aquí, lo usamos en la forma de nombre del módulo + nombre de la función.

Paso 3: Ejecutar y confirmar el resultado

A continuación, ejecutemos main.py desde la terminal o el símbolo del sistema.

python main.py

Resultado de salida:

¡Hola, Sagawa!

La función del archivo separado se llamó exitosamente y se mostró el mensaje previsto.

Probemos otro método de importación (from-import)

Al reescribirlo como a continuación, también es posible llamar la función de manera más concisa.

# main.py(versión mejorada)

from utils import greet

print(greet("Sagawa"))

Con este método, en lugar de utils.greet(), se puede escribir simplemente greet().

Además, si se desean usar múltiples funciones, enumérelas separadas por comas.

Un consejo para organizar el código

  • Procesos comunes como utils.py se pueden agrupar en directorios como «modules» o «helpers» para facilitar la gestión.
  • A nivel profesional, organizar la estructura de directorios contribuye a mejorar la legibilidad y el mantenimiento.

8. FAQ: Preguntas frecuentes sobre la llamada a archivos separados en Python

Q1. import y from ... import ..., ¿cuál es la diferencia?

A.
Ambas son métodos para cargar archivos separados, pero difieren en la forma de llamarlos.

  • import module: Carga todo el módulo y se usa como module.function().
  • from module import function: Carga solo funciones o clases específicas y se puede llamar directamente como function().

Cuando se usan múltiples funciones o se quiere mostrar explícitamente qué funciones se están usando, from ... import ... es conveniente.

Q2. La importación relativa no funciona correctamente. ¿Por qué?

A.
La importación relativa puede generar errores cuando se ejecuta el módulo de forma independiente. Esto se debe a que Python no reconoce el archivo como parte de un paquete.

Se puede evitar ejecutándolo como módulo de la siguiente manera.

python -m package.module

Además, para principiantes se recomienda usar importaciones absolutas. Son más estables y menos propensas a problemas.

Q3. Me confundo con cómo estructurar los archivos en Python

A.
Básicamente, se recomienda dividir directorios o módulos por funcionalidad de la siguiente manera.

project/
├── main.py
├── utils/
│   ├── __init__.py
│   ├── formatter.py
│   └── validator.py
└── config/
    └── settings.py
  • Si hay múltiples funciones, divide el archivo
  • Agrupa el procesamiento común en «utils» o «common»
  • Al empaquetar por directorios, es más fácil extenderlo

Q4. ¿Es __init__.py estrictamente necesario?

A.
Desde Python 3.3, funciona como paquete incluso sin __init__.py (Implicit Namespace Package).
Sin embargo, aún se recomienda usarlo por las siguientes razones.

  • Se reconoce explícitamente como paquete
  • Es obligatorio para herramientas antiguas o algunos editores
  • Se puede usar para inicialización o configuración de funciones públicas

Dado que se usa ampliamente en equipos de desarrollo y desarrollo comercial, básicamente es más seguro instalarlo siempre.

Q5. ¿Se pueden usar nombres de archivo con japonés o caracteres especiales al importar?

A.
Básicamente, los nombres de módulos (nombres de archivo) deben usar solo letras inglesas, números y guiones bajos (_).

Por ejemplo, los siguientes nombres de archivo no son válidos:

  • función.py
  • utils-mod.py

En Python, el nombre del archivo se convierte directamente en el nombre del módulo, por lo que los caracteres especiales o guiones causan errores.

Ejemplos de nomenclatura correcta:

  • utils.py
  • data_handler.py

9. Resumen: Entender import hace que Python sea más libre

Repaso de lo aprendido en este artículo

En este artículo hasta ahora, hemos explicado paso a paso contenidos como los siguientes:

  • ¿Por qué llamar archivos separados?
    → Para organizar el código y hacerlo reutilizable
  • La forma básica de usar la instrucción import
    → La distinción entre import / from ... import ...
  • Cómo cargar módulos de subdirectorios o carpetas diferentes
    → Entender el manejo de rutas y la necesidad de __init__.py
  • La diferencia entre importación absoluta e importación relativa
    → Para principiantes, se recomienda la importación absoluta
  • Errores comunes de importación y cómo solucionarlos
    → La mayoría de las causas de errores son problemas de ruta de ejecución y configuración
  • Verificación con código práctico y suplemento en FAQ
    → Cobertura de teoría + práctica + preguntas frecuentes

Si dominas import, el mundo de Python se expande de inmediato

Al entender el mecanismo de import y usarlo correctamente, obtendrás las siguientes ventajas:

  • Puedes crear estructuras que no te confundan ni en proyectos a gran escala
  • Resumir procesos comunes hace que el mantenimiento y las modificaciones sean más fáciles
  • Es más fácil entender código escrito por otros
  • Podrás manejar bibliotecas y frameworks (Django, Flask, FastAPI, etc.) de manera natural

En otras palabras, entender import es como la puerta de entrada para avanzar más allá del nivel de principiante.

En conclusión

Python es atractivo por su sintaxis simple y flexibilidad, pero por eso mismo es un lenguaje que exige «habilidades de diseño».
Al entender correctamente cómo llamar archivos separados y dominar módulos y paquetes, tu código evolucionará significativamente.

Espero que este artículo sea de ayuda para tu aprendizaje de Python o desarrollo profesional.
Por favor, practica creando tu propia estructura de módulos.