¿Cómo cargar todos los módulos en una carpeta?

¿Podría alguien proporcionarme una buena manera de importar un directorio completo de módulos?
Tengo una estructura como esta:

/Foo bar.py spam.py eggs.py 

Intenté simplemente convertirlo en un paquete agregando __init__.py y haciendo from Foo import * pero no funcionó como esperaba.

Liste todos los archivos de python ( .py ) en la carpeta actual y __all__ como la variable __init__.py en __init__.py

 from os.path import dirname, basename, isfile import glob modules = glob.glob(dirname(__file__)+"/*.py") __all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')] 

Agregue la variable __init__.py a __init__.py contiene:

 __all__ = ["bar", "spam", "eggs"] 

Consulte también http://docs.python.org/tutorial/modules.html

Actualización: hoy probablemente quieras usar importlib en importlib lugar.

Convierta el directorio de Foo en un paquete agregando un __init__.py . En ese __init__.py agregar:

 import bar import eggs import spam 

Ya que lo quieres dynamic (lo que puede o no ser una buena idea), enumera todos los archivos py con list dir y los importa con algo como esto:

 import os for module in os.listdir(os.path.dirname(__file__)): if module == '__init__.py' or module[-3:] != '.py': continue __import__(module[:-3], locals(), globals()) del module 

Luego, desde tu código haz esto:

 import Foo 

Ahora puedes acceder a los módulos con

 Foo.bar Foo.eggs Foo.spam 

etc. de Foo import * no es una buena idea por varias razones, incluidos los conflictos de nombres y dificultar el análisis del código.

Ampliando la respuesta de Mihail, creo que la forma no hacker (como en, no manejar las rutas de archivo directamente) es la siguiente:

  1. crear un archivo __init__.py vacío bajo Foo/
  2. Ejecutar
 import pkgutil import sys def load_all_modules_from_dir(dirname): for importer, package_name, _ in pkgutil.iter_modules([dirname]): full_package_name = '%s.%s' % (dirname, package_name) if full_package_name not in sys.modules: module = importer.find_module(package_name ).load_module(full_package_name) print module load_all_modules_from_dir('Foo') 

Obtendrás:

   

Python, incluye todos los archivos en un directorio:

Para los novatos que simplemente no pueden hacerlo funcionar y necesitan que les tomen las manos.

  1. Haga una carpeta / home / el / foo y haga un archivo main.py bajo / home / el / foo Coloque este código allí:

     from hellokitty import * spam.spamfunc() ham.hamfunc() 
  2. Hacer un directorio /home/el/foo/hellokitty

  3. Haga un archivo __init__.py bajo /home/el/foo/hellokitty y ponga este código allí:

     __all__ = ["spam", "ham"] 
  4. Haga dos archivos de python: spam.py y ham.py bajo /home/el/foo/hellokitty

  5. Define una función dentro de spam.py:

     def spamfunc(): print "Spammity spam" 
  6. Define una función dentro de ham.py:

     def hamfunc(): print "Upgrade from baloney" 
  7. Ejecutarlo:

     el@apollo:/home/el/foo$ python main.py spammity spam Upgrade from baloney 

Me cansé de este problema, así que escribí un paquete llamado automodinit para solucionarlo. Puede obtenerlo en http://pypi.python.org/pypi/automodinit/ .

El uso es así:

  1. Incluya el paquete automodinit en sus dependencias setup.py .
  2. Reemplace todos los archivos __init__.py como este:
 __all__ = ["Me reescribirán"]
 # ¡No modifique la línea de arriba, o esta línea!
 importar automodinit
 automodinit.automodinit (__ name__, __file__, globals ())
 del automodinit
 # Cualquier cosa que quieras puede ir después, no se modificará.

¡Eso es! A partir de ahora, la importación de un módulo establecerá __all__ a una lista de archivos .py [co] en el módulo y también importará cada uno de esos archivos como si hubiera escrito:

 for x in __all__: import x 

Por lo tanto, el efecto de “from M import *” coincide exactamente con “import M”.

automodinit está feliz ejecutándose desde dentro de archivos ZIP y, por lo tanto, es seguro para ZIP.

Niall

Sé que estoy actualizando una publicación bastante antigua, e intenté usar automodinit , pero descubrí que el proceso de configuración está roto para python3. Entonces, basado en la respuesta de Luca, se me ocurrió una respuesta más simple, que podría no funcionar con .zip, para este problema, así que pensé que debería compartirlo aquí:

dentro del módulo yourpackage de su yourpackage :

 #!/usr/bin/env python import os, pkgutil __all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)])) 

y dentro de otro paquete debajo de su paquete:

 from yourpackage import * 

Luego, tendrá cargados todos los módulos que están colocados dentro del paquete, y si escribe un nuevo módulo, también se importará automáticamente. Por supuesto, usar ese tipo de cosas con cuidado, con grandes poderes conlleva grandes responsabilidades.

También he encontrado este problema y esta fue mi solución:

 import os def loadImports(path): files = os.listdir(path) imps = [] for i in range(len(files)): name = files[i].split('.') if len(name) > 1: if name[1] == 'py' and name[0] != '__init__': name = name[0] imps.append(name) file = open(path+'__init__.py','w') toWrite = '__all__ = '+str(imps) file.write(toWrite) file.close() 

Esta función crea un archivo (en la carpeta provista) llamado __init__.py , que contiene una variable __all__ que contiene todos los módulos de la carpeta.

Por ejemplo, tengo una carpeta llamada Test que contiene:

 Foo.py Bar.py 

Así que en el script quiero que se importen los módulos en los que escribiré:

 loadImports('Test/') from Test import * 

Esto importará todo desde la Test y el archivo __init__.py en la Test ahora contendrá:

 __all__ = ['Foo','Bar'] 

El ejemplo de Anurag con un par de correcciones:

 import os, glob modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py")) __all__ = [os.path.basename(f)[:-3] for f in modules if not f.endswith("__init__.py")] 

Anurag Uniyal responde con mejoras sugeridas!

 #!/usr/bin/python # -*- encoding: utf-8 -*- import os import glob all_list = list() for f in glob.glob(os.path.dirname(__file__)+"/*.py"): if os.path.isfile(f) and not os.path.basename(f).startswith('_'): all_list.append(os.path.basename(f)[:-3]) __all__ = all_list 
 import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'): __import__(module) 

Comprueba que tu __init__.py defina __all__ . Los módulos – paquetes doc dice

Los archivos __init__.py son necesarios para que Python trate los directorios como paquetes que contienen; esto se hace para evitar que los directorios con un nombre común, como una cadena, oculten involuntariamente los módulos válidos que aparecen más adelante en la ruta de búsqueda del módulo. En el caso más simple, __init__.py solo puede ser un archivo vacío, pero también puede ejecutar el código de inicialización del paquete o establecer la variable __all__ , que se describe más adelante.

La única solución es que el autor del paquete proporcione un índice explícito del paquete. La statement de importación usa la siguiente convención: si el código __init__.py un paquete define una lista llamada __all__ , se considera la lista de nombres de módulos que deben importarse cuando se encuentra desde la importación de paquetes *. Depende del autor del paquete mantener esta lista actualizada cuando se lance una nueva versión del paquete. Los autores de paquetes también pueden decidir no admitirlo, si no ven un uso para importar * de su paquete. Por ejemplo, el archivo sounds/effects/__init__.py podría contener el siguiente código:

__all__ = ["echo", "surround", "reverse"]

Esto significaría que from sound.effects import * importaría los tres submódulos nombrados del paquete de sonido.

Esta es la mejor manera que he encontrado hasta ahora:

 from os.path import dirname, join, isdir, abspath, basename from glob import glob pwd = dirname(__file__) for x in glob(join(pwd, '*.py')): if not x.startswith('__'): __import__(basename(x)[:-3], globals(), locals()) 

Mira el módulo pkgutil de la biblioteca estándar. Le permitirá hacer exactamente lo que quiera, siempre y cuando tenga un archivo __init__.py en el directorio. El archivo __init__.py puede estar vacío.

He creado un módulo para eso, que no se basa en __init__.py (ni en ningún otro archivo auxiliar) y me hace escribir solo las siguientes dos líneas:

 import importdir importdir.do("Foo", globals()) 

Siéntase libre de reutilizar o contribuir: http://gitlab.com/aurelien-lourot/importdir

Solo impórtelos por importlib y agréguelos a __all__ (la acción de add es opcional) en recurse en el __init__.py del paquete.

 /Foo bar.py spam.py eggs.py __init__.py # __init__.py import os import importlib pyfile_extes = ['py', ] __all__ = [importlib.import_module('.%s' % filename, __package__) for filename in [os.path.splitext(i)[0] for i in os.listdir(os.path.dirname(__file__)) if os.path.splitext(i)[1] in pyfile_extes] if not filename.startswith('__')] del os, importlib, pyfile_extes