Earlier you have learned that any Python file is considered a module. You separate your code thematically into different files to keep it organized. But if your project is very big? In that case you can go a step further and group your modules into packages.
A package is simply a folder that contains Python modules (.py files) . It might contain other sub-folders, aka sub-packages as well which would contain more Python modules.
Normally, when you import a Python module, you import only one file with the extension .py . When you import a Python package you essentially import a folder containing a collection of modules rather than a single module.
If you think more about this, what if the folder that you’re trying to import contained many sub-folders? And you wanted to access those sub-folders. Would you need to import each sub-package before you can use it?
The answer is – you don’t. Importing each sub-folder would be tedious and Python doesn’t expect you to do that. Once you import a package, you can access all sub-packages by using the “dot operator ( . )” while importing / calling the required module / function.
Let’s suppose that there is a package named “jack” which contains multiple sub-packages. You import jack into your Python file and then attempt to call a function “up()”. Take a look at the following code which calls a function present within multiple subpackages.
As you can see, once you import a package you can access its sub-packages and individual modules using the dot operator.
In the above example, you could have imported the package jill with import jack.and.jill and then called the function starting from jill i.e., your call would have been jill.went.up().
Try to compare the different ways in which you can import packages/modules and how it affects the code used to call their containing modules & functions.
core.utilities. = Packages, AKA folders
calc / logs / colors = Modules, AKA python files
add(), print_logs(), screen_test() = Functions
A couple of things to notice in these examples.
There are no official best practices recommended for importing. However, it is common sense to:
There are no hard and fast rules for importing but the main idea is to improve code readability through trial and error. So if you find yourself constantly typing multiple packages then consider importing the subpackage rather than the main package or using aliases.
If you create an __init__.py file inside any folder, then Python will recognize that folder as a package. Even if the __init__.py file is completely empty, your folder is still considered a package.
However, from Python 3.3+ the empty __init__.py file was made optional for packages. In other words, you could import any random folder into your code and Python would treat it as a package.
This has caused much confusion where you will hear people saying that you need to add the __init__.py file if you are creating a package. However, if you’re on Python 3.3+ it’s not necessary.
The __init__.py file will get executed at the time of package import. However, that said, it is beyond the scope of this course to cover this file in any more details. For now you need to know that this file gets executed whenever its package is imported. That will help you as you work on projects.
|Imports multiple python files.||Imports a single python file.|
|Once a package is imported you can access nested packages as well (sub-packages).||Is a single python file.|
|__init__.py file gets executed when a package is imported.||The python module gets executed when it is imported.|
|Added automatically to PYTHONPATH after creation of __init_.py file.||Needs to be manually added to PATH or PYTHONPATH.|
|To run a package directly by name it must contain a __main__.py file which will get executed. (Ex. python -m packagename1).||You can run a module by calling it directly by name from the terminal. (Ex. python filename1).|