Importando clases de diferentes archivos en un subdirectorio

Aquí está la estructura con la que estoy trabajando:

directory/ script.py subdir/ __init__.py myclass01.py myclass02.py 

Lo que quiero hacer es importar en script.py las clases definidas en myclass01.py y myclass02.py . Si lo hago:

 from subdir.myclass01 import * 

Funciona bien para la clase definida en myclass01.py . Pero con esta solución, si hay muchas clases definidas en diferentes archivos en subdir y quiero importarlas todas, tendré que escribir una línea para cada archivo. Debe haber un atajo para esto. Lo intenté:

 from subdir.* import * 

Pero no funcionó.

EDITAR : aquí están los contenidos de los archivos:

Esto es __init__.py (usando __all__ como sugirió Apalala):

 __all__ = ['MyClass01','MyClass02'] 

Esta es myclass01.py :

 class MyClass01: def printsomething(): print 'hey' 

Esta es myclass02.py :

 class MyClass02: def printsomething(): print 'sup' 

Esto es script.py :

 from subdir import * MyClass01().printsomething() MyClass02().printsomething() 

Este es el rastreo que recibo cuando bash ejecutar script.py :

 File "script.py", line 1, in  from subdir import * AttributeError: 'module' object has no attribute 'MyClass01' 

Aunque los nombres utilizados allí son diferentes de lo que se muestra en la estructura de directorios de su pregunta, puede usar mi respuesta a la pregunta titulada Espacios de nombres y clases . El __init__.py muestra allí también habría permitido que el script usepackage.py se haya escrito de esta manera (el package subdir en su pregunta y Class1 a myclass01 , etc.):

 from package import * print Class1 print Class2 print Class3 

Revisión (actualizada):

Vaya, lo siento, el código en mi otra respuesta no hace exactamente lo que quieres, solo importa automáticamente los nombres de los submódulos de cualquier paquete. Para que también importe los atributos nombrados de cada submódulo se requieren algunas líneas más de código. Aquí hay una versión modificada del archivo __init__.py del paquete (que también funciona en Python 3.4.1):

 def _import_package_files(): """ Dynamically import all the public attributes of the python modules in this file's directory (the package directory) and return a list of their names. """ import os exports = [] globals_, locals_ = globals(), locals() package_path = os.path.dirname(__file__) package_name = os.path.basename(package_path) for filename in os.listdir(package_path): modulename, ext = os.path.splitext(filename) if modulename[0] != '_' and ext in ('.py', '.pyw'): subpackage = '{}.{}'.format(package_name, modulename) # pkg relative module = __import__(subpackage, globals_, locals_, [modulename]) modict = module.__dict__ names = (modict['__all__'] if '__all__' in modict else [name for name in modict if name[0] != '_']) # all public exports.extend(names) globals_.update((name, modict[name]) for name in names) return exports if __name__ != '__main__': __all__ = ['__all__'] + _import_package_files() # '__all__' in __all__ 

Alternativamente, puede colocar lo anterior en un archivo de módulo .py propio en el directorio del paquete, y usarlo desde el __init__.py del paquete de la __init__.py manera:

 if __name__ != '__main__': from ._import_package_files import * # defines __all__ __all__.remove('__all__') # prevent export (optional) 

Cualquiera que sea el nombre del archivo, debe ser algo que comience con un carácter de subrayado _ para que no intente import forma recursiva.

Su mejor opción, aunque probablemente no sea el mejor estilo, es importar todo al espacio de nombres del paquete:

 # this is subdir/__init__.py from myclass01 import * from myclass02 import * from myclass03 import * 

Luego, en otros módulos, puede importar lo que quiera directamente del paquete:

 from subdir import Class1 

Sé que han pasado un par de meses desde que se respondió esta pregunta, pero estaba buscando lo mismo y corrí a través de esta página. No estaba muy satisfecho con la respuesta elegida, así que terminé escribiendo mi propia solución y pensé en compartirla. Esto es lo que se me ocurrió:

 # NOTE: The function name starts with an underscore so it doesn't get deleted by iself def _load_modules(attr_filter=None): import os curdir = os.path.dirname(__file__) imports = [os.path.splitext(fname)[0] for fname in os.listdir(curdir) if fname.endswith(".py")] pubattrs = {} for mod_name in imports: mod = __import__(mod_name, globals(), locals(), ['*'], -1) for attr in mod.__dict__: if not attr.startswith('_') and (not attr_filter or attr_filter(mod_name, attr)): pubattrs[attr] = getattr(mod, attr) # Restore the global namespace to it's initial state for var in globals().copy(): if not var.startswith('_'): del globals()[var] # Update the global namespace with the specific items we want globals().update(pubattrs) # EXAMPLE: Only load classes that end with "Resource" _load_modules(attr_filter=lambda mod, attr: True if attr.endswith("Resource") else False) del _load_modules # Keep the namespace clean 

Esto simplemente importa * de todos los archivos .py en el directorio del paquete y luego solo saca los públicos en el espacio de nombres global. Además, permite un filtro si solo se desean ciertos atributos públicos.

Yo uso esta manera simple:

  1. agregar el directorio a la ruta del sistema, luego
  2. import module o from module import function1, class1 en ese directorio.

Observe que el module no es más que el nombre de su archivo *.py , sin la parte de extensión.

Aquí hay un ejemplo general:

 import sys sys.path.append("/path/to/folder/") import module # in that folder 

En tu caso podría ser algo como esto:

 import sys sys.path.append("subdir/") import myclass01 # or from myclass01 import func1, class1, class2 # .. etc 
 from subdir.* import * 

No puede usar ‘*’ de esta manera directamente después de la statement ‘from’. Necesitas importaciones explícitas. Consulte la documentación de Python sobre importaciones y paquetes.