# Importing functions and packages#

Very often, we need tools that are not directly provided by the default Python library. In that case we need to import the necessary functions from modules or packages into our notebooks or scripts. Some modules come directly with the Python distribution (like the math module seen in the Basic math in python), and some others like Numpy, scikit-image etc. are external packages installed with pip or conda. When it comes to import they work in the same way, and we have multiple ways of importing single functions or groups of them.

## Basic import#

The basic import statment uses the key-words `import`

and the module name. For example with the basic Python module `pathlib`

that deals with file paths and names:

```
import pathlib
```

If we want to import an external package we need to make sure it is actually installed, otherwise we get an error message:

```
import absent_package
```

```
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Input In [14], in <cell line: 1>()
----> 1 import absent_package
ModuleNotFoundError: No module named 'absent_package'
```

If you have a missing package, you can install it directly from the notebook using pip or conda. For example if Numpy is not installed yet you could execute:

```
conda install -c conda-forge numpy
```

```
Collecting package metadata (current_repodata.json): done
Solving environment: done
# All requested packages already installed.
Note: you may need to restart the kernel to use updated packages.
```

## Alternative import formulation#

Using the simple formulation above, we get access to functions directly attached to the main package. Let’s import the Numpy package that we will use later to handle image. We can import it:

```
import numpy
```

and now we get e.g. access to the cosine function of Numpy by simply using the dot notation:

```
numpy.cos(3.14)
```

```
-0.9999987317275395
```

To find all functions available in a package or a module, you typically have to go to its documentation and look for the *Application Programming Interface* or *API*. For example here we find a description of all mathematical functions (including the cosine) of Numpy: https://numpy.org/doc/stable/reference/routines.math.html

### Name shortening#

If we use a package regularly, we might not want to write the full package name every time we need a function from it. To avoid that we can abbreviate it at the time of import using the `as`

statement:

```
import numpy as np
```

```
np.cos(3.14)
```

```
-0.9999987317275395
```

### Specific functions#

If we only need a specific function from a package, we can also just import it using the `from`

statement. For examample if we want to only import the `np.cos`

function above:

```
from numpy import cos
```

```
cos(3.14)
```

```
-0.9999987317275395
```

Of course in this case, unless we find the specfiic line where the function is imported, we don’t know that `cos`

necessarily belongs to Numpy as we could also have defined such a function in the notebook. If we want to import **all** functions from a package we can also use the `*`

sign:

```
from numpy import *
```

Here we have for example access to the sine function withouth having explicitly imported it:

```
sin(3.14)
```

```
0.0015926529164868282
```

As you can see, with this solution we have *no idea* what we actually imported in our notebook, which can lead to unwanted effects like re-using a function name. **If you don’t have a specific reason to use this import variant, we strongly discourage its use.**

## Sub-modules#

In larger packages like Numpy, some functions are directly accessible from the main package (like `np.cos`

) and others with more specialized tasks are grouped together by topic or domain into submodules. For example Numpy has a submodule dedicated to distributions called `random`

. All the points seen above are still valide here.

We use the dot notation to access functions, but now need to also specify the submodule name. For example the `normal`

function that generates numbers drawn from a normal distribution:

```
np.random.normal()
```

```
1.8077301364791438
```

We can shorten the function call by importing only the sub-module:

```
from numpy import random
```

```
random.normal()
```

```
0.0909924357071552
```

and we can further shorten by importing just the function:

```
from numpy.random import normal
```

```
normal()
```

```
0.0038794083334154307
```

Finally we can rename using the `as`

statement:

```
from numpy import random as rd
```

```
rd.normal()
```

```
-0.6781586087709578
```

## Exercise#

The Numpy package has a linear algebra submodule called `linalg`

. The following code computes the norm of a vector: `np.linalg.norm([1,2])`

. Try to:

import just the sub-module and call the same function

import just the

`norm`

function and call it