Многие python разработчики пишут свои модули и большинство из них часто не задумываются об их структуре. В результате возникает ситуация, что структура модулей может отличаться у разных разработчиков, что снижает читабельность кода и преемственность функционала другими разработчиками. При работе над крупным проектами, такое недопустимо.
Обычно при создании собственных новых модулей, рекомендуется их формировать стандартным образом, с использованием информации, представленной ниже.
Обычно при создании собственных новых модулей, рекомендуется их формировать стандартным образом, с использованием информации, представленной ниже.
Как стоит и как не стоит писать модули
Вся основная логика модуля заключена в отдельные функции или классы. На глобальном уровне могут быть объявлены только константы или необходимые для инициализации модуля операции.
MOD_CONST = 15
print(MOD_CONST)
def get_sum(x, y):
return (x + y) * MOD_CONST
a, b = 1, 2
print(get_sum(a, b))
print(MOD_CONST)
def get_sum(x, y):
return (x + y) * MOD_CONST
a, b = 1, 2
print(get_sum(a, b))
Выше представлен пример плохой структуры модуля. В нем содержаться лишние функции print, а также объявлены не константные переменные a и b, которые проверяют работу функции get_sum.
Ниже представлено более правильное исполнение данного модуля. Если планируется запускать модуль как самостоятельный скрипт, то должны быть определена точка входа в модуль в нее записаны инструкции. В python такой конструкцией является if __name__ == '__main__':
Ниже представлено более правильное исполнение данного модуля. Если планируется запускать модуль как самостоятельный скрипт, то должны быть определена точка входа в модуль в нее записаны инструкции. В python такой конструкцией является if __name__ == '__main__':
MOD_CONST = 15
def get_sum(x, y):
return (x + y) * MOD_CONST
if __name__ == '__main__':
print(MOD_CONST)
a, b = 1, 2
print(get_sum(a, b))
def get_sum(x, y):
return (x + y) * MOD_CONST
if __name__ == '__main__':
print(MOD_CONST)
a, b = 1, 2
print(get_sum(a, b))
Как правило, в блок if __name__ == '__main__' заносят все вызовы функций и вывод информации на стандартный поток вывода. Ещё один вариант — создать отдельную main() функцию, переписав в неё всю логику при запуске, и вызывать её в данном блоке. Как это работает? Ваш скрипт может выполняться и самостоятельно, а может быть импортирован как модуль другим скриптом. Чтобы выделить код, который не должен выполняться при импорте его следует поместить в условный оператор с условием if __name__ == '__main__':
Каждый скрипт при запуске получает от интерпретатора имя, которое хранится в специальной переменной __name__, которая будет равна "__main__", только если файл запускается как основная программа, и выставляется равной имени модуля при импорте модуля. То есть условие if __name__ == '__main__' проверяет, был ли файл запущен напрямую.
Каждый скрипт при запуске получает от интерпретатора имя, которое хранится в специальной переменной __name__, которая будет равна "__main__", только если файл запускается как основная программа, и выставляется равной имени модуля при импорте модуля. То есть условие if __name__ == '__main__' проверяет, был ли файл запущен напрямую.
Структура модуля
Хорошая структура модуля выглядит следующим образом:
В качестве примера использования Docstring модуля, представлен пример ниже. Он применим и для многих стандартных функций.Чтобы вывести значение описания после импорта используется стандартная функция help().
- Docstring (описание) модуля. В тройных кавычках описывается назначение модуля и его основные команды.
- Область импорта различных библиотек. Причем согласно PEP8:
- Каждый импорт должен быть на отдельной строке.
- Импорты должны быть сгруппированы в следующем порядке:
- импорты из стандартной библиотеки
- импорты сторонних библиотек
- импорты модулей текущего проекта
- При этом вставляйте пустую строку между каждой группой импортов.
- Область объявление глобальных констант.
- Инициализация модуля.
- Область определения функций и классов
- if __name__ == '__main__' (метод main) при необходимости.
В качестве примера использования Docstring модуля, представлен пример ниже. Он применим и для многих стандартных функций.Чтобы вывести значение описания после импорта используется стандартная функция help().
import os
help(os)
help(os)
В результате получим:
Help on module os:
NAME os - OS routines for NT or Posix depending on what system we're on.
DESCRIPTION This exports:
- all functions from posix or nt, e.g. unlink, stat, etc.
- os.path is either posixpath or ntpat
- os.name is either 'posix' or 'nt'
- os.curdir is a string representing the current directory (always '.')
- os.pardir is a string representing the parent directory (always '..')
- os.sep is the (or a most common) pathname separator ('/' or '\\')
- os.extsep is the extension separator (always '.')
- os.altsep is the alternate pathname separator (None or '/')
- os.pathsep is the component separator used in $PATH etc
- os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
- os.defpath is the default search path for executables
- os.devnull is the file path of the null device ('/dev/null', etc.) Programs that import and use 'os' stand a better chance of being portable between different platforms…
NAME os - OS routines for NT or Posix depending on what system we're on.
DESCRIPTION This exports:
- all functions from posix or nt, e.g. unlink, stat, etc.
- os.path is either posixpath or ntpat
- os.name is either 'posix' or 'nt'
- os.curdir is a string representing the current directory (always '.')
- os.pardir is a string representing the parent directory (always '..')
- os.sep is the (or a most common) pathname separator ('/' or '\\')
- os.extsep is the extension separator (always '.')
- os.altsep is the alternate pathname separator (None or '/')
- os.pathsep is the component separator used in $PATH etc
- os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
- os.defpath is the default search path for executables
- os.devnull is the file path of the null device ('/dev/null', etc.) Programs that import and use 'os' stand a better chance of being portable between different platforms…
Ниже представлен пример модуля с подобной структурой.
"""Описание нового модуля, вызываемое с помощью стандартной функции help()."""
import os
import math
import pandas as pd
import numpy as np
import my_module
MOD_CONST = 15
def main():
print(MOD_CONST)
some_func()
def some_func():
print(os.path.abspath())
df = pd.read_csv('test.csv')
print(df.head())
if __name__ == '__main__':
main()
import os
import math
import pandas as pd
import numpy as np
import my_module
MOD_CONST = 15
def main():
print(MOD_CONST)
some_func()
def some_func():
print(os.path.abspath())
df = pd.read_csv('test.csv')
print(df.head())
if __name__ == '__main__':
main()
В начале модуля представлено описание того, что он выполняет, так называемый docstring. Затем происходит импорт необходимых библиотек. Далее идет объявление констант.
Следом идет инициализация модуля, т.е. функция содержащая код, который будет выполняться при непосредственном запуске модуля. Делается это из-за того, что модуль может содержать большое количество вспомогательных функций. И чтобы не искать основную логику работы модуля по многочисленным строкам кода или прокрутки файла до блока if __name__ == '__main__':, который находиться в самом конце, её выносят в отдельную функцию и ставят на первое место.
Далее идет область определения функций и классов, которые необходимы для работы с модулями. И в конце блок if __name__ == '__main__':, содержащий код, который не должен выполняться при импорте, а только при непосредственном запуске. Заканчиваться модуль всегда пустой строкой.
Следом идет инициализация модуля, т.е. функция содержащая код, который будет выполняться при непосредственном запуске модуля. Делается это из-за того, что модуль может содержать большое количество вспомогательных функций. И чтобы не искать основную логику работы модуля по многочисленным строкам кода или прокрутки файла до блока if __name__ == '__main__':, который находиться в самом конце, её выносят в отдельную функцию и ставят на первое место.
Далее идет область определения функций и классов, которые необходимы для работы с модулями. И в конце блок if __name__ == '__main__':, содержащий код, который не должен выполняться при импорте, а только при непосредственном запуске. Заканчиваться модуль всегда пустой строкой.