8

In Python 3, modules can be namespace modules without an __init__.py (as per PEP 420) or as a regular module (i.e. '[modules] packages as they are implemented in Python 3.2 and earlier' - PEP 420) that have an __init__.py or are a single .py file.

How can you tell the difference between a namespace module and an 'ordinary' module?

(I am using Python 3.5.3)

e.g. Namespace module named mod prints out as:

(Pdb) mod
<module 'mymodule' (namespace)>

and ordinary modules print out as:

(Pdb) mod
<module 'mymodule' from '/path/to/mymodule/__init__.py'>
3
  • BTW the way it printed depends on the interpreter Commented Mar 22, 2017 at 20:57
  • @abccd: What's unclear about it? Have you just not heard of namespace packages? Commented Mar 22, 2017 at 20:57
  • @user2357112 have you just not heard of the OP can edit the post within the first minute and not show up as a edit? And have you just not see that I deleted that comment after that? Commented Mar 22, 2017 at 20:59

2 Answers 2

10

Namespace packages have a __path__, and either __file__ set to None or no __file__ attribute. (__file__ is set to None on Python 3.7 and later; previously, it was unset.)

if hasattr(mod, '__path__') and getattr(mod, '__file__', None) is None:
    print("It's a namespace package.")

In contrast, modules that aren't packages don't have a __path__, and packages that aren't namespace packages have __file__ set to the location of their __init__.py.

Sign up to request clarification or add additional context in comments.

2 Comments

In my code, both namespace and regular modules have a __path__, is there a reason for checking the __path__ attribute exists?
@NathanaelFarley: Packages have a __path__, but non-package modules don't. The __path__ check is there to distinguish namespace packages from built-in modules like sys, which also don't have a __file__.
6

From the Python 3.8 documentation, __file__ is:

Name of the place from which the module is loaded, e.g. “builtin” for built-in modules and the filename for modules loaded from source. Normally “origin” should be set, but it may be None (the default) which indicates it is unspecified (e.g. for namespace packages).

Also, the correct answer should be:

is_namespace = (
    lambda module: hasattr(module, "__path__")
    and getattr(module, "__file__", None) is None
)

3 Comments

Oh crud, you're right - PEP 420 says a namespace package "Does not have a __file__ attribute", but it looks like that got changed to __file__=None at some point.
Any reason for using lambda over def?
Just a matter of taste. Here I wanted minimal and inline stuff.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.