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?

2

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

3 Comments

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
@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?
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).
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.

Comments

3

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

1 Comment

Not quite what I was hoping for, but it led me to a workable solution, thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.