0

When importing a popular library, for example >>> import numpy, and then >>> help(numpy), tons of tons of classes and functions are made available.

This is the structure of my package:

Blur/
├── __init__.py
├── blur
│   ├── __init__.py
│   ├── blur.py
│   ├── funcs
│   │   ├── __init__.py
│   │   └── funcs.py
│   ├── scripts
│   │   ├── __init__.py
│   │   └── blur_script.py
│   ├── tests
│   └── utils
│       ├── __init__.py
│       └── timer.py
└── setup.py

I do >>> import blur and then >>> help(blur), I get this:

NAME
    blur

PACKAGE CONTENTS
    blur
    funcs (package)
    scripts (package)
    utils (package)

FILE
    /Users/admin/Documents/Studie/IN3110/assignment4/Blur/blur/__init__.py

I want import blur to import the blur.py module, with its functions and classes. If I want to import blur.py I have to write import blur.blur. Think it is a bit ugly, don't you think? How to do this with only import blur?

Snusifer
  • 485
  • 3
  • 17
  • 1
    Have you read [this](https://stackoverflow.com/questions/44834/can-someone-explain-all-in-python)? – MyNameIsCaleb Sep 25 '19 at 15:35
  • I am aware, but thats not what i am trying to do. From X import * is not safe due to possible namespace conflicts. Im trying to understand how libraries like numpy only require a simple "import numpy" for the module to be imported, not "import numpy.foo.thud.etc" – Snusifer Sep 25 '19 at 15:57
  • 1
    Check out [their \_\_init\_\_.py file](https://github.com/numpy/numpy/blob/master/numpy/__init__.py) and see how they are importing numerous other things from within that. They are also using `__all__` and extending it with the `__all__` from some of those other imports which makes all of those functions available from the one import. – MyNameIsCaleb Sep 25 '19 at 16:01
  • I thought `__all__ ` in the init.py files were invoked only when calling `from X import * `. Is this not true? What in the numpy-init-file makes it so that `import numpy` works? I am looking at it myself, but some guidance would help a lot. – Snusifer Sep 25 '19 at 16:14
  • I broke it out below as an answer @Snusifer – MyNameIsCaleb Sep 25 '19 at 16:36

1 Answers1

0

So let's walk down a small portion of numpy that hopefully makes this more understandable.

numpy main __init__.py code

from . import polynomial

So that says to do a relative import (we know from the .) within the same folder, of polynomial. So in practice, this puts the module name into the namespace which we know by doing:

>>> 'polynomial' in dir(numpy)
True

What ends up in the namespace is based on module names and top level packages for the most part. So in this case, with numpy, each of those imports is being brought in to make up the giant list of available functions/etc.


Look at all of these import statements:

    from . import _distributor_init

    from . import core
    from .core import *
    from . import compat
    from . import lib
    # FIXME: why have numpy.lib if everything is imported here??
    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

And if you want you can go through and collect all of those names, plus everything within any * and you'll eventually add up to all of the available functions in numpy

MyNameIsCaleb
  • 4,409
  • 1
  • 13
  • 31