Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Python Packages

In this lesson, you’ll learn about Python packages. Suppose you have developed a very large application that includes many modules. As the number of modules grows, it becomes difficult to keep track of them all if they’re dumped in one location. This is particularly true if they have similar names or functionality. You might want a way to group and organize them.

Packages allow for a hierarchical structuring of the module namespace using dot notation. In the same way that modules help avoid collisions between global variable names, packages help avoid collisions between module names.

Creating a package is quite straightforward, since it makes use of the operating system’s inherent hierarchical file structure. Consider the following arrangement:

Image of a Python package

Here, there is a directory named pkg that contains two modules, mod1.py and mod2.py. Take a look at the contents of the modules. Here’s mod1.py:

def load_data():
    print('loading data using mod1.load_data()')

class Customer:
    pass

Here’s mod2.py:

def clean_data():
    print('cleaning data using mod2.clean_data()')

class Location:
    pass

Given this structure, if the pkg directory resides in a location where it can be found (in one of the directories contained in sys.path), you can refer to the two modules with dot notation (pkg.mod1, pkg.mod2) and import them with the syntax you’re already familiar with:

import <module_name>[, <module_name> ...]

Here’s what that looks like in practice:

>>>
>>> import pkg.mod1, pkg.mod2
>>> pkg.mod1.load_data()
loading data using mod1.load_data()
>>> x = pkg.mod2.Location()
>>> x
<pkg.mod2.Location object at 0x10818c550>

You can also use this syntax:

from <module_name> import <name(s)>

Here’s what that looks like in practice:

>>>
>>> from pkg.mod1 import load_data
>>> load_data()
loading data using mod1.load_data()

You can also use this syntax:

from <module_name> import <name> as <alt_name>

Here’s what that looks like in practice:

>>>
>>> from pkg.mod2 import Location as Primary
>>> y = Primary()
>>> y
<pkg.mod2.Location object at 0x10d8ed2b0>

You can import modules with these statements as well:

from <package_name> import <modules_name>[, <module_name> ...]
from <package_name> import <module_name> as <alt_name>

Here’s what that looks like in practice:

>>>
>>> from pkg import mod1
>>> mod1.load_data
<function load_data at 0x101b37f28>
>>> from pkg import mod2 as foo
>>> foo.clean_data()
cleaning data using mod2.clean_data()

You can technically import the package as well:

>>>
>>> import pkg
>>> pkg
<module 'pkg' (namespace)>

But doing that is of little use. Though this is, strictly speaking, a syntactically correct Python statement, it doesn’t do much of anything useful. In particular, it doesn’t place any of the modules in pkg into the local namespace:

>>>
>>> pkg.mod1
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    pkg.mod1
AttributeError: module 'pkg' has no attribute 'mod1'
>>> pkg.mod2.Location
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    pkg.mod2.Location
AttributeError: module 'pkg' has no attribute 'mod2'
>>> pkg.mod1.load_data()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    pkg.mod1.load_data()
AttributeError: module 'pkg' has no attribute 'mod1'

To actually import the modules or their contents, you need to use one of the forms you saw above.

macblanelw on July 4, 2020

This does not work for me: bpython version 0.18 on top of Python 3.8.2 /usr/bin/python3

import pkg.mod1, pkg.mod2 Traceback (most recent call last): File “<input>”, line 1, in <module> import pkg.mod1, pkg.mod2 ModuleNotFoundError: No module named ‘pkg’

Clearly, my version of python does not assume that a directory is a module, or will not treat the directory as one. Anything I can do? My current path is ~/projects/python/ModulesAndPackages/pkg/ I tried this from within /pkg/ and above it. Same results.

Ricky White RP Team on July 5, 2020

Try adding a __init__.py file to your pkg folder. There doesn’t have to be any code in it, but it’s presence will help it be identified as a package that can be imported.

macblanelw on July 6, 2020

This does not work for me: bpython version 0.18 on top of Python 3.8.2 /usr/bin/python3

import pkg.mod1, pkg.mod2 Traceback (most recent call last): File “<input>”, line 1, in <module> import pkg.mod1, pkg.mod2 ModuleNotFoundError: No module named ‘pkg’

Clearly, my version of python does not assume that a directory is a module, or will not treat the directory as one. Anything I can do? My current path is ~/projects/python/ModulesAndPackages/pkg/ I tried this from within /pkg/ and above it. Same results.

Chris Bailey RP Team on July 7, 2020

Hi @macblanelw, Are you using the resources for the course? I just downloaded the resources from “Supporting Materials” button, and unzipped the code to my desktop on my Mac. I entered into my terminal and changed into the sample directory, cd 08_PythonPackages.

The directory looks like this when I use the ls command:

pkg

I then started bPython

$ bpython
bpython version 0.19 on top of Python 3.8.2

I was able to confirm it was working when I typed import from the prompt and the letter pk, as bpython showed auto completion options for:

>>> import pk
pkg       pkg_resources     pkginfo

Have you been able to use the other resource files? And have you been able to create and use some of your own in a similar way? This is

konkna on July 16, 2020

hey,

when I have downloaded the code and run it via command line it works.

/mnt/c/NK/Learnings/python/realpython/ModulesAndPackages_Code/ModulesAndPackages_Code/08_PythonPackages
$ python3 08_PythonPackages_REPL.py
loading data using mod1.load_data()
loading data using mod1.load_data()
cleaning data using mod2.clean_data()
loading data using mod1.load_data()

However, when I run it via the bpython3 repl it doesn’t unless I have the init.py file

and even setting the sys.path.append to the directory doesn’t work.

>>> import sys
>>> sys.path
['', '/usr/bin', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dy
nload', '/home/konkNa/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-
packages', '/usr/lib/python3/dist-packages']
>>> sys.path.append(r'/mnt/c/NK/Learnings/python/realpython/ModulesAndPackages_Code/Module
sAndPackages_Code/08_PythonPackages')

>>> import pkg.mod1
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    import pkg.mod1
ModuleNotFoundError: No module named 'pkg'

Wondering how would be it different running in the batch/script mode vs running in the repl

FYI.. I use a ubuntu on the windows machine. So, it has python2 which is default and python3.6 and python3.7

bpython3 points to

bpython3
bpython version 0.17.1 on top of Python 3.6.9 /usr/bin/python3

tirexxerit on July 17, 2020

I got the same bpython error when I use python3.6 but if I switch to python3.8, I don’t see any error. Look;

 bpython
bpython version 0.19 on top of Python 3.8.4 /home/gyilmaz/Automation/Python/PAN/Dev/Training/venv/bin/python
>>> import pkg
>>> 
bpython3
bpython version 0.17.1 on top of Python 3.6.10 /usr/bin/python3
>>> import pkg
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    import pkg
ModuleNotFoundError: No module named 'pkg'

tirexxerit on July 17, 2020

or it is about bpython version not necessarily about python as it works on 0.19 bpython..

Idris Diba on Aug. 19, 2020

I also got the same error but then I added __init__.py to pkg folder which is located inside Modules_and_packages and it worked like a charm.

Become a Member to join the conversation.