2

This is my project structure (Python 3.5.1.):

a
├── b.py
└── __init__.py

Case 1

  • File b.py is empty.

  • File __init__.py is:

    print(b)
    

If we run import a, the output is:

NameError: name 'b' is not defined

Case 2

  • File b.py is empty.

  • File __init__.py is:

    import a.b
    print(b)
    

If we run import a, the output is:

<module 'a.b' from '/tmp/a/b.py'>

Question

Why doesn't the program fail in Case 2?

Usually if we run import a.b then we can only reference it by a.b, not b. Hopefully somebody can help explain what's happening to the namespace in Case 2.

asked Mar 16, 2016 at 12:32
3
  • I think it's probably because b is introduced to the namespace of a by the import a.b statement. But I'm not sure about the details. Nor do I know whether it's an explicitly supported feature. Commented Mar 16, 2016 at 12:36
  • @shx2 Both a and b. a should be there. But why is b also there? The most logical thing I can guess is: a is introduced into the current scope, then b is introduced into the scope of a. But the current scope is the same as the scope of a when executing a/__init__.py. Need confirmation. Commented Mar 16, 2016 at 12:46
  • @shx2: yes, that's the point of the question. Why is b there too? It was never explicitly imported. import a.b only adds a, normally. Commented Mar 16, 2016 at 12:57

2 Answers 2

3

Python adds modules as globals to the parent package after import.

So when you imported a.b, the name b was added as a global to the a module, created by a/__init__.py.

From the Python 3 import system documentation:

When a submodule is loaded using any mechanism (e.g. importlib APIs, the import or import-from statements, or built-in __import__()) a binding is placed in the parent module’s namespace to the submodule object. For example, if package spam has a submodule foo, after importing spam.foo, spam will have an attribute foo which is bound to the submodule.

Bold emphasis mine. Note that the same applies to Python 2, but Python 3 made the process more explicit.

answered Mar 16, 2016 at 12:43
Sign up to request clarification or add additional context in comments.

Comments

-1

An import statement brings a module into scope. You imported b, so there it is, a module object.

Read the documentation for import:

The basic import statement (no from clause) is executed in two steps:

  • find a module, loading and initializing it if necessary
  • define a name or names in the local namespace for the scope where the import statement occurs.

You didn't import b in the first case.

answered Mar 16, 2016 at 12:36

3 Comments

I wouldn't be very suprised if Case 1 fails. If you run import a.b; print(b) in a __main__ script then it will fail. But it doesn't fail in Case 2 here.
@BarryTheHatchet: import a.b binds the name a in a namespace. What is special here is that b is a submodule of a and thus the import internals set the name b in the namespace of a. That results in a global b in that the namespace of a, i.e. __init__.py. If this was any other module the name b would not have appeared like this.
@BarryTheHatchet: In other words, they didn't import b in the second case either, but it was added anyway.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.