3

Assume I have this barebones structure:

project/
  main.py
  providers/
    __init.py__
    acme1.py
    acme2.py
    acme3.py
    acme4.py
    acme5.py
    acme6.py

Assume that main.py contains (partial):

if complexcondition():
  print providers.acme5.get()

Where __init__.py is empty and acme*.py contain (partial):

def get():
  value=complexcalculation()
  return value

How do I change these files to work?

Note: If the answer is "import acme1", "import acme2", and so on in __init__.py, is there a way to accomplish that without listing them all by hand?

arantius
  • 1,715
  • 1
  • 17
  • 28
  • 1
    As you have described it should work already... what problems are you having? – David Z Apr 20 '09 at 23:11
  • Duplicate: http://stackoverflow.com/questions/106896/how-many-python-classes-should-i-put-in-one-file; http://stackoverflow.com/questions/171785/how-do-you-organize-python-modules; http://stackoverflow.com/questions/391879/organising-my-python-project – S.Lott Apr 21 '09 at 15:36

3 Answers3

6

hey! two years later but... maybe could be helpfull to some one

make your providers/__init__.py like that:

import os
import glob

module_path = os.path.dirname(__file__)
files = glob.glob(os.path.join(module_path, 'acme*.py'))
__all__ = [os.path.basename(f)[:-3] for f in files]

you don't have to change it later if add or remove any providers/acme*.py

then use from providers import * in main.py

remosu
  • 5,039
  • 1
  • 23
  • 16
  • This introduces 'magic'; i.e. unexpected sideeffects. The mere existance of a file should not cause code execution. This goes against the principle of least surprise, making this a bad idea (tm). -1 – Ondergetekende Sep 19 '12 at 07:11
  • @koert what is wrong with a little of magic? :P In this case the question say: "is there a way to accomplish that without listing them all by hand?"... he is asking for a little of magic, I think. Maybe the files are automaticaly generated and he don't want to edit his code each time a new one appear. How you could accomplish this without magic? – remosu Sep 21 '12 at 09:57
  • You are right, there is no way to accomplish your scenarios without magic. On the other hand, this type of magic is the start of a sysadmin hell (been there, done that). – Ondergetekende Oct 03 '12 at 09:33
5

If I'm reading your question correctly, it looks like you're not trying to do any dynamic importing (like in the question that Van Gale mentioned) but are actually trying to just import all of the modules in the providers package. If that's the case, in __init__.py you would want to have this statement:

__all__ = ["acme1", "acme2", "acme3", "acme4", "acme5", "acme6"]

Then to import everything you would use from ... import *

from providers import *

And then instead of using the package name explicitly in the code, you would just call the imported classes

acme1.get()
acme2.get()

If you have enough modules in the providers package that it becomes a problem populating the __all__ list, you may want to look into breaking them up into smaller packages or storing the data some other way. I personally wouldn't want to have to deal with dynamic importing schennagins every time I wanted to re-use the package.

TwentyMiles
  • 4,063
  • 3
  • 30
  • 37
3

This question asked today, Dynamic Loading of Python Modules, should have your answer.

Community
  • 1
  • 1
Van Gale
  • 43,536
  • 9
  • 71
  • 81