Python Modules: Organize Your Code

Python modules are used to organize your code. It breaks down your large codebase into small and manageable files. Creating modules reinforces code reusability, which is a highly recommended principle in software development.

For instance, you write some useful generic function. By defining such functions in modules, you can use it without rewriting the function code. Python itself comes with a standard library which contains modules for different tasks.

What is a Module?

Simply module is a file which contains code. Modules include functions, objects, and also variables.

Although it is not necessary, as a best practice, a module should contain related objects. For instance, if you have a date module, it should carry date associated functions and objects.

From Where Comes The Module Name?

The name is derived from the file name without the py suffix. If your file name is datehelper.py, your module name is datehelper. Therefore you should import the module using the datehelper identifier.

import datehelper

Using Python Modules

You can import modules in three different ways.

The import modulename Statement

It is the primary way to import the module.

I have a simple printhelper module, which contains some functions.

printhelper.py

def print_hello():
    print("Hello CodeFacility")

def print_reverse(message):
    print(message[::-1])

Using printhelper module from my main code:

import printhelper

printhelper.print_hello()                 # Hello CodeFacility

printhelper.print_reverse('hello')        # olleh

The from modulename import name1, name2, …, Statement

The second way to import module permits specific objects (functions) to be explicitly introduced into the code.

Therefore you don’t have to use the module name as a prefix.

from printhelper import print_hello

print_hello()

The from modulename import * Statement

The last way to import a module is like the second form with a difference. Using the star sign means, Python imports all names (objects, functions, variables) except those that begin with an underscore.

from printhelper import *
print_hello()                    #  Hello CodeFacility
print_reverse('apple')           #  elppa

But beware of this particular form. If two modules define the same name, name clash will occur. The second name shadows the first name. For the reader, the usage creates difficulty. You wouldn’t know which definition is in effect.

However, for testing purposes, this form could be handy, especially using python interpreter from the command line.

Locating Modules

You may wonder how python finds your custom modules. Python looks for three places (in order) to search for your module.

  • Current Directory: You can put your module in the same directory where your main code file resides.
  • PYTHONPATH: It is an environment variable. If it is not empty, python interpreter reads the environment variable and add the path referred by the PYTHONPATH to the list of the search paths.
  • Default path depending on Installation: Default search path depends on the environment. For Unix, the default search path is ‘/usr/local/lib/python/’.

All the directories from these locations make up the sys.path variable from the system module (sys).

To see the overall module search path list:

import sys
print(sys.path)

For my current python environment (windows 64 bit, python 3.6) the output is:

[  '', 'C:\Users\myusername\AppData\Local\Programs\Python\Python36\python36.zip', 
'C:\Users\myusername\AppData\Local\Programs\Python\Python36\DLLs',
'C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib',
'C:\Users\myusername\AppData\Local\Programs\Python\Python36',
'C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\site-packages']

How To Change Module Search Path Dynamically

Likewise using built-in sys module, you can modify (add, remove) search path programmatically.

I have created another module (printhelper2) in a custom directory: C:\tmp

import sys

mycustomdir = 'C:/tmp'

sys.path.append(mycustomdir)

import printhelper2

printhelper2.print_hello()            # Hello CodeFacility        

Import Exception

If Python could not find the module, it raises an ImportError exception.

The dir() Function

dir function returns the list of the names defined in a module.

import math

print(dir(math))

output:

['doc', 'loader', 'name', 'package', 'spec', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

What are the default modules in Python?

Default modules which are automatically imported when we run python code called build-in modules.

To see what the build-in modules are:

dir(__builtins__)

The output is below:

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', 'build_class', 'debug', 'doc', 'import', 'loader', 'name', 'package', 'spec', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

As you see our lovely print function is part of the __builtins__ module.

For general info about the standard python library, read the python documentation.

Conclusion

The way to organize your code is using Python Modules. Python interpreter uses the module structure to manage his own built-in modules. It enforces code reusability and small, manageable python code files.

Leave a Comment