2021-08-21

A Python Compiler - NUITKA

Nuitka is a compiler that produces binary executables from source code written in Python. It generates the C code for the indented Python script and then it creates the correspondent executable. On Windows, it self-downloads the gcc compiler, thus you don't need to install anything apart for a Python instance (here version 3.7) and the Nuitka module with the usual:

   pip install nuitka

As an example, I have compiled the following script (csv_to_yaml.py) that serialises my todo.csv file into a YAML format.


    # Takes the todo CSV file "todo.csv" and saves in YAML format.
    # Import the relevant libraries
    import csv
    import yaml
    import re
    from datetime import datetime

    # date format
    date_format = "%m/%d/%Y"

    # empty task list
    tasks = []
    class Task(yaml.YAMLObject):

        def __init__(self,task_id,name,length):
            self.task = task_id
            self.name = name
            self.length = length

    # Open the todo file in read-mode.
    with  open('todo.csv', 'r') as csvfile:
        datareader = csv.reader(csvfile, delimiter=',', quotechar='"')

        data_headings = []

        for row_index, row in enumerate(datareader):
            if row_index == 0:
                data_headings = row

            else:
                # id for tasks and subtasks
                id = re.findall(r'\d+', row[0])


                # number of days between start and end date
                try:
                    start = datetime.strptime(row[6], date_format)
                    end = datetime.strptime(row[7], date_format)
                    days = end-start
                except ValueError:
                    days = 0
                
                num_of_days = "{days}d".format(days=days)
                task =  Task(int(id[0]),row[4],num_of_days)
                tasks.append(yaml.dump(task))

        with open("todo.yaml","w") as output:
            output.write("\r\n".join(tasks))
    

To compile the script, I can use the following command:

   python -m nuitka --mingw64 -o csv_to_yaml_nooptions.exe csv_to_yaml.py

the option --mingw64 indicates that I want to use the gcc compiler for Windows.

The figure below shows the list of DLLs that the executable depends upon, you can notice that it requires to have the python37.dll installed.

If you want to ensure that your executable will run on every Windows Os the following command has to be used instead:

   python -m nuitka --mingw64 --onefile -o csv_to_yaml_onefile.exe csv_to_yaml.py

As shown in the figure above only the system DLLs are now required. Of course, the executable in this case will be larger in size and slower to run since it has to create a temporary directory with the runtime libraries. However, for a simple script like this one, isn't particularly bad and the distributable version is just twice as slower as the non-distributable.