TSip
TSip

Reputation: 143

Sub packages and __init__.py

So, this is a set of questions about how to use __init__.py in packages/sub-packages. I have searched, and surprisingly not found a decent answer to this.

If I have the following structure (which is just a simplified example obviously):

my_package/
  __init__.py
  module1.py
  my_sub_package/
    __init__.py
    module2.py

the contents of module1.py is

my_string = 'Hello'

the contents of module2.py is

my_int = 42

First question: importing multiple modules from a package by default

What should be in the __init__.py files?

I can leave them empty, in which case, import my_package does nothing really (obviously it imports the package, but the package effectively contains nothing). This is fine obviously, and what should happen in most cases.

What I'd like in this case though is for import my_package to allow me to use my_package.module1.my_string and my_package.my_sub_package.module2.my_int.

I can add __all__ = [ 'module1' ] to my_package/__init__.py and __all__ = [ 'module2' ] to my_package/my_sub_package/__init__.py, but this only affects imports using a wildcard as I understand it (so only from my_package import * and from my_package.my_sub_package import *).

I can achieve this by putting

import my_package.module1
import my_package.my_sub_package

in my_package/__init__.py and

import my_package.my_sub_package.module2

in my_package/my_sub_package/__init__.py, but is this a bad idea? It creates a (seemingly) infinite series of my_package.my_package.my_package.... when I do this in the Python interpreter (3.5.5).

Separate, but highly related, question: using modules to keep files reasonably sized

If I wanted instead to be able to do the following

import my_package
print(my_package.my_string)
print(str(my_package.my_sub_package.my_int))

i.e. I wanted to use module1 and module2 purely for separating code into smaller more readable files if I actually had lots of modules in each package (which obviously doesn't apply in this trivial example, but can easily)

is doing from my_package.module1 import * in my_package/__init__.py and from my_package.my_sub_package.module2 import * in my_package/my_sub_package/__init__.py a reasonable way to do that? I don't like the use of the wildcard import, but it seems like it would be impractically verbose to import everything defined in a (real) module, listing them all.

Third (also highly related) question: avoiding writing the package names in multiple places

Is there a way I can achieve the above without having to put the names of the packages into the source code in them? I ask because I'd like to avoid having to change it in multiple places if I renamed the package (again, simple in this trivial example, can be done by an IDE or script in reality, but would be nice to know how to avoid).

Upvotes: 3

Views: 3006

Answers (1)

9769953
9769953

Reputation: 12261

In my_package/__init__.py, use

from . import my_sub_package

etc.
See for example NumPy's __init__.py, which has from . import random, and allows

import numpy as np
np.random.random

Wildcard imports inside a single package tend to be common, provided you have __all__ defined in the modules and subpackages you import from. Again an example from NumPy's __init__.py, which has several wildcard imports.

Here's part of that __init__.py:

from . import core
from .core import *
from . import compat
from . import lib
from .lib import *
from . import linalg
from . import fft
from . import polynomial
from . import random
from . import ctypeslib
from . import ma
from . import matrixlib as _mat
from .matrixlib import *
from .compat import long

Notice also the two core import lines. Both numpy.core and the core definitions (functions, classes etc) are then available.

When in doubt how to do something, or whether something is good practice, have a look at a few well-known libraries or packages. That can help gaining some valuable insights.

Upvotes: 9

Related Questions