Какие здесь цели?

Определите набор советов по работе с Python в контексте AWS.

В каком контексте написано это руководство?

Лучшие практики с Python…

  • Как инструмент сценария - Boto3 обращается к API AWS.
  • В качестве языка для Lambda в «бессерверном» расходном материале - код функции Lambda со сторонними зависимостями.
  • В качестве языка для Lambda в инфра-пайплайне - Housekeeping, CFN Custom Resources.
  • Компиляторы, раннеры, развертывание.

Обязательное к прочтению

Документация

  • Пространство Python

Https://www.python.org/dev/peps/pep-0008/

Https://www.python.org/doc/sunset-python-2/

  • AWS Space

Https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html

Https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html

Https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html

Лучшие практики для версий Python

  • Python 2 был закрыт - дата заката уже прошла; это было 1 января 2020 года.
  • Помните о внешних зависимостях между Python 2 и 3.

Вывод: используйте Python 3, если у вас нет такой возможности.

Лучшие практики для инструментов

  1. SublimeText3

2. VSCode

Лучшие практики для CLI (например, Bash)

Используйте оператор if main

  • Поместите логику вашего скрипта в «основной» метод.
  • Затем используйте соглашение «если главное» для вызова этого метода, если он вызывается через интерфейс командной строки (например, python3 myscript.py).

Пример - samlapi_formauth.py:

if __name__ == '__main__':
    main(__get_args())

Лучшие практики для API AWS

  1. Используйте Boto3
  • Имеет собственную логику повтора IIRC
  • Настраиваемый

2. Поддержка сценариев сбоя

Настройка Boto3

from botocore.config import Config

__sts_client = boto3.client(
    'sts',
    config=Config(connect_timeout=15, read_timeout=15, retries=dict(max_attempts=10))
)

Лучшие практики для AWS Lambda

Вы можете написать код на Python, который может работать как через интерфейс командной строки, так и через вызов AWS.

  1. Можно поместить cli.py рядом с main.py и вызывать таким образом
  • См. Simulate.py для расширенного примера
  • Это имитирует функцию AWS Step (которая обычно вызывает Lambda).

2. Можно поставить оператор «if main» для работы через интерфейс командной строки.

Помните об ограничениях

  1. Уровень аккаунта
  • 250 ENI на аккаунт (мягкий лимит, обратитесь к своему специалисту по AWS)
  • 1000 одновременных выполнений

2. Используйте подготовленный параллелизм, чтобы избежать обходных путей при холодном запуске.

  • Требуется гиперплоскость

Лучшие практики для бессерверных

Код упаковки

  • Создайте автономный zip для каждой лямбды ПОСЛЕ установки модулей pip
Code:
  S3Key:
    Fn::Pipeline::FileS3Key:
      Path: consumer.zip
  • Помните об ограничениях AWS Lambda на максимальные размеры

Https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html

Использование модулей common-pip- *

  • Способ обмена модулями между лямбдами в ОДНОМ РЕПО
  • Может ссылаться на сторонние модули
  • Может ссылаться на модули common-pip
  • Пример:
dnspython
git+https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/common-pip-log@master#egg=common-pip-log

И использование в вашем коде main.py:

# Set the first import path to be the "lib" subfolder of the lambda
from os.path import dirname, abspath
from os import environ
import sys
sys.path.insert(0, "{}/lib".format(dirname(abspath(__file__))))

import log

log.info('env', dict(os.environ))  # os.environ is not serializable by itself, cast to dictionary.

Лучшие практики для кода и дизайна

Дзен Python

«Пишите, думая о будущих разработчиках» - они должны убрать ваш беспорядок.

Обратите внимание, что «будущий разработчик» вполне может оказаться вами через 6 месяцев после того, как вы забудете все, что сделали.

Вот Python:

ЗАДАЧА - Просмотрите каждый из них и дайте справочные примеры.

C:/Users/ak>python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>

Напишите свой код в виде модулей

  • Помните, что выполняется, когда ваш файл python импортируется
  • Это напрямую влияет на Sphinx, который импортирует ваш код для создания его документации.
  • Это позволяет вам совместно использовать код, возможно, даже создать «общий» модуль, который могут импортировать другие программы.
  • Будьте осторожны - это делает вас фактическим сопровождающим этого модуля!
  • Нужны примеры
  • Нужны модульные тесты
  • Нужен процесс CICD
  • Для этого нужен список улучшений (для начала я использую README.md)

Уменьшите объем интерфейса вашего модуля

  • Используйте «непубличное» (также известное как «частное») соглашение об именах для внутренних атрибутов и методов, НЕ предназначенных для использования вне модуля.
  • Это должно быть вашей позицией по умолчанию, затем вы медленно реорганизуете материал, чтобы сделать его общедоступным, по мере необходимости с течением времени.

Https://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables

  • Используйте одинарное подчеркивание в начале для «закрытых» имен методов.
  • Например. ` _get_file_contents`

Работа со строками как со логическими значениями

Вам может быть передано строковое свойство, которое должно быть логическим. Значение может быть логическим - true / True / TRUE / 1 / Yes / On / и т. Д.

Используйте что-то вроде этого:

def _s_to_bool(input):
    """Implicit default of false."""
    return input.lower() in ['1', 'true', 'yes', 'on']

При написании комментариев сосредотачивайтесь на «почему», а не на «что».

Нет ничего более разочаровывающего, когда код не объясняет, почему что-то было сделано - вам нужен контекст!

Пример см. В разделе «ScanIndexForward» ниже:

response_iterator = dynamodb_paginator.paginate(
    TableName='core-automation-master-api-db-items',
    IndexName='parent-created_at-index',
    ExpressionAttributeNames=expression_attribute_names,
    ExpressionAttributeValues=expression_attribute_values,
    KeyConditionExpression='parent_prn = :v1',
    ProjectionExpression="#p,#n,#s,#c,#u",
    ScanIndexForward=False  # Process newer builds first (descending order) - important for logic!
)

Если этот комментарий не проясняет будущим разработчикам, что причина ScanIndexForward = False, в будущем может возникнуть ошибка.

Рассмотрим шаблон стратегии для запуска кода в разных контекстах.

  • Т.е. возможно, вы используете стратегию со своим модулем журнала, чтобы вы не выводили журналы локально в JSON, а в Cloud вы делаете это для CloudWatch
  • Другой пример - в контексте AWS Lambda учетные данные вы получаете из AWS Secrets Manager или из хранилища параметров. Вместо этого вы полагаетесь на переменные среды локально.

Лучшие практики для моделирования данных и доступа

  • «Upsert» - хорошая функция на низком уровне
  • Для Dynamodb - для скриптов я обычно не занимаюсь ORM / и т. Д., Я просто пишу вызовы Boto3 API
  • Например, используйте с Marshmallow + PynamoDB.

Библиотеки Python в помощь

Лучшие практики для тестирования

Используйте pytest для модульного тестирования

Хороший набор функций:

  • Автообнаружение тестов
  • Светильники
  • Плагины
  • Отчетность о покрытии и т. Д.

Используйте привязки Selenium для Python в CodeBuild

Лучшие практики для управления зависимостями

Используйте pipenv для явного управления и проверки зависимостей

  • Помогает поддерживать согласованность ваших зависимостей с помощью файла блокировки (т.е. повторять сборки одного и того же кода в разные дни)
  • Lockfile также имеет функцию контрольной суммы, чтобы гарантировать, что правильный пакет будет загружен в будущем (то есть может обнаруживать будущие компрометации)

Лучшие практики для безопасности

  • Используйте «безопасные» методы для парсеров YAML / JSON / XML. Пример:
client = sys.argv[1]

with open('../../{}-config/hosted-zones.yaml'.format(client)) as f:
    client_vars = yaml.safe_load(f.read())

Лучшие практики для пользовательской документации

  1. Используйте сфинкс
  • Используйте плагин редактора, чтобы помочь с форматированием, особенно таблиц

2. Сосредоточьтесь на нескольких ключевых областях:

  • Цели / контекст
  • Дизайн высокого уровня
  • Случаи применения
  • Рабочие примеры, которые люди могут разобрать и использовать повторно