tags:

views:

429

answers:

2

My package have the following structure:

mobilescouter/
    __init__.py #1
    mapper/
        __init__.py  #2
        lxml/
            __init__.py #3
            vehiclemapper.py
            vehiclefeaturemapper.py
            vehiclefeaturesetmapper.py
        ...
        basemapper.py
   vehicle/
        __init__.py #4
        vehicle.py
        vehiclefeature.py
        vehiclefeaturemapper.py
   ...

I'm always not sure how the __init__.py files are written good and correctly.
The __init__.py #1 looks like:

__all__ = ['mapper', 'vehicle']
import mapper
import vehicle

But how should for example __init__.py #2 look like? Mine is:

__all__ = ['basemapper', 'lxml']
from basemaper import *
import lxml

Is it recommend to use __all__?

+15  A: 

My own __init__.py files are empty more often than not. In particular, I never have a from blah import * as part of __init__.py -- if "importing the package" means getting all sort of classes, functions etc defined directly as part of the package, then I would lexically copy the contents of blah.py into the package's __init__.py instead and remove blah.py (the multiplication of source files does no good here).

If you do insist on supporting the import * idioms (eek), then using __all__ (with as miniscule a list of names as you can bring yourself to have in it) may help for damage control. In general, namespaces and explicit imports are good things, and I strong suggest reconsidering any approach based on systematically bypassing either or both concepts!-)

Alex Martelli
+1 For keep it empty.
Frank Krueger
Personally, I prefer to keep things separate, and then import *. THe reason is that, despite folding and stuff, I still hate to browse files containing too many classes, even if related.
Stefano Borini
@stefano think about a big framework. if it uses `import *` you must unconditionally accept all the framework in its all, even features the you will never use. keeping `__init__.py` empty give you more chances than just all-or-nothing semantic. think about twisted.
mg
if keep it empty, even after import mobilescouter, one still can't use mobilescouter.mapper or mobilescouter.vehicle or mobilescouter.whatever. isn't import mobilescouter.A, mobilescouter.B..... too verbose?
sunqiang
@sunqiang this is personal but i don't think so. `from mobilescouter import A, B` is just a line of code and you don't have a project with 666 classes and every one with his own file, right? if you have two or more `import *` in your code you are filling the namespace with potential garbage and quickly you'll forget where `A` come from. And if an upper package do the same? you are grabbing all the sub-packages and sub-sub-packages. like the zen of python says, explicit is better than implicit.
mg
@mg, if there is a line "import A, B" in the __init__.py file, then I can call the A(or B) with the syntax:mobilescouter.A; if we use "from mobilescouter import A, B", then it's just A.something. sometime just this line, I don't remember A is a sub pacakge of mobilescouter, and I think this contributes to namespace pollution (though it's a lot better than ""from mobilescouter import *". I still prefer "import pkgname" give user the uniform public interface. so __init__.py do the import sub_pkgname things.
sunqiang
A: 

__all__ is very good it helps guide import statements without automatically importing modules http://docs.python.org/tutorial/modules.html#importing-from-a-package

using __all__ and import * is redundent, only __all__ is needed

I think one of the most powerful reasons to use import * in an __init__.py to import packages is to be able to refactor a script that has grown into multiple scripts without breaking an existing application. But if your designing a package from the start. I think it's best to leave __init__.py files empty.

for example:

 foo.py - contains classes related to foo such as fooFacroty, tallFoo, shortFoo

then the app grows and now it's a whole folder

 foo/
     __init__.py
     foofactories.py
     tallFoos.py
     shortfoos.py
     medumfoos.py
     santaslittlehelperfoo.py
     superawsomefoo.py
     anotherfoo.py

then the init script can say

     __all__ = ['foofactories','tallFoos' 'shortfoos','medumfoos','santaslittlehelperfoo','superawsomefoo' 'anotherfoo']
     # deprecated to keep older scripts who import this from breaking
     from foo.foofactories import fooFactory
     from foo.tallfoos import tallFoo
     from foo.shortfoos import shortFoo

so that a script written to do the following does not break during the change:

 from foo import fooFactory, tallFoo, shortFoo
Fire Crow