Organizing codes in libraries

Reading time5 min

In brief

Article summary

In this article, we discuss how codes should be organized in modules. In particular, we explain that we can organize them in files, and show how to import functions fromt hese files. This is essential for reusability of the codes you write.

Main takeaways

  • Codes can be stored in files (modules).

  • These modules can be imported in your scripts.

  • Modules should be designed as coherent collections of functions and variables.

  • Structuring codes like this is important for code reusability.

Article contents

1 — Importing functions

A key property of functions is that they can be easily reused. Functions may be thematically regrouped into separated files.

To call a function, called for instance funct_ext, defined in a separated file named my_functions.py, you need to explicitly indicate the Python interpreter where to find this function using the import statement.

However, file my_functions.py should be found by the system. In other words, its directory should be in the PATH variable, which is a list of directories where Python will look for files. If it is not, you can either add your directory to the PATH at the system level, or add the directory to the Python variable sys.path.

Information

Note that depending what you append to the PATH, the system will look at different locations. Indeed, consider the following code:

sys.path.append(os.path.join("..", "my_python_files"))

Here, you append the string "../my_python_files to the path. When running a script, the script will therefore search in its parent directory (..) for a directory named my_python_files. The starting point of the search is therefore the directory containing the script being executed.

Alternatively, you can put an absolute path to the path. To do so, you can use the following code:

this_directory = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(this_directory, "..", "my_python_files"))

Here, this_directory is the absolute path to reach the file containing these lines of code. Then, when running the script, it will search for a directory named my_python_files in the parent directory of the file in which these lines of code appear.

This distinction can be very important when designing modules that are made to be imported!

Here are a few possible ways of importing a function in Python:

# Let's assume the file is not in the path
# For instance, assume it's in a directory "my_python_files" in the parent directory containing this script
import sys
import os
sys.path.append(os.path.join("..", "my_python_files"))

# Let's import func_ext
from my_functions import func_ext

# Now we can use the function
funct_ext()
# Let's assume the file is not in the path
# For instance, assume it's in a directory "my_python_files" in the parent directory containing this script
import sys
import os
sys.path.append(os.path.join("..", "my_python_files"))

# Let's import all functions from "my_functions.py"
from my_functions import *

# Now we can use the function
funct_ext()
# Let's assume the file is not in the path
# For instance, assume it's in a directory "my_python_files" in the parent directory containing this script
import sys
import os
sys.path.append(os.path.join("..", "my_python_files"))

# Let's import the "my_functions" module
import my_functions

# Now we can use the function precising the module in which it is
# This can be very practical when multiple modules have functions with the same name
my_functions.funct_ext()
/**
 * To run this code, you need to have Java installed on your computer, then:
 * - Create a file named `Main.java` in a directory of your choice.
 * - Copy this code in the file.
 * - Open a terminal in the directory where the file is located.
 * - Run the command `javac Main.java` to compile the code.
 * - Run the command `java -ea Main` to execute the compiled code.
 * Note: '-ea' is an option to enable assertions in Java.
 */
public class Main {

    /**
     * This is the entry point of your program.
     * It contains the first codes that are going to be executed.
     * 
     * @param args Command line arguments received.
     */
    public static void main(String[] args) {
        // Now we can use the function
        MyFunctions f = new MyFunctions()
        f.func_ext();
    }

}

In Python, when you import a file, its whole contents is executed. For instance, let’s consider the following code, in a file named my_module.py:

def my_function () -> None:

    """
        A function that does something in your library.
        In:
            * None.
        Out:
            * None.
    """

    print("Hello")



# Let's test our code
print("Testing my function")
my_function()

Now, consider the following script:

# Import the function we want
from my_module import my_function

# Let's use the function
my_function()

When running this script, we get the following output:

Output
Testing my function
Hello
Hello

In such situation, you probably didn’t want the testing part to be executed, but only want the function to be imported. To correct that, you can indicate to Python that a certain code has to be run only when the file is executed directly, i.e., not imported. Here is how to update my_module.py:

def my_function () -> None:

    """
        A function that does something in your library.
        In:
            * None.
        Out:
            * None.
    """

    print("Hello")



# This test indicates that we only run this when the file is executed directly
if __name__ == "__main__":

    # Let's test our code
    print("Testing my function")
    my_function()

Now, when running the script above again, we get the expected output:

Output
Hello

Note that in Java, there is a single entry point called the main function, while each Python script can be run independently.

2 — Structuring code into separate files

Some code that you write may be generic enough to be used in other projects. In general, it is good to systematically separate your functions into thematic files. The codes you write now may be helpful in a few lessons, scholarship years, or maybe later.

To create a reuseable piece of code, we save the code into a separate file with a .py extension. Such a Python file is called a “module”.

To keep code organized, it’s good practice to split it into multiple files. For example:

  • main.py – The main script.
  • functions.py – Contains reusable functions.

The structure of a file such as functions.py should follow the following convention:

"""
    General description of the document contents.
"""

# Needed imports
# ...

# Various functions, well documented.
# ...

# Things to do when running this code directly
if __name__ == "__main__":
    # ...
// Needed imports
// ...



/**
 * General description of the class contents.
 * Here, we name the class Functions for the example.
 * It should match file name.
 */
public class Functions
{

    /**
     * Various functions, well documented.
     */
    // ...

}

Do not hesitate to have multiple such auxiliary files, corresponding to themes. For instance, you could have a file named math_functions.py, and another named network_functions.py.

Important

Beware of file names! If you name your files math.py or random.py for instance, Python will not be able to find the standard math or random modules when trying to import them.

To go further

Important

The content of this section is optional. It contains additional material for you to consolidate your understanding of the current topic.

Looks like this section is empty!

Anything you would have liked to see here? Let us know on the Discord server! Maybe we can add it quickly. Otherwise, it will help us improve the course for next year!

To go beyond

Important

The content of this section is very optional. We suggest you directions to explore if you wish to go deeper in the current topic.