Ответы пользователя по тегу Python
  • Как получить данные из 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 комментарий
  • Почему бот не выполняет команду повторно?

    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 с теми полями которые можно выцепить.
    Ответ написан
    Комментировать
  • Как прекратить ввод значений по нажатии 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 комментарий
  • Как получать "чистое" значение ячейки в Google Sheets?

    shabelski89
    @shabelski89
    engineer
    Вам нужно просто извлечь значение из JSON. если посмотреть внимательно то перед вами словарь, и нужный элемент получается по ключу.
    А то что Вы делаете описано подробно тут
    ну и в качестве домашнего задания разберитесь по строчкам кода
    response = {'majorDimension': 'COLUMNS', 'range': 'guid!B2', 'values': [['102126989']]}
    response.get('values', 'No key values')
    [['102126989']]
    result = response.get('values', 'No key values')
    type(result)
    <class 'list'>
    result[0]
    ['102126989']
    result[0][0]
    '102126989'
    values = result[0][0]
    values
    '102126989'
    v = response['values'][0][0]
    v
    '102126989'
    import json
    from_google_sheet = '[{"majorDimension": "COLUMNS", "range": "guid!B2", "values": [["1"]]},{"majorDimension": "COLUMNS", "range": "guid!B2", "values": [["2"]]},{"majorDimension": "COLUMNS", "range": "guid!B2", "values": [["3"]]}]'
    json_from_google_sheet = json.loads(from_google_sheet)
    json_from_google_sheet
    [{'majorDimension': 'COLUMNS', 'range': 'guid!B2', 'values': [['1']]}, {'majorDimension': 'COLUMNS', 'range': 'guid!B2', 'values': [['2']]}, {'majorDimension': 'COLUMNS', 'range': 'guid!B2', 'values': [['3']]}]
    type(json_from_google_sheet)
    <class 'list'>
    for values in json_from_google_sheet:
        print(values['values'][0][0])
        
    1
    2
    3
    Ответ написан
    Комментировать
  • Задержка для парсера сайта?

    shabelski89
    @shabelski89
    engineer
    есть вероятность что это JS даёт задержку , вот тут предлагаю элегантное решение

    from bs4 import BeautifulSoup
    from selenium import webdriver
    
    url = "http://legendas.tv/busca/walking%20dead%20s03e02"
    browser = webdriver.PhantomJS()
    browser.get(url)
    html = browser.page_source
    soup = BeautifulSoup(html, 'lxml')
    a = soup.find('section', 'wrapper')
    Ответ написан
    Комментировать
  • Как передать большой файл через сокеты на Python?

    shabelski89
    @shabelski89
    engineer
    Ответ написан
    Комментировать
  • Почему не работает print?

    shabelski89
    @shabelski89
    engineer
    не работает из-за непонимания того что Вы пытаетесь сделать.
    def talk():
      myEmi = input("")  # 1 присваиваем переменной myEmi значение введенное в input (это должно быть имя файла?) а кажется что сюда хотели вводить слово которое нужно искать в файле
      with open(f"BD1/{myEmi}.txt",  "r") as file:  # 2 открытие файла на чтение с именем из п.1
        if file.read() == myEmi:  # 3 file.read() читает содержимое file и возвращает содержимое ввиде строки, а дальше вы сравниваете с введенным словом, которое же почему и в имени файла?! Нужно использовать оператор IN вместо ==, а ещё правильнее прочитать файл так result = file.readlines() , что вернёт список строк и потом уже искать в списке элемент.
          print("Это слово есть!")
          talk()
        else:
          with open(f"BD1/{myEmi}.txt",  "w") as file:
            file.write(myEmi)
            talk()
    talk()   # 0 вызов функции talk()
    Ответ написан
    Комментировать
  • Зачем в python 3 функция format у строк?

    shabelski89
    @shabelski89
    engineer
    f нотация, появилась в питоне 3.6, в более ранних версиях был .format . Функицонально различий нет, есть различие в читаемости и лаконичности, я использую f нотацию.
    Ответ написан
    Комментировать
  • Как считать байт код файла?

    shabelski89
    @shabelski89
    engineer
    Зачем?
    Чтобы считать байт-код файла, его нужно скопилировать.
    пример питон файла
    root@vs1:~/project/test_nuitka# cat test_program.py
    def test():
        print('passed')
    
    if __name__ == "__main__":
        test()

    пример компиляции
    root@vs1:~/project/test_nuitka# python3
    Python 3.7.3 (default, Jan 22 2021, 20:04:44)
    [GCC 8.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import py_compile
    >>> import os
    >>> os.listdir()
    ['include', 'share', 'test_program.py', 'lib64', 'bin', 'pyvenv.cfg', 'lib', 'ping.py']
    >>> py_compile.compile('test_program.py')
    '__pycache__/test_program.cpython-37.pyc'


    полученынй файл перемещаем куда угодно с помощью shutil.

    это если под байт-кодом понималось именно это, а ваш код показывает что нужно просто переместить файл с помощью shutil, вот примеры.
    Ответ написан
    Комментировать
  • Что не так со списком в python?

    shabelski89
    @shabelski89
    engineer
    1e - если используете with, то не нужно закрывать файл явно, при выходе из блока with сам это сделает.
    2е - метод read() возврщает строку, то есть answers - строка, убедиться можно сделав
    print(type(answer))
    уверен что answer[0] - это пробел
    3е - чтобы получить список, нужно вместо read() использовать readlines()
    Ответ написан
    1 комментарий
  • Очиститель файла после знака?

    shabelski89
    @shabelski89
    engineer
    class FileHandler:
        def __init__(self, filename):
            self.filename = filename
    
        def read(self):
            with open(self.filename, 'r', encoding='utf-8') as in_file, \
                    open(f'result_{self.filename}', 'w', encoding='utf-8') as out_file:
                for line in in_file:
                    if line:
                        out_line = self.__parse(line)
                        out_file.write(out_line)
                        out_file.write("\n")
    
        @staticmethod
        def __parse(line):
            result, *_ = line.split(":")
            return result
    
    
    if __name__ == "__main__":
        f = FileHandler(r'yot_file_name')
        f.read()
    Ответ написан
    Комментировать