Simplifying imports?

C

chapolim-colorado

I like to keep my classes each in a separate file with the same name of
the class. The problem with that is that I end up with multiple imports
in the beginning of each file, like this:

from foo.Bar import Bar
from foo.Blah import Blah
from foo.Zzz import Zzz

What I'd like to do would be to replace it all by a single line:

from foo.* import *

Of course, that doesn't work, but is there a way to do something like
that?

Chapolim
 
N

Neal Norwitz

I like to keep my classes each in a separate file with the same name of
the class. The problem with that is that I end up with multiple imports
in the beginning of each file, like this:

from foo.Bar import Bar
from foo.Blah import Blah
from foo.Zzz import Zzz

Must ... resist ... temptation ... to ... complain ... about ... J...
What I'd like to do would be to replace it all by a single line:

from foo.* import *

Of course, that doesn't work, but is there a way to do something like
that?

In foo there is a file __init__.py, right? If you have 3 class files
in foo: bar.py, baz.py, and bax.py, you're __init__.py could contain:

# __init__.py
from foo.bar import Bar
from foo.baz import Baz
from foo.bax import Bax
# end of __init__.py

Then, voila:
['Bar', 'Bax', 'Baz', '__builtins__', '__doc__', '__file__',
'__name__', '__path__', 'bar', 'bax', 'baz']

You could write code in __init__.py to import all the files in foo/ if
you wanted. That way you wouldn't have to explicitly list each file.
(Hint: see os.listdir() and __import__().)

HTH,
n

PS. I don't really like this approach. It seems too implicit
(magical).
 
T

Terry Hancock

I like to keep my classes each in a separate file with the same name of
the class. The problem with that is that I end up with multiple imports
in the beginning of each file, like this:

from foo.Bar import Bar
from foo.Blah import Blah
from foo.Zzz import Zzz

What I'd like to do would be to replace it all by a single line:

from foo.* import *

Of course, that doesn't work, but is there a way to do something like
that?

Apparently "foo" is already a package defined using __init__.py,
so you know about that part already.

Just change its contents to read:

from Bar import Bar
from Blah import Blah
from Zzz import Zzz

Then whenever you need to use these classes, you only need:

from foo import Bar, Blah, Zzz

or

from foo import *

Cheers,
Terry
 
R

Reinhold Birkenfeld

Terry said:
Apparently "foo" is already a package defined using __init__.py,
so you know about that part already.

Just change its contents to read:

from Bar import Bar
from Blah import Blah
from Zzz import Zzz

Then whenever you need to use these classes, you only need:

from foo import Bar, Blah, Zzz

or

from foo import *

Or, if the Bar, Blah and Zzz classes are small enough, there's no need to
put each of them in separate modules. Just put them in foo.py.

Concise structuring of classes and modules is not easy. Structure too much,
and you will not see the wood for the trees. Structure too little, and you
won't find things anymore. IMO, the Twisted project is an example of
excellent Python structuring.

Reinhold
 
C

chapolim-colorado

bruno said:
Let me guess: you have a C++ or Java background ?

You're right, I come from Java :). I'm still learning the Pythonic
approach. Thank you guys

Chapolim
 
G

George Sakkis

Terry Hancock said:
Apparently "foo" is already a package defined using __init__.py,
so you know about that part already.

Just change its contents to read:

from Bar import Bar
from Blah import Blah
from Zzz import Zzz

If you do this often or have lots of classes you want to import this
way, you could automate it:

#======== Foo.py ====================================
class Foo(object):
pass

#======== Bar.py ====================================
class Bar(object):
pass

#======== test.py ====================================
from autoimport import autoimport
autoimport("Foo","Bar")

if __name__ == '__main__':
print Foo
print Bar

# output:
# <class 'Foo.Foo'>
# <class 'Bar.Bar>

#======== autoimport.py ====================================
import sys

def autoimport(*modulenames):
'''
Perform the equivalent of "from XXX import XXX" for every
module XXX in modulenames. In case of packaged modules, it is
equivalent to "from XXX.YYY.ZZZ import ZZZ"
'''
caller_frame = sys._getframe(1)
caller_locals = caller_frame.f_locals
# import every module XXX and add the XXX.XXX object
# to the caller's locals
for name in modulenames:
# in case of packaged modules A.B.C, make sure to import C
module = __import__(name, caller_frame.f_globals,
caller_locals, [name])
# extract 'C' from 'A.B.C'
attribute = name[name.rfind('.')+1:]
if hasattr(module,attribute):
caller_locals[attribute] = getattr(module,attribute)

#==================================================

Or even better, forget about the braindead java restriction of one
class per file and organize your code as it makes more sense to you.

HTH,
George
 
S

Steven D'Aprano

I like to keep my classes each in a separate file with the same name of
the class. The problem with that is that I end up with multiple imports
in the beginning of each file, like this:

from foo.Bar import Bar
from foo.Blah import Blah
from foo.Zzz import Zzz

What I'd like to do would be to replace it all by a single line:

from foo.* import *

Of course, that doesn't work, but is there a way to do something like
that?

"Doctor, it hurts when I do this."

"Then don't do that."

If putting one class per file causes you pain, then don't put one class
per file. The idea of packages is to make things easier for you, not
harder -- if you are having to fight the import mechanism, then perhaps
you need to rethink your design.

eg if you have a good reason for requiring one class per file, then one
possible work around would be to define a single "header" module
containing all those "from foo.Bar import Bar" statements, and then in
your actual module(s) call "from header import *". Watch out for circular
imports though.
 
T

Terry Hancock

Terry Hancock said:
Apparently "foo" is already a package defined using __init__.py,
so you know about that part already.

Just change its contents to read:

from Bar import Bar
from Blah import Blah
from Zzz import Zzz

If you do this often or have lots of classes you want to import this
way, you could automate it:
(nice)

[...]
Or even better, forget about the braindead java restriction of one
class per file and organize your code as it makes more sense to you.

While this is good sound Python advice, there are good Human-readability
reasons for keeping a small number of classes per module. Python classes
certainly may not tend to blossum into the verbosity of their Java
counterparts, but I've still seen some pretty chunky classes (e.g. in
the Zope sources). So, the __init__.py approach and packaging is
still a good idea.

I particularly like the ability of __init__.py to craft the interface
layout of the module, independently of the file-structure that you
choose, as the best layout for the user may not be the best layout
for the developer.

I personally wouldn't favor automating this process unless you are
actually working with some kind of "plugin" design pattern. It's nicer
to have the fine control over the interface and be able to pick and
choose how things should be laid out. And the __init__.py code then
serves as a map for the developer to figure out where things are stored
(yes, they could also use grep, but every little bit helps).
 
G

George Sakkis

Terry Hancock said:
While this is good sound Python advice, there are good Human-readability
reasons for keeping a small number of classes per module. Python classes
certainly may not tend to blossum into the verbosity of their Java
counterparts, but I've still seen some pretty chunky classes (e.g. in
the Zope sources). So, the __init__.py approach and packaging is
still a good idea.

I agree, and that's what I had in mind with "as it makes more sense to
you". Big fat classes _are_ a good reason to keep them in separate
files, if nothing else, for readability reasons. What's braindead is
that java imposes a rule for what should be at best a good style
guideline.

George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top