Structuring code

Python statements (code in general) are usually written in files which are stored in folders.

Lets see how to organize our code and how to use it.

1. Modules and scripts

  • Modules/scripts are files which store Python code and have the extension .py. Example:

In [ ]:
!cat my_python_module.py

From Python, modules are invoked using import (notice that when a module is imported, the code of the module is run):


In [ ]:
import my_python_module

However, this happens only the first time we invoke a module from another module (this notebook):


In [ ]:
import my_python_module # This import should not generate any output

Module structures are accesible from the invoker code using the notation: <module_name>.<structure>:


In [ ]:
my_python_module.a

The module name of a module is accesible through the global variable __name__:


In [ ]:
my_python_module.__name__
  • Any module that is invoked using the interpreter directly, will be called as a script:

In [ ]:
!python my_python_module.py
  • Listening the names of a (in this case) a module:

In [ ]:
dir(my_python_module)

2. Packages ... and scripts

  • Any folder which stores at least one module and a (even empty) __init__.py file is a package.

In [1]:
!tree my_package


my_package
├── __init__.py
├── __main__.py
├── my_module.py
└── __pycache__
    ├── __init__.cpython-36.pyc
    ├── __main__.cpython-36.pyc
    └── my_module.cpython-36.pyc

1 directory, 6 files

In [2]:
!cat my_package/__init__.py


print("my_package/__init__.py executed")
import my_package.my_module

In [3]:
!cat my_package/my_module.py


a = 1
print("Hi from my_package/my_module.py!")

if __name__ == "__main__":
  print("I was invoked as a script.")
else:
  print("I was invoked as a module.") 
  • Invoking my_package as a module:

In [4]:
import my_package


my_package/__init__.py executed
Hi from my_package/my_module.py!
I was invoked as a module.

In [ ]:
dir(my_package)

In [ ]:
my_package.my_module.a
  • It is possible to avoid using the package namespace for the objects defined inside:

In [ ]:
my_module.a # This should fail

In [ ]:
from my_package import my_module

In [ ]:
my_module.a # This should work
  • To run a package as a script, it must have a __main__.py file with the first code to be executed:

In [ ]:
!cat my_package/__main__.py

In [ ]:
!python my_package

Avoiding to reference the path of the packages/modules

By default, modules and packages are imported from:


In [ ]:
import sys
sys.path

(Note: the previous output depends on the interpreter, the host, the configuration of Python, etc.)

To add a new directory, we can modify the PYTHONPATH environment variable (from the shell):


In [ ]:
!python -c 'import sys; print(sys.path)'
!(export PYTHONPATH=$PYTHONPATH:'/my/new/dir'; python -c 'import sys; print(sys.path)')

(... or from Python itself):


In [ ]:
sys.path

In [ ]:
sys.path.append("/my/new/dir")

In [ ]:
sys.path