64

All I want to know is what exactly does __package__ mean? Didn't find any explanation in the official doc, even on SO.

If you could provide some examples I would be very happy.

nbro
  • 15,395
  • 32
  • 113
  • 196
laike9m
  • 18,344
  • 20
  • 107
  • 140

2 Answers2

77

See the PEP 366 and import system reference documentation:

The major proposed change is the introduction of a new module level attribute, __package__. When it is present, relative imports will be based on this attribute rather than the module __name__ attribute.

and

  • The module’s __package__ attribute should be set. Its value must be a string, but it can be the same value as its __name__. If the attribute is set to None or is missing, the import system will fill it in with a more appropriate value. When the module is a package, its __package__ value should be set to its __name__. When the module is not a package, __package__ should be set to the empty string for top-level modules, or for submodules, to the parent package’s name. See PEP 366 for further details.

So, for a module located in foo/bar/baz.py, __name__ is set to foo.bar.baz, and __package__ is set to foo.bar, while foo/bar/__init__.py will have foo.bar for both the __name__ and __package__ attributes.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 3
    Martijn, than you for your answer, but would you mind to give an example of the problem when the `__package__` attribute is really usefull? – chiffa Feb 12 '15 at 21:50
  • 2
    @Andrei: the PEP I link to addresses this specifically, but it allows you to detect when a module file in a package is executed directly (with `python /modulename.py`) and adjust for that situation. – Martijn Pieters Feb 12 '15 at 22:14
  • I was reading PEP but didn't quite understand how it would be used, mainly because the default behavior of the `__name__.rpartition('.')[0]` line is not entirely clear to me, just as the interaction of the `__name__` and `__package__` attributes and the base paths used for importing module from other folders within project. In fact I have a module accessing behavior from the main entry point I am happy about and that I don't want to break but I would also like to use modules deeper in the folder tree as primary access points for some applications, which I currently have trouble with. – chiffa Feb 12 '15 at 22:46
  • 1
    The `str.rpartition()` call splits on the last `.` and returns the first half; so `foo.bar.baz.eggs` splits off to `foo.bar.baz`. The rest is too broad to go into in comments. – Martijn Pieters Feb 12 '15 at 23:51
51

All I want to know is what exactly does __package__ mean

It is the mechanism that enables explicit relative imports.

There are three possible categories of values for __package__

  • A package name (a string)
  • An empty string
  • None

Package Name

That is, if a module is in a package, __package__ is set to the package name to enable explicit relative imports. Specifically:

When the module is a package, its __package__ value should be set to its __name__. When the module is not a package, __package__ should be set [...] for submodules, to the parent package’s name.

Empty String

If a module is at root, or top-level, that is, the current module is imported with

import current_module

or when a top-level module is run as the entry point as with:

$ python -m current_module

then __package__ is an empty string. Or as the documentation says:

When the module is not a package, __package__ should be set to the empty string for top-level modules...

None

If a module/script is run by filename, __package__ is None:

When the main module is specified by its filename, then the __package__ attribute will be set to None.

Evidence

First, let's create a file structure with noisy debugging - using Python 3.6:

text = "print(f'{__name__}, __file__: {__file__}, __package__: {repr(__package__)}')"

from pathlib import Path
Path('foo.py').write_text(text)
Path('package').mkdir()
Path('package/__init__.py').write_text(text)
Path('package/__main__.py').write_text(text)
Path('package/bar.py').write_text(text)

# and include a submodule with a relative import:
Path('package/baz.py').write_text(text + '\nfrom . import bar')

Now we see that foo.py executed as a module has an empty string for __package__, while the script executed by file name as the entry point has None:

$ python -m foo
__main__, __file__: ~\foo.py, __package__: ''
$ python foo.py
__main__, __file__: foo.py, __package__: None

When we execute a package as a module for the entry point, its __init__.py module runs, then its __main__.py runs:

$ python -m package
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\__main__.py, __package__: 'package'

Similarly, when we execute a submodule as a module for the entry point, the __init__.py module runs, then it runs:

$ python -m package.bar
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\bar.py, __package__: 'package'

Finally, we see that the explicit relative import, the entire reason for having __package__, (which happens last here) is enabled:

$ python -m package.baz
package, __file__: ~\package\__init__.py, __package__: 'package'
__main__, __file__: ~\package\baz.py, __package__: 'package'
package.bar, __file__: ~\package\bar.py, __package__: 'package'

Note, in the output, I have substituted ~ for the parent directories.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • I guess a small quirk is calling a package by its name like so: ```python package```. In that case ```__package__``` is '' and not ```None```. Beats me why that is the choice though – figs_and_nuts Jan 19 '22 at 13:33