In his work a programmer must “separate the entities” when the complexity of the code increases. In most cases this means that a block of code is divided into smaller blocks, such as functions, classes, class methods… But what to do if there are so many blocks that their number creates complexity? You have to “raise the level of abstraction” by dividing your code into several files. In this lesson, we will learn how to use several such files as complete code. One of the important characteristics of a programming language is how it sets up this mechanism. Well, Python provides, as usual, a convenient mechanism, which is a system of file imports. Let’s agree on the terms: any Python code file can be used in another Python file and is then called a module or library. By the way, Python can also use C or C++ files. Let’s learn about it!
Connecting a module from the standard library
The Standard Library is a set of the most common and used modules that come with the Python language. In other words, when you install the language on your computer, this set comes with it. In order to access any module from the Standard Library, just write the keyword import Python in your code, like this:
This line imports a module from the standard library, sys.
print(sys) print(type(sys)) # Output:
In fact, importing with Python import creates a sys variable that stores a reference to the file:
import sys print('sys', sys) print('type(sys)', type(sys)) os = sys sys = 1 print('sys', sys) print('type(sys)', type(sys)) print('os', os) print('type(os)', type(os)) # output: sys type(sys) sys 1 type(sys) os type(os)
The sys module helps you interact with your computer system. You can now use objects and functions from this library in your code. This is done using the syntax: “module.attribute”. For example, to know what type of operating system is used:
import sys print(sys.platform) # output: win32
After the keyword import you can specify not one but several Python modules (libraries). However, you should not do so, as it makes the readability of the code worse:
import sys, pprint pprint.pprint(sys.platform) # Output: 'win32'
It is important to know that when importing a module, the code from the module is immediately executed. For example, if you import the following code:
def foo(): print("foo") print("bar")
it will appear in the terminal:
The inscription foo did not appear, because the function has not yet been called anywhere. If you do this:
def foo(): print("foo") print("bar") foo()
then the terminal will display:
The fact that the code starts to run immediately is done in order to make it possible to initialize the module, that is to prepare it in some way before using it. For example, to start the server or fill in the variables with values. If you have code that should run when you run a script but shouldn’t when you import that script, use the standard trick:
def foo(): print("foo") if __name__ == '__main__': print("bar") foo()
The code will now execute as described above.
If you try to use something that is not in the module, the interpreter will return an AttributeError exception:
import sys print(sys.wrong_argument) # output: Traceback (most recent call last): File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch.py", line 4, in print(sys.wrong_argument) AttributeError: module 'sys' has no attribute 'wrong_argument' Process finished with exit code 1
If you try to import a module that does not exist, you will see a ModuleNotFoundError exception:
import wrong_module # Output: Traceback (most recent call last): File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch.py", line 1, in import wrong_module ModuleNotFoundError: No module named 'wrong_module' Process finished with exit code 1
Use of aliases It is common practice to use short aliases for long names for the imported module. There is a special word as for this purpose.
import itertools as iter print(iter) # output:
In fact, as is just “syntactic sugar”, because what happens here is the same thing we did earlier: substitute the variable storing the reference to the module.
import itertools as iter import itertools it = itertools print(it is iter) # output: True
The instruction from
Often you don’t need the whole module, just some part of it. You don’t buy a whole tea shop when you need one packet of tea, do you? Python has a keyword from that allows you to import only the parts you want. The simplest use case looks like this:
from sys import *
This imports all entities from the module and can now be accessed as if they were declared in the current file:
from sys import * print(platform) # output: win32
But this option is as bad as possible! Why? It’s all about namespace. If you use this way, the namespace is out of your control-now you don’t know what names of variables, functions, classes are used in your program, and that can cause trouble. After all, you’re not going to buy everything in a tea shop without looking, are you? In order to import only certain entities, specify their names after the import keyword (you can have several).
from sys import platform print(platform) # output: win32
You can use aliases here too.
from sys import platform as pl print(pl) # output: win32
Creating your own module in Python
As mentioned above, any Python code is a module, so creating modules is very easy. For example, let’s create a hello.py file:
def say(): print("Hello!")
Now in the same directory let’s create a talk.py file in which we will import the say function:
from hello import say say() # output: Hello!
Yes, it’s that simple! But how do you install a module written by someone else? Use pip instal.
There are some restrictions here. The most important – you can not name the module with the Python keyword itself (for example, pass or for), otherwise it just can not be imported. Also, you should not use Python identifiers (for example, class or type). You can get a complete list of reserved words and identifiers using the following code:
print(help("keywords")) # Output: Here is a list of the Python keywords. Enter any keyword to get more help. False break for not None class from or True continue global pass __peg_parser__ def if raise and del import return as elif in try assert else is while async except lambda with await finally nonlocal yield None
In addition, it is not desirable to give a module the same name as the modules of the built-in library, or any of the common third-party modules – it introduces unnecessary ambiguity.
Where should the module be placed?
Wherever you can find it later. The module search paths are specified in the sys.path variable. This includes the current directory (that is, the module can be left in the folder with the main program) as well as the directories where python is installed. In addition, the sys.path variable can be changed manually, which allows you to put the module in any convenient location (the main thing is to remember to modify the sys.path in the main program).
What to do if your project grows and there are already too many modules? Python offers an elegant solution: why not use a hierarchy that already exists in the operating system – directories (folders)? In Python, this is called packages. A package in Python is a directory with the obligatory __init__.py module. The rest of the contents can include both modules and other packages. __init__.py is a file that is executed immediately after importing a package and is designed to initialize – pre-prepare before using the contents of the package. This mechanism is similar to the way the main code flow is executed when importing a module. If a package does not contain __init__.py, it becomes a so-called “namespace” – it can contain other packages, but it cannot contain modules at first level.