Задать вопрос
  • Как получить значение в словаре, если не знаешь ключ?

    shabelski89
    @shabelski89
    engineer
    Если Вы уверены в том что в словарь отсортирован как нужно, можно забирать данные из списка.
    d = {235454: 11, 6546464: 43}
    list(d.values())
    [11, 43]
    list(d.values())[0]
    11
    Ответ написан
    Комментировать
  • Как добавлять кнопки в клавиатуру в зависимости от данных из базы данных в Telebot?

    shabelski89
    @shabelski89
    engineer
    Предположим Вы знаете как из sqlite полчать данные, обычно при fetchall() получаем список кортежей, например такой: some_data_from_sqlite = [('one',), ('two',), ('ten',)] .
    а уж клавиатуру сделать проще простого:
    import telebot
    from telebot import types
    
    
    API_TOKEN = ""
    bot = telebot.TeleBot(API_TOKEN)
    
    
    @bot.message_handler(commands=['start'])
    def start(message):
        some_data_from_sqlite = [('one',), ('two',), ('ten',)]  # список кортежей из БД
        buttons_dict = {i: x[0] for i, x in enumerate(some_data_from_sqlite)}
        keyboard = types.InlineKeyboardMarkup()
        back_button = types.InlineKeyboardButton(text="Back", callback_data="MainMenu")
        button_list = [types.InlineKeyboardButton(text=x, callback_data=x) for x in buttons_dict.values()] # callback дата понадобится при обработке нажатий на кнопку, но это уже совсем другая история :)
        keyboard.add(*button_list, back_button)
        bot.send_message(chat_id=message.chat.id, text=message.text, reply_markup=keyboard)
    
    
    if __name__ == "__main__":
        try:
            bot.polling(none_stop=True)
        except Exception as e:
            print(e)
    Ответ написан
    5 комментариев
  • Как получить данные из postgresql в python?

    shabelski89
    @shabelski89
    engineer
    На скорую руку
    import psycopg2
    from datetime import datetime, timedelta
    from pprint import pprint
    
    
    def get_dt(dt: str):
        return datetime.strptime(dt, '%Y%m%d')
    
    
    def get_dt_delta(dt: datetime, s=1, e=4):
        return dt - timedelta(days=s), dt + timedelta(days=e)
    
    
    def execute(config, sql, param=None, select_mode=True):
        connection = None
        try:
            connection = psycopg2.connect(**config)
            cursor = connection.cursor()
            if param:
                cursor.execute(sql, param)
            else:
                cursor.execute(sql)
            if select_mode:
                return cursor.fetchall()
        except Exception as E:
            print(E)
        finally:
            connection.close()
    
    
    def get_devices():
        devices_q = "SELECT * from devices LEFT JOIN devatt on devices.dev = devatt.dev " \
                    "WHERE devatt.att = 'otherinfo' AND devatt.value like '0%'"
        return [x[0] for x in execute(cfg, devices_q)]
    
    
    def generate_rep(devs, period):
        r = {}
        period_dt = get_dt(period)
        period_s, period_e = get_dt_delta(period_dt)
        for dev in devs:
            q = 'SELECT * from rawdata where deveui = %s and time between %s AND %s ORDER BY id DESC'
            rawdata = execute(config=cfg, sql=q, param=(dev, period_s, period_e))
            r[dev] = rawdata
        return r
    
    
    if __name__ == "__main__":
        cfg = dict(user="pguser", password="localpass", host="127.0.0.1", port="5432", database="wan_server")
        devices = get_devices()
        date = '20220308'
        result = generate_rep(devs=devices, period=date)
        pprint(result)


    1. смотрите как правильно работать с датой и временем
    2. не используйте интерполяцию в sql запросе
    Ответ написан
    1 комментарий
  • SQLALCHEMY как организовать работу с сессией?

    shabelski89
    @shabelski89
    engineer
    Без примера кода сложно понять, но я использую декоратор для функций работы с БД.
    def catch_session(func):
        """Decorator for Session"""
        @wraps(func)
        def wrapper(self, *args, **kwargs):
            print(f"Try calling db func: {func.__name__}")
            result = func(self, *args, **kwargs)
            try:
                self.session.commit()
                print(f"Success calling db func: {func.__name__}\n")
            except SQLAlchemyError as e:
                print(f"Error - {e}\n")
                self.session.rollback()
            finally:
                self.session.close()
            return result
        return wrapper


    просто оборачиваете им функцию и он сам делает commit если не было ошибок, если было то rollback и сообщение об ошибке.

    взято отсюда
    Ответ написан
    Комментировать
  • Почему бот не выполняет команду повторно?

    shabelski89
    @shabelski89
    engineer
    Код практически невозможно читать, куча копипастов даже из моих старых ответов :) ).

    На вашем текущем уровне понимания ЯП я бы предложил почистить код.
    выносим БД и все данные в отдельный модуль и наводим порядок.
    tanks_db.py

    import sqlite3
    from sqlite3 import Error
    from time import ctime
    
    
    def post_sql_query(sql_query, database='bazaa.db'):
        with sqlite3.connect(database) as connection:
            cursor = connection.cursor()
            try:
                cursor.execute(sql_query)
            except Error as E:
                print(E)
            result = cursor.fetchall()
            return result
    
    
    def register_user(user_id, username, first_name, last_name):
        user_check_query = f'SELECT * FROM USERS WHERE user_id = {user_id};'
        user_check_data = post_sql_query(user_check_query)
        if not user_check_data:
            insert_to_db_query = f'INSERT INTO USERS (user_id, username, first_name, last_name, reg_date) ' \
                                 f'VALUES ({user_id}, "{username}", "{first_name}", "{last_name}", "{ctime()}");'
            post_sql_query(insert_to_db_query)
    
    
    def user_exists(user_id):
        if get_user_name(user_id) is None:
            return False
        return True
    
    
    def get_user_name(user_id):
        user_check_query = f'SELECT username FROM USERS WHERE user_id = {user_id};'
        result = post_sql_query(user_check_query)
        if result is None:
            return None
        return result[0]
    
    
    
    users_tables = '''CREATE TABLE IF NOT EXISTS USERS 
                            (user_id INTEGER PRIMARY KEY NOT NULL,
                            username TEXT,
                            first_name TEXT,
                            last_name TEXT,
                            reg_date TEXT);'''
    
    post_sql_query(users_tables)
    
    tanks_tables = '''CREATE TABLE IF NOT EXISTS TANKS 
                            (name TEXT PRIMARY KEY, info TEXT, photo TEXT);'''
    
    post_sql_query(tanks_tables)
    tanks = [
        {'name': 'Т-26', 'info': '<======Т-26======>\n\nМасса (т) - 9.26\n\nПрочность - 270 ед.\n\nМощность двигателя (л.с.) - 130\n\nМаксимальная скорость (км/ч) - 36\n\nБронепробиваемость базовым снарядом (мм) - 37-51\n\nУрон базовым снарядом - 26-44\n\nСкорострельность орудия (выстр/мин) - 10.3', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\R09_T-26.png'},
        {'name': 'БТ-2', 'info': '<======БТ-2======>\n\nМасса (т) - 12.93\n\nПрочность - 380 ед.\n\nМощность двигателя (л.с.) - 350\n\nМаксимальная скорость (км/ч) - 44\n\nБронепробиваемость базовым снарядом (мм) - 37-51\n\nУрон базовым снарядом - 38-63\n\nСкорострельность орудия (выстр/мин) - 11.8', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\r08_bt-2_image_resized.png'},
        {'name': 'БТ-7', 'info': '<======БТ-7======>\n\nМасса (т) - 15.34\n\nПрочность - 470 ед.\n\nМощность двигателя (л.с.) - 375\n\nМаксимальная скорость (км/ч) - 45\n\nБронепробиваемость базовым снарядом (мм) - 48-64\n\nУрон базовым снарядом - 45-75\n\nСкорострельность орудия (выстр/мин) - 13.0', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\r03_bt-7_image_resized.png'},
        {'name': 'А-20', 'info': '<======А-20======>\n\nМасса (т) - 18.57\n\nПрочность - 520 ед.\n\nМощность двигателя (л.с.) - 400\n\nМаксимальная скорость (км/ч) - 45\n\nБронепробиваемость базовым снарядом (мм) - 71-97\n\nУрон базовым снарядом - 90-150\n\nСкорострельность орудия (выстр/мин) - 7.8', 'photo': r'C:\\Users\\User\\Desktop\\Bot_WotBlitz\\r12_a-20_image_resized.png'}
    ]
    
    for tank in tanks:
        name = tank['name']
        info = tank['info']
        photo = tank['photo']
        post_sql_query(f'INSERT OR IGNORE INTO TANKS (name, info, photo) VALUES("{name}","{info}","{photo}")')



    далее пишем основную логику, в целом там делов на 1 час, форматирование вывода и наполнение БД сделать.

    tanks_bot.py

    import os.path
    import telebot
    from telebot import types
    from tanks_bd import *
    
    
    API_TOKEN = ""
    bot = telebot.TeleBot(API_TOKEN)
    
    
    def get_photo(path):
        try:
            if os.path.exists(path):
                return open(path, 'rb')
        except Exception as E:
            print(E)
            return False
    
    
    def get_main_keyboard():
        keyboard_main = types.InlineKeyboardMarkup()
        tanks_menu = types.InlineKeyboardButton('Танки', callback_data="Tanks")
        profile_button = types.InlineKeyboardButton('Профиль', callback_data="Profile")
        keyboard_main.add(profile_button, tanks_menu)
        return keyboard_main
    
    
    @bot.message_handler(commands=['start'])
    def get_text_messages(message):
        username = message.from_user.first_name
        register_user(message.from_user.id, message.from_user.username, username, message.from_user.last_name)
        keyboard = get_main_keyboard()
        bot.send_message(message.chat.id, f'Добро пожаловать {username}', reply_markup=keyboard)
    
    
    @bot.callback_query_handler(func=lambda call: True)
    def callback_inline(call):
        if call.data == "MainMenu":
            keyboard = get_main_keyboard()
            username = call.message.chat.first_name
            bot.send_message(call.message.chat.id, f'Добро пожаловать {username}', reply_markup=keyboard)
    
        if call.data == "Profile":
            profile_query = f'SELECT * FROM USERS WHERE user_id = {call.message.chat.id};'
            profile = post_sql_query(profile_query)
            username, first_name, last_name = profile[0]
            keyboard = get_main_keyboard()
            bot.send_message(call.message.chat.id,
                             f'*username*\n{username}\n*first_name*\n{first_name}\n*last_name*\n{last_name}',
                             reply_markup=keyboard)
    
        if call.data == "Tanks":
            tanks_query = f'SELECT distinct(name) FROM TANKS;'
            tanks_result = post_sql_query(tanks_query)
            keyboard = types.InlineKeyboardMarkup()
            back_button = types.InlineKeyboardButton(text="Back", callback_data="MainMenu")
            button_list = [types.InlineKeyboardButton(text=elem[0], callback_data=elem[0]) for elem in tanks_result]
            keyboard.add(*button_list, back_button)
            bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
                                  text=call.message.text, reply_markup=keyboard)
    
        if call.data:
            check_data = f'SELECT name, info, photo FROM TANKS WHERE name = "{call.data}";'
            check = post_sql_query(check_data)
            if check:
                name, info, photo = check[0]
                bot.send_message(call.message.chat.id, f'*Name*\n{name}\n*Info*\n{info}')
                if get_photo(photo):
                    bot.send_photo(call.message.chat.id, get_photo(photo))
                keyboard = get_main_keyboard()
                username = call.message.chat.first_name
                bot.send_message(call.message.chat.id, f'Добро пожаловать {username}', reply_markup=keyboard)
    
    
    if __name__ == "__main__":
        try:
            bot.polling(none_stop=True)
        except Exception as e:
            print(e)


    622853c0baf07174276544.png
    Ответ написан
    Комментировать
  • Как "попросить" python код, при вводе команды " start" автоматически заносить в базу данных айди пользователя?

    shabelski89
    @shabelski89
    engineer
    То что Вы спрашиваете называется авто_инкремент ,
    но он в данном случае не очень нужен, так как user_id уникальный в телеграм, проще использовать в качестве ключа его - смотри пример кода тут. Нужно 1 раз создать таблицу create_tables и потом наполнять её функцией register_user.

    Если же надумаете добавить свой ид на основе автоинкремента, то просто изменить в коде как создаётся таблица и делает инсерт.
    Ответ написан
    Комментировать
  • Как и з телеграм подтягивать телефон?

    shabelski89
    @shabelski89
    engineer
    1 Можно ли сделать так, чтобы в БД подтягивалось имя?
    Да
    2 Можно ли сделать так чтобы в БД подтягивался телефон?
    Телефон можно получить только через запрос, либо человек нажмёт поделиться телефоном, либо нужно сделать кнопку поделиться телефоном
    3 Можно ли сделать так чтобы в БД подтягивался юзернейм?
    Да
    В телеге найти бота @ShowJsonBot и отправить ему сообщение, в ответ вы получит JSON с теми полями которые можно выцепить.
    Ответ написан
    Комментировать
  • Как передать путь до файлов скрипту на питоне через контекстное меню windows?

    shabelski89
    @shabelski89
    engineer
    я тоже думаю что загвоздка в винде, но вопрос как обойти её питоном ?
    может через синглетон ?
    что будет при таком коде ?
    from pdf2image import convert_from_path
    import os
    from sys import argv
    
    
    class SingletonMeta(type):
        """
        Класс Одиночка, для запуска единственного экземпляра
        """
    
        _instances = {}
    
        def __call__(cls, *args, **kwargs):
            if cls not in cls._instances:
                instance = super().__call__(*args, **kwargs)
                cls._instances[cls] = instance
            return cls._instances[cls]
    
    
    class Converter(metaclass=SingletonMeta):
        CONST = 200
        POPPLER_PATH = r'C:\Program Files\poppler-0.68.0\bin'
    
        def convert_file(self):
            """
            Метод для конвертации файла pdf в картинки постранично
            """
    
            print("-" * 50)
            print('Конвертирование файла ', argv[1])
            print("-" * 50)
    
            filepath = argv[1]
            path = os.path.dirname(filepath)
            full_filename = os.path.basename(path)
            filename_without_extension = os.path.splitext(full_filename)[0]
    
            # конвертация и сохранние файлов
            pages = convert_from_path(path, self.CONST, poppler_path=self.POPPLER_PATH)
            if not os.path.isdir(filename_without_extension):
                print("-" * 50)
                print("Конвертирование завершено!")
                print("-" * 50)
                print(f"Создание папки {filename_without_extension} под файлы картинок")
                try:
                    os.mkdir(filename_without_extension)
                except OSError as E:
                    print(E)
            print("-" * 50)
    
            for i, page in enumerate(pages):
                print(f"Сохранение страницы {i + 1} как картинки")
                converted_filename = f"{full_filename}_{i + 1}.jpg"
                page.save(os.path.join(path, full_filename, converted_filename), 'JPEG')
            print("-" * 50)
            print('Сохранение завершено!')
            print("-" * 50)
    
    
    if __name__ == "__main__":
        s = Converter()
        s.convert_file()
    Ответ написан
  • Как узнать какой ip или host?

    shabelski89
    @shabelski89
    engineer
    Это не ip адрес, вот тут минимально доступно написано
    Ответ написан
    Комментировать
  • Как прекратить ввод значений по нажатии CTRL?

    shabelski89
    @shabelski89
    engineer
    import signal
    import time
    
    
    class SigHandler:
        stop = False
    
        def __init__(self):
            signal.signal(signal.SIGINT, self.exit)
            signal.signal(signal.SIGTERM, self.exit)
    
        def exit(self, *args):
            print(signal.strsignal(args[0]))
            self.stop = True
    
    
    if __name__ == '__main__':
        Array = []
    
        signal_handler = SigHandler()
        while not signal_handler.stop:
            Array += input('Input value: ')
            print(Array)
            time.sleep(0.5)
    
        print("Exit")
    Ответ написан
    Комментировать
  • Как указать относительный путь к файлу через внешнюю папку?

    shabelski89
    @shabelski89
    engineer
    >>> import os
    >>> c = os.getcwd()
    >>> c
    'C:\\Users\\ashab'
    >>> d = os.path.split(c)
    >>> d
    ('C:\\Users', 'ashab')
    >>> test_folder = r'C:\Program Files\Common Files\Adobe'
    >>> d_test_folder = os.path.split(test_folder)
    >>> d_test_folder
    ('C:\\Program Files\\Common Files', 'Adobe')
    >>> d_test_folder[0]
    'C:\\Program Files\\Common Files'
    >>>
    Ответ написан
    Комментировать
  • Почему Telegram Bot неполностью форматирует текст?

    shabelski89
    @shabelski89
    engineer
    Sending large text messages

    Sometimes you must send messages that exceed 5000 characters. The Telegram API can not handle that many characters in one request, so we need to split the message in multiples. Here is how to do that using the API:

    from telebot import util
    large_text = open("large_text.txt", "rb").read()
    
    # Split the text each 3000 characters.
    # split_string returns a list with the splitted text.
    splitted_text = util.split_string(large_text, 3000)
    
    for text in splitted_text:
    	tb.send_message(chat_id, text)
    Ответ написан
    Комментировать
  • Как принять поступающий POST запрос на мой сервер?

    shabelski89
    @shabelski89
    engineer
    Самое простое например свой веб на flask
    from flask import Flask
    from flask import request
    
    app = Flask(__name__)
    
    @app.route('/url/', methods = ['GET', 'POST'])
    def handle_request():
        if request.method == 'POST':
            data = request.form
    Ответ написан
    Комментировать
  • Ошибка в tkinker, при нажатии на кнопку, как исправить?

    shabelski89
    @shabelski89
    engineer
    внутри функции save вы её вызываете ещё раз -зачем? и откуда берется link1 тоже не ясно
    def save(link):
        filename = link.split('/')[-1]
        print (filename)
        r = requests.get(link)
        open(filename, 'wb').write(r.content)
        #save(link1) # убираем это
        save_1 = tk.Label(win, text='Desktop cкачан в текущую папку', bg='#CCC', font=('Arial',10))
        save_1.pack()
        save_1.place(x=15, y=200)

    что там про чек-бокс не понятно, нужен полный код программы
    Ответ написан
    6 комментариев
  • В чем заключается ошибка, Python Aiogram?

    shabelski89
    @shabelski89
    engineer
    В трейсе ошибки же написано :
    TypeError: a bytes-like object is required, not '_io.BytesIO'

    new_file.write(dowloaded_file_photo.read())
    или
    new_file.write(dowloaded_file_photo.getvalue())
    Ответ написан
    Комментировать
  • Как узнать количество секций в config.ini заданных пользователем?

    shabelski89
    @shabelski89
    engineer
    Я думаю можно как-то так.
    1) Циклы
    2) Классы
    3) Выполнение и перехват процессов ОС
    4) форматирование вывода - тут ещё нужно подумать над выравниванием

    to do
    1) сейчас реализован разовый запуск и проверка по списку, в идеале чтобы висел непрерывно

    from configparser import ConfigParser
    from enum import IntEnum
    import subprocess
    from datetime import datetime
    import colorama
    from colorama import Fore, Style
    
    
    class Status(IntEnum):
        UP = 1
        DOWN = 2
    
    
    class PingStatus(IntEnum):
        success = 0
        failed = 2
    
    
    class Camera:
        def __init__(self, pos: int, name: str, area: str, ip: str, mac: str):
            self.pos = pos
            self.name = name
            self.area = area
            self.ip = ip
            self.mac = mac
            self.status = None
            self.dt = None
    
        def __repr__(self):
            return "|".join([str(x).ljust(15) for x in vars(self).values()])
    
        def check_status(self):
            result = subprocess.call('ping %s -n 2' % self.ip, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
            if result == PingStatus.success:
                self.status = "\033[4m\033[37m\033[42m{}\033[0m".format(Status.UP.name)
            elif result == PingStatus.failed:
                self.status = "\033[4m\033[37m\033[41m{}\033[0m".format(Status.DOWN.name)
            else:
                self.status = "\033[4m\033[37m\033[41m{}\033[0m".format(Status.DOWN.name)
            self.dt = datetime.now().strftime("%Y.%m.%d %H:%M")
    
    
    if __name__ == "__main__":
        colorama.init()
        print(Fore.YELLOW + 'IP CCTV monitoring system')
        print(Style.RESET_ALL)
        config = ConfigParser()
        config.read('config.ini')
        cams = {config[x]['name']: Camera(pos=int(config[x]['pos']), name=config[x]['name'], area=config[x]['area'],
                                          mac=config[x]['mac'], ip=config[x]['Ip'])
                for x in config.sections() if x.startswith('cam')}
    
        for cam in cams.values():
            cam.check_status()
            print(cam)
    Ответ написан
    1 комментарий
  • Запрос MySql. Как составить выборку из первой таблицы по нескольким параметрам из второй?

    shabelski89
    @shabelski89
    engineer
    То что Вы хотите в представлении нужно фильтровать по OR (или IN) и добавлять фильтр по fruit.
    SELECT  
    FT.ID as ID_fruit, FT.fruit as FT_fruit, PT.ID_Param as D_Param 
    FROM Frut_table FT 
    LEFT JOIN Param_Table PT ON FT.ID = PT.ID_fruit
    WHERE PT.ID_Param IN (10, 20) AND FT.ID IN (1, 3)
    Ответ написан