Инструменты пользователя

Инструменты сайта


develop:pyton:practics

Practics

Seller

:!: Работа с csv /pandas

Штатный вариант
Возвращает каждую строку в формате List

import csv
 
with open('docs/orders_mini.csv', newline='') as csvfile:
  for row in _reader:
    print(type(row))
    print(row)

Вариант с pandas
Библиотека конечно матерая, но есть увеличенный порог входа, там все свое, куча собственный типов/форматов данных, во всем этом надо какое то время еще разбираться

import pandas as pd
 
data = pd.read_csv("docs/orders_mini2.csv", delimiter=';')
 
  # собственный формат dataFrame
print(type(data))
print(data)
 
# кортеж со строками, тоже матерый формат
for label, content in data.items():
    print(f'label: {label}')
    print(f'content: {content}')
 
  # так столбцы, в виде строк
for content in data.keys():
  print(f'content: {content}')
 
# и еще очень много всяких функций/вариантов
:!: Работа со словарями
  # Сортировка по значению
dict_result_successed = dict(sorted( dict_counted_acticles_successed.items(), key=lambda item: item[1], reverse=True))
 
 
  # Сумма значений (значение понятно int)
sum_successed = sum([ item for item in dict_counted_acticles_successed.values() ], 0)
 
 
  # Имея список с повторяющимися одиночными значениями, генерируем словарь с уникальными значениями и числом в value, начальное значение 0, далее будем считать
dict_counted_acticles = { key: value for (key, value) in (zip(set(ls_only_article), itertools.repeat(0))) }
:!: Работа со списками
  # В данном случае надо было из большого списка сформировать список с одиночными значениями плюс оставив только часть строки, вырезается регуляркой
reLabelSize = re.compile(r"-[\d]{1,2}$")
 
  # Делаем список доставленных, но только артикулы, без размера
lsOnlyArticle = [ reLabelSize.sub("", item["Артикул"]) for item in lsSourceBigDicts ]

Diagrams

:!: модуль diagrams

Статья
Дока

Установка
sudo apt install graphviz
pip install diagrams

Использование
:!: Группировка очень примитивная. После группировки нескольких элементов, хоть в коде и работаешь с одним объектом, группой, но стрелки рисуются с каждым элементом в группе, что добавляет не мало мусора, много мусора на самом деле добавляет

Рамка создается не всегда, только при использовании элемента «cluster» видимо, т.е. можно просто для краткости кода объединить в группу без отображения рамки

Внутри кластера так же можно устанавливать связи
Вложенная группировка таже присутствует, ограничений нет, логика вроде ясна

:!: Параметры отображения вроде регулируются, относится к компоненту GraphViz

:!: Свои элементы тоже создаются

:!: Перечень доступных узлов

:!: Направление соединения собсна « » так же - без направления
Стрелки имеют три атрибута, цвет, тип и текст

:!: Примеры
from diagrams import Diagram, Cluster, Edge
from diagrams.aws.compute import EC2
from diagrams.aws.network import ELB
from diagrams.aws.network import Route53
from diagrams.onprem.database import PostgreSQL
from diagrams.onprem.inmemory import Redis
 
# Просто перечень узлов
with Diagram("./images/simple_diagram") as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    database = PostgreSQL("User Database")
    cache = Redis("Cache")
    svc_group = [ EC2("Webserver 1"),
                  EC2("Webserver 2"),
                  EC2("Webserver 3") ]
diag
 
 
# С группировкой
with Diagram("./images/simple_diagram") as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    database = PostgreSQL("User Database")
    cache = Redis("Cache")
    with Cluster("Web server cluster"):
        svc_group = [ EC2("Webserver 1"),
                      EC2("Webserver 2"),
                      EC2("Webserver 3") ]
diag
 
 
# Связи
with Diagram("./images/simple_diagram") as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    database = PostgreSQL("User Database")
    cache = Redis("Cache")
    # Объединение в группу
    with Cluster("Web server cluster"):
        svc_group = [ EC2("Webserver 1"), EC2("Webserver 2"), EC2("Webserver 3") ]
    # Связи между элементами
    dns >> load_balancer >> svc_group
    svc_group >> cache
    #svc_group >> database
diag
 
 
# Форматирование стрелок
with Diagram("./images/simple_diagram") as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    cache = Redis("Cache")
    # Объединение в группу
    with Cluster("Web server cluster"):
        svc_group = [ EC2("Webserver 1"), EC2("Webserver 2"), EC2("Webserver 3") ]
    # Связи между элементами
    dns >> Edge(color="red", style="bold") << load_balancer >> svc_group
    svc_group >> Edge(label="this text") >> cache
diag
 
 
# Пар-ры графика
    # Конструктор принимает:
    # outformat=["jpg", "png", "dot"] - формат выходного файла, можно сразу несколько
    # filename="my_diagram" - имя файла, show=False показ, direction="TB" - направление
    # Так же, можно задавать доп аттрибуты
graph_attr = {
    "fontsize": "45",
    "bgcolor": "transparent"
}
with Diagram("./images/simple_diagram", graph_attr = graph_attr) as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    cache = Redis("Cache")
    # Объединение в группу
    with Cluster("Web server cluster"):
        svc_group = [ EC2("Webserver 1"), EC2("Webserver 2"), EC2("Webserver 3") ]
    # Связи между элементами
    dns >> load_balancer >> svc_group
    svc_group >> cache
diag
 
 
# Связи внутри кластера
with Diagram("./images/Grouped Workers"):
    dns = Route53("dns")
    web = Redis("cache")
 
    with Cluster("DB cluster"):
        db_primary = PostgreSQL("primary")
        db_primary - [PostgreSQL("replica1"), PostgreSQL("replica2")]
 
    dns >> web >> db_primary
:!: Примеры
from diagrams import Diagram, Cluster, Node
 
with Diagram('./output/output', show=False, outformat='svg') as d:
	with Cluster('cluster'):
		n1 = Node('A', height = '0.5', width = '5', labelloc = "c", fillcolor = 'purple', fontcolor = 'white', style = 'filled')
		n2 = Node('B', height = '0.5', width = '5', labelloc = "c", fillcolor = 'purple', fontcolor = 'white', style = 'filled')
        n3 = Node('C', height='0.5', width='5', labelloc="c", fillcolor='purple', fontcolor='white', style='filled')
        n4 = Node('D', height='0.5', width='5', labelloc="c", fillcolor='purple', fontcolor='white', style='filled')

Модули для Ansible

Располагаем py файлы по пути например «.ansible\collections\ansible_collections\community\general\plugins\modules» (в целом расположения указываются в конфиге). Тут можно сделать подпапку

:!: Минимальный пример

В данном примере файл «try_diagrams» в подпапке «my_diagrams»

---
- name: "Show list"
  community.general.my_diagrams.try_diagrams:
    my_variable: 'dcdc'
#!/usr/bin/python
 
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.module_utils.basic import AnsibleModule
 
 
def main():
    module = AnsibleModule(
        argument_spec = dict(
            cluster_list = dict(type = 'str', required = True),
            mode = dict(type = 'str', default = 'first', choices = ['first', 'second'])
        ), 
        supports_check_mode = True)
 
    # Полученные аргументы
    cluster_list = module.params['cluster_list']
    mode = module.params['mode']
 
    # Возвращаемое значение
    # некоторые зарезервированы, такие как change, другие можно добавлять любые кастомные, в выводе видно при "-vvv", там уже как удобнее будет извлекать
    # module.exit_json(changed=True)
    module.exit_json(msg="this is mymsg", data = 'this is mydata', myvar = 'this my variable')
 
    # Для ошибки
    # module.fail_json(msg="Failed to send message")
 
 
# Класс для примера, тут не используется
class myClass():
    def get_list(self, name_screens):
        return name_screens + 'ddcdc'
 
if __name__ == '__main__':
    main()

Скрины из заббикса

Для получения графиков изображением есть несколько php скриптов («/usr/share/zabbix/chart*.php»)

  • chart.php - рисует график по переданному массиву «itemids»
  • chart2.php - простой график по graphID (chart6.php тоже самое только круговой)
  • chart4.php - рисует график по триггеру, статистика

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

:!: Еще работа с заббиксом
  # Простой график
http://10.10.10.10/zabbix/chart2.php?graphid=15155&from=now-7d&to=now
http://10.10.10.10/zabbix/chart2.php?graphid=15155&from=now-24h&profileIdx=web.graphs.filter&to=now&width=1301
http://10.10.10.10/zabbix/chart2.php?period=from=now-10800&to=now&profileIdx=web.graphs.filter&graphid=15155&name=title&width=900&height=200&graphtype=0&legend=1
  # Триггер
http://10.10.10.10/zabbix/chart4.php?triggerid=22050
  # Массив итемов
http://10.10.10.10/zabbix/chart.php?itemids[]=55063&itemids[]=55064
:!: Пример скрипта
#!/usr/bin/python3
""" Скрипт для получения изображения графиков заббикса
    Графики для поиска перечислены в конфиге, параметр "list_graphs_on_screen"
    Заббикс группа передается в аргументе, предполагается кластерная группа, но можно использовать любую существующую
    Изображение сохраняется в этой же директории, перезаписывается один и тот же файл
 
Требуются пакеты:
    pip install Pillow
"""
 
from PIL import Image
import requests
import json
import settings
import io
import math
import argparse
import re
 
 
def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("-c", type = str, help = "Укажите имя кластера")
    args = arg_parser.parse_args()
    if not args.c:
        print("     Error: Укажите имя кластера для получения графиков")
        exit(1)
 
    # Принимаем только цифро-буквы и нижнее подчеркивание
    args.c = re.sub('[^\w_]', '', args.c)
 
    # Так же меняем префикс в имени кластера
    name_zabbix_group = args.c.replace("cl_", "GSC_")
 
    # Получаем перечень ИД графиков, указанных в конфиге
    list_ids_graphs = get_list_id_graphs(name_zabbix_group)
 
    if len(list_ids_graphs) > 0:
        # Получаем все изображения, собираем их в одно и сохраняем на диск
        image_path = get_screen_image(list_ids_graphs)
 
        # Возвращаем имя файла
        print(image_path)
 
 
def get_list_id_graphs(name_zabbix_group):
    """ Здесь получаем перечень ИД графиков, указанного кластера
    """
    # Сначала узнаем ИД указанной заббикс группы
    id_zabbix_group = get_id_zabbix_group(name_zabbix_group)
    if len(id_zabbix_group) == 0:
        return []
 
    query = """{"jsonrpc": "2.0",
        "method": "graph.get",
        "params": {
            "output": "graphid",
            "groupids": \""""+ id_zabbix_group +"""\",
            "sortfield": "name",
            "sortorder": "DESC",
            "filter": {
                "name": ["""+ settings.list_graphs_on_screen +"""]
            }
        }, "auth": \""""+ settings.zabbix_key +"""\","id": 1} """.replace('\n', '')
 
    answer = requests.post(f'http://{settings.zabbix_url}/api_jsonrpc.php', json=json.loads(query))
 
    if answer.status_code != 200:
        print(f"ZabbixAPI: Не удалось получить ответ от заббикса, ошибка: {answer.status_code}")
        return []
    else:
        # В результатах созвращается список словарей, с ключ-значение, нам нужен только список значений
        list_graphs_ids= [item['graphid'] for item in answer.json()['result']]
        return list_graphs_ids
 
 
def get_id_zabbix_group(name_zabbix_group):
    """ Получаем ИД заббикс группы по имени переданного кластера
    """
    query = """{"jsonrpc": "2.0",
        "method": "hostgroup.get",
        "params": {
            "output": "groupid",
            "filter": {
                "name": \""""+ name_zabbix_group +"""\"
            } 
        }, "auth": \""""+ settings.zabbix_key +"""\","id": 1} """.replace('\n', '')
    answer = requests.post(f'http://{settings.zabbix_url}/api_jsonrpc.php', json=json.loads(query))
 
    if answer.status_code == 200 and len(answer.json()['result']) > 0:
        return answer.json()['result'][0]['groupid']
    else:
        print(f"ZabbixAPI: Ответ от заббикса пуст, код ответа: {answer.status_code}")
        return ""
 
 
def get_screen_image(list_id_graphs):
    """ Из переданного списка графиков собираем общий коллаж
    """
    # Получаем куки авторизации, здесь, чтобы не вызываться в цикле
    data_api = {"name": settings.zabbix_user, "password": settings.zabbix_passwd, "enter": "Sign in"}
    cookie = requests.post(f"http://{settings.zabbix_url}/", data = data_api).cookies
 
    # Объект для итогового изображения, размер задается сразу
        # Ширина множится на два т.к. графики в два столбца
        # Высота - сумма всех, деленная на два т.к. в два столбца
    screen_image = Image.new("RGBA", ((settings.graph_width * 2), (settings.graph_height * math.ceil(len(list_id_graphs) / 2))))
    y_coordinate = 0
    x_coordinate = 0
 
    # Обходим список ИД графиков, получаем изображение каждого
    for id_graph in list_id_graphs:
        graph_image_bytes = get_graph_image(id_graph, cookie)
        if len(graph_image_bytes) == 0:
            continue
 
        # Ресайзим картинку и добавляем в общий коллаж
        graph_image = Image.open(io.BytesIO(graph_image_bytes)).resize((settings.graph_width, settings.graph_height))
        screen_image.paste(graph_image, (x_coordinate, y_coordinate))
 
        # Устанавливаем координаты вставки для следующего изображения
        if x_coordinate == 0:
            x_coordinate = settings.graph_width
        else:
            x_coordinate = 0
            y_coordinate += settings.graph_height
 
    # Сохраняем итоговое, общее изображение
        # Надобности хранить изображения нет, они сразу забираются
        # Есть надобность удалять старые
        # Выбран вариант перезаписывать один и тот же файл
    img_file_name = "zabbix_screen_image.png"
    screen_image.save(img_file_name)
    return img_file_name
 
 
def get_graph_image(id_graph, cookie):
    """ Получаем из заббикса изображение указанного ИД графика
    """    
    answer = requests.get(f"http://{settings.zabbix_url}/chart2.php?graphid={id_graph}&legend=1", cookies = cookie, verify = False)
 
    # Возвращаем `content` только если код ответа успешный, в противном случае пустую строку
    if answer.status_code == 200:
        return answer.content
    else:
        print(f"ZabbixAPI: Не удалось получить изображение, ошибка: {answer.status_code}")
        return ""
 
 
if __name__ == "__main__":
    main()

settings.py

zabbix_url = '{{ slack_notify_zabbix_url }}'
list_graphs_on_screen = '{{ slack_notify_graphs_on_screen }}'
graph_width = {{ slack_notify_graph_width }}
graph_height = {{ slack_notify_graph_height }}
zabbix_user = '{{ slack_notify_zabbix_user }}'
zabbix_passwd = '{{ slack_notify_zabbix_passwd }}'
zabbix_key = '{{ slack_notify_zabbix_key }}'

Overall

:!: Сортировка

Сортировка в списке словарей, по одному значению внутри словаря

# Структура в таком виде
ls_finished_log_records.append({
   'current_name': current_filename,
   'clear_name': clear_file_name,
   'duration': int(duration)
})
 
# Cортировкa по полю "duration"
ls_finished_log_records.sort(key=lambda item:item['duration'], reverse=True)

Посчитать кол-во уникальных элементов в списке

from collections import Counter
 
ls_hosts = ['a','b','a']
 
print(Counter(ls_hosts).keys())
print(Counter(ls_hosts).values())
 
['a','b']
['2','1']
:!: Работа со строками

Подстановка переменных в строку

#
print(f'{var1}_{var2}')
 
#
print('{}_{}'.format(var1,var2))
:!: Размер шрифта строки
from PIL import ImageFont
 
font_path = "LiberationMono-Regular.ttf"
font_size=300
 
ttf = ImageFont.truetype(font_path, font_size)
 
txt = "Hello World!"
w, h = ttf.getsize(txt)
print(w, h)
:!: Длинна самого длинного слова в строке
longest_word = max(text_in_node.split(), key=len)
:!:
 
:!:
 
develop/pyton/practics.txt · Последнее изменение: 2024/07/15 05:32 — admin