Commit ae09c9
2025-12-07 11:35:16 feagor: -/-| /dev/null .. Python/Выполнение_запроса_по_списку_БД.md | |
| @@ 0,0 1,142 @@ | |
| + | # Выполнение_запроса_по_списку_БД |
| + | ## Настройка Python |
| + | В Python версии 3.7 и выше дополнительно необходимо установить `pip install oracledb, pip install pandas, pip install requests, pip install openpyxl`. |
| + | В Python версии 3.7 и выше cx_oracle не работает, нужен oracledb, при необходимости запуска на Python 3.0-3.7 заменить oracledb на cx_oracle |
| + | |
| + | ## Python 3.7+ Параллельный запуск запроса или скрипта |
| + | ```python |
| + | import oracledb |
| + | import threading |
| + | from pandas import DataFrame |
| + | import datetime |
| + | import os |
| + | import requests |
| + | ########################################################################################## |
| + | ### Список переменных, которые нужно изменить ### |
| + | ########################################################################################## |
| + | # Директория с клиентом Oracle |
| + | oracledb.init_oracle_client(lib_dir=r"D:\instantclient_21_11") |
| + | # Запрос или скрипт в txt файле, который нужно выполнять |
| + | QUERY = open('qry/hidden_par_val.sql').read() |
| + | # Режим выполнения: |
| + | # 0 - выполнение запроса, 1 - выполнение скрипта |
| + | execution_mode = 0 |
| + | # Режим получения списка баз данных: |
| + | # 0 - получение из файла, 1 - получение всех актуальных БД через HTTP-запрос к CDMS |
| + | db_list_mode = 1 |
| + | # Файл с списком БД для db_list_mode=0 |
| + | BASELIST = open('bases/baselist.txt').readlines() |
| + | # Токен для подключения к CDMS для db_list_mode=1 |
| + | api_token = "cdmt@pve!" |
| + | # Логин и пароль для подключения к БД Oracle |
| + | or_usr = 'sys' |
| + | or_pas = '' |
| + | ########################################################################################## |
| + | ### Далее ничего менять не нужно. Результат выполнения будет сохранён в excel файл ### |
| + | ### в директорию output с именем - script_res или query_res и текущей датой ### |
| + | ########################################################################################## |
| + | # Функция для получения списка баз данных через HTTP-запрос к CDMS |
| + | def get_oracle_bases_from_http(): |
| + | db_url = "https://cdms.colvir.ru/api/getactualdb" |
| + | headers = { |
| + | "Content-Type": "application/json", |
| + | "Accept": "application/json" |
| + | } |
| + | |
| + | payload = { |
| + | "api_token": api_token |
| + | } |
| + | try: |
| + | print("Получаем список БД через API") |
| + | response = requests.get( |
| + | db_url, |
| + | headers=headers, |
| + | json=payload |
| + | ) |
| + | response.raise_for_status() |
| + | |
| + | data = response.json() |
| + | print(f"HTTP Status Code: {response.status_code}") |
| + | return [item['con_str'] for item in data] |
| + | |
| + | except requests.exceptions.RequestException as e: |
| + | print(f"Ошибка при выполнении HTTP-запроса: {e}") |
| + | return [] |
| + | except ValueError as ve: |
| + | print(f"Ошибка декодирования JSON: {ve}") |
| + | return [] |
| + | except KeyError as ke: |
| + | print(f"Ошибка в структуре ответа: отсутствует ключ {ke}") |
| + | return [] |
| + | #Очистка экрана |
| + | def cls(): |
| + | os.system('cls' if os.name=='nt' else 'clear') |
| + | |
| + | #выполнение запроса или скрипта |
| + | def exec_qry(idx, con_str): |
| + | print(f"Поток {idx}: обработка {con_str}".ljust(80), end='\r') |
| + | try: |
| + | exc = ' ' |
| + | val = ' ' |
| + | # Условие для установки режима SYSDBA только для пользователя 'sys' |
| + | if or_usr.lower() == 'sys': |
| + | con = oracledb.connect(user=or_usr, password=or_pas, dsn=con_str, mode=oracledb.SYSDBA) |
| + | else: |
| + | con = oracledb.connect(user=or_usr, password=or_pas, dsn=con_str) |
| + | cur = con.cursor() |
| + | cur.execute(QUERY) |
| + | # Выполнение запроса |
| + | if execution_mode == 0: |
| + | for result in cur: |
| + | val = ';'.join(map(str, result)) |
| + | # Выполнение скрипта |
| + | else: |
| + | val = 'Ok' |
| + | cur.close() |
| + | con.close() |
| + | except oracledb.DatabaseError as e: |
| + | error_obj, = e.args |
| + | exc = error_obj.message |
| + | finally: |
| + | base_list.append(con_str) |
| + | value_list.append(val) |
| + | except_list.append(exc) |
| + | return |
| + | #Основной код |
| + | cls() |
| + | # Получение списка баз данных |
| + | BASES = BASELIST if db_list_mode == 0 else get_oracle_bases_from_http() |
| + | if len(BASES) == 0: |
| + | print("Нет БД для обработки. Выходим") |
| + | exit() |
| + | else: |
| + | print(f"Список БД получен, количество БД в списке: {len(BASES)}") |
| + | print("Запускаем многопоточную обработку") |
| + | base_list, value_list, except_list = [], [], [] |
| + | # Запуск потоков для каждой базы данных |
| + | threads = list() |
| + | for BASE in BASES: |
| + | idx = len(threads) |
| + | x = threading.Thread(target=exec_qry, args=(idx, BASE.strip(),)) |
| + | threads.append(x) |
| + | x.start() |
| + | print(f"Все потоки запущены. Количество запущенных потоков:{idx+1}") |
| + | for index, thread in enumerate(threads): |
| + | print(f"Основной поток: ожидаем ответ потока #{index} для БД {BASES[index].strip()}".ljust(80), end='\r') |
| + | thread.join() |
| + | print() |
| + | print(f"Закончили, формируем excel файл ") |
| + | # Генерация имени выходного файла и создание директории, если её нет |
| + | os.makedirs('output', exist_ok=True) |
| + | output_prefix = 'script_res' if execution_mode == 1 else 'query_res' |
| + | date_str = datetime.datetime.now().strftime('%Y%m%d') |
| + | output_filename = f"{output_prefix}-{date_str}-1.xlsx" |
| + | # Проверка на существование файла |
| + | counter = 1 |
| + | while os.path.exists(f"output/{output_filename}"): |
| + | counter += 1 |
| + | output_filename = f"{output_prefix}-{date_str}-{counter}.xlsx" |
| + | df = DataFrame({'База': base_list, 'Результат': value_list, 'Исключение': except_list}) |
| + | df.to_excel(f'output/{output_filename}', sheet_name='sheet1', index=False) |
| + | print(f"Excel файл сформирован: output/{output_filename}") |
| + | ``` |