Как удалить последное сообщение бота
У меня есть бот который выводит файл .pdf и если пользователь находиться в текущей сессии запускается таймер который через 8 секунд выводит новое сообщение. Как удалить сообщение с файлом .pdf после вывода нового сообщения? У меня выдает ошибку message to delete not found.
<code>
@bot.callback_query_handler(func=lambda call: call.data == 'cake')
def cake(call: types.CallbackQuery):
    global flag
    flag = True
    N = 1
    bot.delete_message(message_id=call.message.message_id, chat_id=call.message.chat.id)
    global information
    information.append('Cake')
    markup = types.InlineKeyboardMarkup(row_width=1).add(types.InlineKeyboardButton('Order', callback_data='order'),
                                                         types.InlineKeyboardButton('Main menu', callback_data='main_back'))
    bot.send_document(call.message.chat.id, open(r'file.pdf', 'rb'), caption='Catalog', reply_markup=markup)
    while N:
        sleep(3)
        if not flag:
            break
        sleep(5)
        bot.delete_message(message_id=call.message.message_id, chat_id=call.message.chat.id)
        bot.send_message(call.message.chat.id, 'Have you already chosen which cake you want to order?', reply_markup=markup)
        N -= 1
</code>

delfile = bot.send_document...

bot.delete_message(message_id=document.message_id, chat_id=call.message.chat.id)


Олимпиадная задача, оптимизация кода
Есть олимпиадная задачка, её суть такова:
Дано целое число N. 1 <= N <= 10^9. Необходимо определить количество возможных последовательностей длины N, составленных из символов A, G, T, C при условии, что согласные и гласные буквы в этих последовательностях должны чередоваться. Так как ответ может быть очень большим, вывести его остаток от деления на (10^9 + 7).
Ограничение по времени - 1 секунда.
Есть переборное решение, которое проходит тесты с N < 11:

import itertools

n = int(input())
s = "AGTC"
count = 0
for i in itertools.product(s, repeat=n):
    word = "".join(i)
    flag = True
    if word[0] == "A":
        for ind in range(0, len(word), 2):
            if not word[ind] == "A":
                flag = False
                break
        for ind in range(1, len(word), 2):
            if not flag: break
            if not word[ind] in "GTC":
                flag = False
                break

    if word[0] in "GTC":
        for ind in range(0, len(word), 2):
            if not flag: break
            if not word[ind] in "GTC":
                flag = False
                break
        for ind in range(1, len(word), 2):
            if not flag: break
            if not word[ind] == "A":
                flag = False
                break
    if flag:
        count += 1

print(count)

Проанализировав закономерность в ответах, были определены формулы, которые позволят вычислить ответ за 1 сек. для значений N < 10^4:

n = int(input())
if n % 2 == 0:
    result = 6 * 3 ** (n // 2 - 1)
else:
    result = 4 * 3 ** ((n - 1) // 2)
print(result % (10**9 + 7))

Нужна помощь с нахождением решения, которое не будет превышать лимит времени 1 сек. для N до 10^9.

Проблема в том, что при возведении в степень получается уж очень большое число. Однако оно нам нужно не само по себе, а остаток от деления по указанному модулю. Поэтому можно использовать быстрое бинарное возведение в степень по модулю, в ходе работы которого длинные числа появляться не будут. На ваше счастье, в Python есть готовая функция - это
pow с третьим аргументом.
Формулы ваши, кстати, можно упростить

2*3**(n//2)
4*3**(n//2)

Пример для чётной части, время мгновенное

n = 8888888888
m = pow(3, n//2, 1000000007)
result = (m + m) % 1000000007
print(result)


Как правильно написать данный кусок кода в pyTelegramBotAPI
Всем привет. Пытаюсь на практике изучать питон и написание телеграмм бота. Написал свой код на питоне, все работает, хочу сделать на его основе бота в pyTelegramBotAPI. Довольно много видео по созданию ботов, однако они все однотипные и не совсем понятно как превратить данный кусок кода (подобных кусков много) в жизнь. Через @bot.message_handler(): ?
подскажите как правильно написать данный код в телебота
<code>
def get_english ():
    while True:
        level_of_english = input('Укажите уровень английского 4 или 5. При отсутствии поставить 0. ')
        if level_of_english in ('0', '4', '5'):
            level_of_english = int(level_of_english)
            break
        print('Ввели неправильно!')
    return level_of_english
</code>

Вот так
<code>
@bot.message_handler(commands=['start'])
def start(message: types.Message):
    bot.send_message(message.chat.id, "Укажите уровень английского 4 или 5. При отсутствии поставить 0")
    bot.register_next_step_handler(message, get_level_eng)

def get_level_eng(message: types.Message):
    # проверяем число ли ввел юзер
    if message.text.isdigit():
        if message.text in ('0', '4', '5'):
            print(message.text)
    # если не число, то требуем повтороного ввода
    else:
        bot.send_message(message.chat.id, "Укажите уровень английского 4 или 5. При отсутствии поставить 0")
        bot.register_next_step_handler(message, get_level_eng)
</code>


Взять определенный элемент из списка в списке

a = [[10, 20, 30], [13223, 56, 48996], [156, 684, 9686]]
print(a[:][1])

Выдаст:
[13223, 56, 48996]
Нужно:
[20, 56, 684]
То есть, выбрать первый элемент из всех списков максимально быстрым способом. И как это можно реализовать для numpy array?

есть еще способ:
<code>
a = [[10, 20, 30], [13223, 56, 48996], [156, 684, 9686]]

list(zip(*a))[1]  # (20, 56, 684)
</code>
если вложенные списки могут быть разной длины, то вместо zip берем zip_longest из библиотеки itertools


Django, не понимаю как связать три таблицы моделей
У меня есть три таблицы
Первая таблица:

    class Person(models.Model):
        first_name = models.CharField(max_length=150)
        surname = models.CharField(max_length=150)
        url = models.CharField(max_length=500)
        location = models.CharField(max_length=150)
        last_position = models.CharField(max_length=150)

Вторая таблица:

class Education(models.Model):
    university = models.CharField(max_length=150)
    degree = models.CharField(max_length=150)
    info = models.CharField(max_length=150)
    admission_date = models.DateField()
    graduation_date = models.DateField()

Третья таблица:

class Experience(models.Model):
    company = models.CharField(max_length=150)
    position = models.CharField(max_length=150)
    hiring_date = models.DateField()
    fired_date = models.DateField()
    job_location = models.CharField(max_length=150)
    description = models.CharField(max_length=150)
    person = models.ForeignKey(Person, on_delete=models.PROTECT)

У каждого Person может быть несколько Education и Experience. Как мне правильно организовать взаимоотношения таблиц? Я в тупике, пробовал через foreign_key, но выдавало ошибку об отсутствии поля person_id, хотя оно должно создаваться автоматически. Наведите меня на верный путь, пожалуйста!

<code>
class Person(models.Model):
    first_name = models.CharField(max_length=150)
    surname = models.CharField(max_length=150)
    url = models.CharField(max_length=500)
    location = models.CharField(max_length=150)
    last_position = models.CharField(max_length=150)

class Education(models.Model):
    person = models.ForeignKey('Person', on_delete=models.CASCADE)  # тут связь на внешную таблицу
    university = models.CharField(max_length=150)
    degree = models.CharField(max_length=150)
    info = models.CharField(max_length=150)
    admission_date = models.DateField()
    graduation_date = models.DateField()

class Experience(models.Model):
    person = models.ForeignKey('Person', on_delete=models.CASCADE)  # тут связь на внешную таблицу
    company = models.CharField(max_length=150)
    position = models.CharField(max_length=150)
    hiring_date = models.DateField()
    fired_date = models.DateField()
    job_location = models.CharField(max_length=150)
    description = models.CharField(max_length=150)

</code>
Таким образом можно связать ваши три таблицы. Что касается on_delete - в вашем случае наверное уместнее использовать CASCADE. Механика 'CASCADE' проста - удаляя Person удаляются связные Education и Experience
Ваша ошибка 'об отсутсвии поля person_id' связанна с тем что вы пытаетесь обратиться к объекту модели Person 'person = models.ForeignKey(Person, on_delete=models.PROTECT)' (и она должно уже существовать в бд). Если же вам нужно связать ForeignKey таблицы с нуля, надо обращаться к имени модели 'Person' что бы создать связи. Это если совсем коротко :)


как вывести текст в определенное время
пыталась научиться выводить текст в определенное время на python, но не выходит. Где я ошиблась?
<code>
import datetime
import sys

date_time = datetime.datetime(2022, 9, 26, 21, 20, 0)
today = datetime.datetime.today()

print(date_time)
print(today)

while True:
    if date_time == today:
        print("выведен")
        sys.exit()
    else:
        print("не выведен")
</code>

Моя переменная today брала значение лишь один раз, тогда когда я добавила ее в цикл while, сменила
date_time == today на
date_time > today и переработала логику. Все стало работать верно. Всем огромное спасибо!

import datetime
import sys
import time

date_time = datetime.datetime(2022, 9, 26, 22, 42, 0)
today = datetime.datetime.today()

print(date_time)
print(today)
while True:
    if date_time > today:
        today = datetime.datetime.today()
        print(today)
    else:
        print("Вышло")
        break


Поиск по списку автомобителей
необходимо сделать поиск по списку автомобилей. Чтобы он находил как совпадение большой и маленькой буквы.
Audi A4,audi A5,AUDI a6 A7,BMW X5,VOLVO x60, audi a5
Тоесть из этого списка от должен найти все машины марки Ауди и выписать их.
Сделала такой код, но он не работает, где ошибка?

def search_by_make(all_cars: str) -> list:
 cars = all_cars.split(',')
 make = []
 for car in cars:
    if car.lower() in all_cars.lower():
        return make
    elif car.upper() in all_cars.upper():
        return make

верхняя часть спасибо, решена. По её принципу была сделана другая часть, но надо найти полное совпадение в данном коде:

def search_by_models(all_cars: str, the_models: str) -> list:
cars = all_cars.split(',')
models = []
for model in cars:
    if the_models.lower() in model.lower():
        models.append(model)
return models

print(search_by_models("Audi A4,Audi a4 2021,Audi A40", "A4"))

Код находит даже по частичному совпадению, что является ошибкой.

Из основных ошибок:

В функцию не передается параметр, что именно искать (Audi) и не ищется.
Внутри цикла ищутся все марки автомобилей в начальном тексте
all_cars
Не пополняется список
make
Осуществляется выход из функции после первого же совпадения, всегда возвращая пустой список
make (см. п.2)

Остальные ошибки можно найти сравнив код:

def search_by_make(all_cars: str, the_car: str) -> list:
    cars = all_cars.split(',')
    make = []
    for car in cars:
        if the_car.lower() in car.lower():
            make.append(car) # пополняем список
    return make

all_cars = 'Audi A4,audi A5,AUDI a6 A7,BMW X5,VOLVO x60, audi a5'
print(search_by_make(all_cars, 'AuDi'))

['Audi A4', 'audi A5', 'AUDI a6 A7', ' audi a5']

Можно написать код короче c тем же результатом, например:

all_cars = 'Audi A4,audi A5,AUDI a6 A7,BMW X5,VOLVO x60, audi a5'
print(list(filter(lambda x: 'audi' in x.lower(), all_cars.split(','))))


JOIN INNER. Psycopg2. Python
У меня есть две таблицы: old_prod и new_prod. В обоих есть поле price и prod_id.
Задача: если price из new_prod на 20% меньше чем в old_prod занести целую запись(category, link, price) в третью таблицу good_prod. Из общего у двух товаров - prod_id
Подскажите как это можно сделать одним запросом к БД без вмешательства питона? Спасибо.

INSERT INTO good_prod (category, link, price)
SELECT ???.category, ???.link, ???.price
FROM new_prod
JOIN old_prod USING (prod_id)
WHERE new_prod.price <= old_prod.price * 0.8
;

Поскольку непонятно, из какой таблицы брать значения, поставил знаки вопроса. Нужные алиасы расставляй самостоятельно.
Запрос предполагает, что в обеих таблицах поле
prod_id как минимум уникально.


не работает __setitem__
Создан вот такой класс (сугубо в учебных целях), в котором есть список с координатами точек маршрута и средней скоростью.

class Track:
    def __init__(self):
        self.coords = []

    def add_point(self, x, y, speed):
        self.coords.append(((x, y), speed))

    def verify_indx(self, indx):
        if indx not in range(0, len(self.coords)):
            raise IndexError('некорректный индекс')

    def __getitem__(self, item):
        self.verify_indx(item)
        return self.coords[item]

    def __setitem__(self, key, value):
        self.verify_indx(key)
        lst_coord = list(self.coords[key])
        list(lst_coord)[-1] = value

tr = Track()
tr.add_point(20, 0, 100)
tr.add_point(50, -20, 80)
tr.add_point(63.45, 1.24, 60.34)

tr[2] = 60
c, s = tr[2]

и когда срабатывает строчка
print(c, s) я ожидаю увидеть результат
(63.45, 1.24) 60, но выводится все равно
(63.45, 1.24) 60.34.
В
__setitem__ пробовал вместо
list(lst_coord)[-1] = value написать
lst_coord.insert(-1, value), но тоже все так же. При этом когда в
__setitem__ вставил
print(lst_coord), выдало нужный результат.

Сделайте так:
<code>
def __setitem__(self, key, value):
    self.verify_indx(key)
    self.coords[key] = (self.coords[key][0], value)
</code>


Как правильно встроить цикл while в данную функцию
Немного не понял, как правильно встроить цикл while в данную функцию, условия по циклу не выполняются и продолжения не следует, на этом работа всего кода останавливается
<code>
def get_position ():
    position = input("Укажите Вашу должность 1; 2 ")
    while type(position)  != 1 and type(position) !=2:
        try:
            position = int(position)
        except ValueError:
            print('Ввели неправильно!')
            position = input("Укажите Вашу должность 1; 2 ")
    if position == 1:
        SALARY = 37000
        PIECE_RATE = 822
        PAX_RATE = 800
        INCENTIVE_RATE = 455
        LANDING_RATE = 700
        SAFETY_RATE = 454
    else:
        SALARY = 19000
        PIECE_RATE = 653
        PAX_RATE = 600
        INCENTIVE_RATE = 340
        LANDING_RATE = 422
        SAFETY_RATE = 182
    return (SALARY , PIECE_RATE, PAX_RATE, INCENTIVE_RATE, LANDING_RATE, SAFETY_RATE, position)
</code>

На мой взгляд,
try/except здесь излишни, как и ряд других операций.

# ... предыдущий код
while True:
    position = input("Укажите Вашу должность 1; 2 ")
    if position in ('1', '2'):
        position = int(position)
        break
    print('Ввели неправильно!')
# ... последующий код


Как узнать длину списка без функции len или цикла?
Как с помощью try/assert/except узнать длину списка без функции len, цикла?Возможно так сделать нельзя, но по крайней мере мне в голову ничего путного не приходит.

Вариант 1
Получился абсурдный код, но все условия выполняются :)

узнать длину списка
с помощью try/assert/except
без функции len, цикла

lst = [[1], 2, '3', {4}]
try:
    assert 1 == 0
except:
    print(sum(map(lambda x: 1, lst)))

4

Вариант 2
Еще одна мысль пришла. Если добавить к списку доп. элемент - сам список, то этот элемент будет уникальным и, получив его индекс, мы определим длину списка. Обернуть этот код в
try/assert/except можно по желанию по аналогии с вариантом 1 :)

lst = [[1], 2, '3', {4}]
print((lst+[lst]).index(lst))

4

Вариант 3
Мыслительный процесс продолжается :)
Даже все
try/assert/except при деле

try:
    assert lst != []
    print(list(enumerate(lst))[-1][0] + 1)
except AssertionError:
    print(0)  # для пустого списка


Страницы с url картинками через реакции. Как разделить для пользователей возможности листать независимо?
Данный код позволяет изменять содержание сообщения через нажатие на заранее созданные реакции.
Здесь создана имитация перелистывания страниц с картинками, из бд вызывается url адрес картинки и передаётся в сообщение. По нажатию на кнопки в реакции картинка меняется на следующую в списке.
Происходит по нажатию прибавление или убавление переменной, которая как раз и указывает числом на индекс объекта, вызываемого из списка.
Суть: проблема в том, что переменная v глобальная и если один человек листает такой список, то это происходит для всех. Если объявить переменную внутри функции, то она будет после каждого нажатия на реакцию принимать это значение (ноль) и только затем изменяться, что полностью рушит работу страниц.
Есть ли варианты, как это исправить?
Сохранять url каждый в отдельной переменной или на странице embed'а не вариант, их слишком много будет, необходимо именно из бд брать.
Если есть наглядная документация по новый кнопкам, то это могло бы решить проблему
<code>
    v = 0
    @bot.event
    async def on_raw_reaction_add(payload):
        cur.execute(f"""SELECT URL FROM images ORDER BY nA DESC""")
        art = cur.fetchall()
        user = payload.member
        channel = payload.channel_id
        message = payload.message_id
        channel = bot.get_channel(channel)
        message = await channel.fetch_message(message)
        global v

        if payload.emoji.name == "⬅":
            v += 1
            await message.edit(content=f"{art[v][0]}")
            if user != bot.user:
                for reaction in message.reactions:
                    await reaction.remove(user)

        elif payload.emoji.name == "➡":
            v -= 1
            await message.edit(content=f"{art[v][0]}")
            if user != bot.user:
                for reaction in message.reactions:
                    await reaction.remove(user)
</code>

Я так и не нашёл нормальный и адекватный способ это реализовать, поэтому сделал как любой уважающий себя нелюдь - сделал мега костыль:
<code>
    @bot.event
    async def on_raw_reaction_add(payload):
        user = payload.member
        channel1 = payload.channel_id
        message1 = payload.message_id
        channel = bot.get_channel(channel1)
        message = await channel.fetch_message(message1)

        if f'{message1}' == f'{message1}':
            if payload.emoji.name == "➡":
                if user != bot.user:
                    cur.execute(f"""SELECT v FROM test WHERE id = '{message1}'""")
                    va = cur.fetchone()
                    cur.execute(f"""UPDATE test SET v = {va[0]} + 1 WHERE id = '{message1}'""")
                    adb.commit()

                    cur.execute(f"""SELECT v FROM test WHERE id = '{message1}'""")
                    sss = cur.fetchall()
                    artid = sss[0][0]
                    cur.execute("""SELECT URL from images ORDER BY nA ASC""")
                    art = cur.fetchall()
                    await message.edit(content=f"{artid + 1}\n{art[artid][0]}")
                    for reaction in message.reactions:
                        await reaction.remove(user)

            elif payload.emoji.name == "⬅":
                if user != bot.user:
                    cur.execute(f"""SELECT v FROM test WHERE id = '{message1}'""")
                    va = cur.fetchone()
                    cur.execute(f"""UPDATE test SET v = {va[0]} - 1 WHERE id = '{message1}'""")
                    adb.commit()
                    cur.execute(f"""SELECT v FROM test WHERE id = '{message1}'""")
                    sss = cur.fetchall()
                    artid = sss[0][0]
                    cur.execute("""SELECT URL from images ORDER BY nA ASC""")
                    art = cur.fetchall()
                    await message.edit(content=f"{artid + 1}\n{art[artid][0]}")
                    if user != bot.user:
                        for reaction in message.reactions:
                            await reaction.remove(user)
    ```

И также команда для вызова сообщения с картинками, которые нужно листать. После вызова, id этого поста записывается в бд.
</code>
<code>
@bot.command()
async def nn(ctx):
    await ctx.send('Nyaa')
    last = ctx.channel.last_message_id
    message = await ctx.channel.fetch_message(int(last))
    channel = bot.get_channel(1021497810589339719)
    # message = await channel.fetch_message(1023646768145113230)
    cur.execute(f"""INSERT INTO test (v, id) VALUES ('0', '{last}')""")
    adb.commit()
    cur.execute("""SELECT URL FROM images WHERE nA = '1'""")
    image = cur.fetchone()
    await message.edit(content=f"1\n{image[0]}")
    time.sleep(1)
    await message.add_reaction('⬅')
    await message.add_reaction('➡')
```
</code>
Здесь переменная хранится в базе данных sqlite3 и вместо обычных операции, происходят sql запросы, имитирующие операции с обычными переменными. Это сделано, чтобы "переменная" была независима и разделена на каждый пост. В таблице значение переменных связано с каждым созданным постом, где необходимо листать сообщение.
Чтобы изменялось только нужное сообщение, а не все, я сделал проверку id поста с постом, где поставили реакцию. Если совпадает, то можно менять.
Не рекомендую повторять это, но оно работает.


Как после нажатия кнопки остановить цикл и сменить сообщение
Есть бот который после нажатия кнопки выводит текст и файл .pdf после этого запускаеться бесконечный цикл который каждые 15 минут отсылает сообщение. Как сделать что б после нажатия любой кнопки или ввода команды /start цикл останавливался. И еще одна проблема, после нажатия кнопки 'main_menu' файл .pdf не пропадает и выдает ошибку there is no text in the message to edit. Как сделать что б файл пропал и появились другие кнопки?
<code>
@bot.callback_query_handler(func=lambda call: call.data == 'cake')
def cake(call: types.CallbackQuery):
    markup = types.InlineKeyboardMarkup(row_width=1).add(types.InlineKeyboardButton('Order', callback_data='order'),
                                                         types.InlineKeyboardButton('Main menu', callback_data='main_back'))
#Когда нажимаю main_back это сообщение остается и выводит ошибку
    bot.edit_message_text(message_id=call.message.message_id, chat_id=call.message.chat.id, text='Choose a cake from the catalogChoose a cake from the catalog')
    bot.send_document(call.message.chat.id, open(r'1.pdf', 'rb'), reply_markup=markup)
    while True:
        sleep(15 * 60)
        bot.send_message(call.message.chat.id, 'You already chosen which cake you want to order?', reply_markup=markup)

@bot.callback_query_handler(func=lambda call: call.data == 'main_back')
def main_back(call: types.CallbackQuery):
    global information
    global photo
    global candy
    photo = False
    candy = False
    information.clear()
# Удаляет только документ с кнопками
    bot.delete_message(message_id=call.message.message_id, chat_id=call.message.chat.id)
    bot.clear_step_handler_by_chat_id(chat_id=call.message.chat.id)
    markup = types.InlineKeyboardMarkup(row_width=3).add(
        types.InlineKeyboardButton('Cake', callback_data='cake'),
        types.InlineKeyboardButton('Bento-Cake', callback_data='bento_cake'),
        types.InlineKeyboardButton('Candy', callback_data='candy'),
    )
    bot.edit_message_text(message_id=call.message.message_id,
                          chat_id=call.message.chat.id,
                          text='Choose what you want to order',
                          reply_markup=markup)
</code>

А если так?
<code>
bot.delete_message(message_id=call.message.message_id, chat_id=call.message.chat.id)
bot.clear_step_handler_by_chat_id(chat_id=call.message.chat.id)
markup = types.InlineKeyboardMarkup(row_width=3).add(
    types.InlineKeyboardButton('Cake', callback_data='cake'),
    types.InlineKeyboardButton('Bento-Cake', callback_data='bento_cake'),
    types.InlineKeyboardButton('Candy', callback_data='candy'))
bot.send_message(chat_id=call.message.chat.id,
                 text='Choose what you want to order',
                 reply_markup=markup)
</code>


скопировал начальный код Discord.py и выбивает ошибку: AttributeError: 'Intents' object has no attribute 'message_content' [закрыт]

Закрыт. Этот вопрос не по теме. Ответы на него в данный момент не принимаются.

 Вопрос вызван проблемой, которая больше не воспроизводится, или опечаткой. Хотя похожие вопросы могут быть уместны на этом сайте, решение для этого вопроса вряд ли поможет будущим посетителям. Обычно можно избежать подобных вопросов написанием и исследованием минимальной программы для воспроизведения проблемы до публикации вопроса.

Закрыт 1 год назад.

                        Улучшить вопрос

<code>
import discord
from discord.ext import commands

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='>', intents=intents)

@bot.command()
async def ping(ctx):
    await ctx.send('pong')

bot.run('TOKEN')
</code>
Выводит ошибку:
File "Расположение файла", line 5, in
intents.message_content = True
AttributeError: 'Intents' object has no attribute 'message_content'

Какая версия библиотеки? Проверить можно так:

import discord
print(discord.__version__)

Попробуй обновить:

pip install --upgrade discord.py


Как правильно заменить список, обращаясь к нему, как к ключу в другом списке?

test = [1]
test2 = [test]
test2[0] = [2]
print(test) # [1]

Что нужно сделать, чтобы по итогу изменить не только нулевой индекс у списка
test2, но и само значение списка
test?

Чтобы обратиться к исходному списку, квадратные скобки можно писать подряд. Замените последнее присваивание на:
<code>
test2[0][0] = 2
</code>


Как получить state определенного юзера Aiogram 3
Как получить объект стейта (
FSMContext), дату и сам стейт в aiogram 3?

from aiogram.fsm.context import FSMContext
from aiogram.fsm.storage.base import StorageKey

user_id = ... # юзер айди искомого юзера
chat_id = ... # чат айди, где находится юзер

state_with: FSMContext = FSMContext(
    bot=bot, # объект бота
    storage=dp.storage, # dp - экземпляр диспатчера
    key=StorageKey(
        chat_id=chat_id, # если юзер в ЛС, то chat_id=user_id
        user_id=user_id,
        bot_id=bot.id))

# получение данных
await state_with.get_state()
await state_with.get_data()

await state_with.set_state(AnonFSM.bind) # пример присвоения стейта
await state_with.update_data({"data_name": ...}) # пример добавления данных в дату стейта


Ответ на сообщение Python Telegram bot
Подскажите, пожалуйста, как можно вызвать ответ бота на любое сообщение в боте обратной связи. По примеру:
Пользователь: /start
Бот: Welcome message (Привет)
Пользователь: сообщение
Бот: Feedback message (Ожидайте)
Постарался сделать, через функцию echo, но скорее всего где-то допустил ошибку.
Прикладываю код:
main.py:

from telegram.ext import Updater

from handlers import setup_dispatcher
from settings import TELEGRAM_TOKEN

# Setup bot handlers
updater = Updater(TELEGRAM_TOKEN)

dp = updater.dispatcher
dp = setup_dispatcher(dp)

updater.start_polling()
updater.idle()

settings.py:

import os
from dotenv import load_dotenv, find_dotenv

# Loading .env variables
load_dotenv(find_dotenv())

TELEGRAM_TOKEN = "Тут токен"

TELEGRAM_SUPPORT_CHAT_ID = "Тут айди чата"
TELEGRAM_SUPPORT_CHAT_ID = int(TELEGRAM_SUPPORT_CHAT_ID)

WELCOME_MESSAGE = os.getenv("WELCOME_MESSAGE", "Привет 👋")
FEEDBACK_MESSAGE = os.getenv("FEEDBACK_MESSAGE", "Ожидайте 👋")
REPLY_TO_THIS_MESSAGE = os.getenv("REPLY_TO_THIS_MESSAGE", "REPLY_TO_THIS")
WRONG_REPLY = os.getenv("WRONG_REPLY", "WRONG_REPLY")

handlers.py:

import os

from telegram import Update
from telegram.ext import CommandHandler, MessageHandler, Filters, CallbackContext

from settings import WELCOME_MESSAGE, TELEGRAM_SUPPORT_CHAT_ID, REPLY_TO_THIS_MESSAGE, WRONG_REPLY

def start(update, context):
    update.message.reply_text(WELCOME_MESSAGE) # ответ на /start

    user_info = update.message.from_user.to_dict()

    context.bot.send_message(
        chat_id=TELEGRAM_SUPPORT_CHAT_ID,
        text=f"""
📞 Connected {user_info}.
        """,
    )

def echo(update: Update, context: CallbackContext):
    update.message.reply_text(FEEDBACK_MESSAGE) # тут должен быть ответ на любое сообщение "Ожидайте"

def forward_to_chat(update, context):
    forwarded = update.message.forward(chat_id=TELEGRAM_SUPPORT_CHAT_ID)
    if not forwarded.forward_from:
        context.bot.send_message(
            chat_id=TELEGRAM_SUPPORT_CHAT_ID,
            reply_to_message_id=forwarded.message_id,
            text=f'{update.message.from_user.id}\n{REPLY_TO_THIS_MESSAGE}'
        )

def forward_to_user(update, context):
    user_id = None
    if update.message.reply_to_message.forward_from:
        user_id = update.message.reply_to_message.forward_from.id
    elif REPLY_TO_THIS_MESSAGE in update.message.reply_to_message.text:
        try:
            user_id = int(update.message.reply_to_message.text.split('\n')[0])
        except ValueError:
            user_id = None
    if user_id:
        context.bot.copy_message(
            message_id=update.message.message_id,
            chat_id=user_id,
            from_chat_id=update.message.chat_id
        )
    else:
        context.bot.send_message(
            chat_id=TELEGRAM_SUPPORT_CHAT_ID,
            text=WRONG_REPLY
        )

def setup_dispatcher(dp):
    dp.add_handler(CommandHandler('start', start))
    dp.add_handler(MessageHandler(Filters.chat_type.private, forward_to_chat))
    dp.add_handler(MessageHandler(Filters.chat(TELEGRAM_SUPPORT_CHAT_ID) & Filters.reply, forward_to_user))
    return dp

Буду очень благодарен за помощь

Дополнительно исследовал документацию, относительно части обработчика диалогов в библиотеке, которую я использую. Было найдено следующее решение:
переписать функции def echo и def forward_to_chat, объединив их.

def echo_forward_handler(update, context):
    text = 'Ожидайте'
    context.bot.send_message(chat_id=update.effective_chat.id,
                             text=text)
    forwarded = update.message.forward(chat_id=TELEGRAM_SUPPORT_CHAT_ID)
    if not forwarded.forward_from:
        context.bot.send_message(
            chat_id=TELEGRAM_SUPPORT_CHAT_ID,
            reply_to_message_id=forwarded.message_id,
            text=f'{update.message.from_user.id}\n{REPLY_TO_THIS_MESSAGE}'
        )

Так же в конце был сформирован необходимый dispatcher:

def setup_dispatcher(dp):
    dp.add_handler(MessageHandler(Filters.text & (~Filters.command) & Filters.chat_type.private, echo_forward_handler))
    return dp

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


Как я могу красиво проверить первые символы в строке?
Итак у меня есть команда которую я ввожу допустим
/dosmth -a -b -c file.txt. Я хочу проверять только первые символы строки. У меня есть словарь со строками и значениями к ним, если эта строка в начале команды. find проверяет всю строку, слайсы со сравнениями выглядят немного колхозно. Вот что я хочу в коде:

commands = ["/all": 23, "/dd pc": 19, "/clear": 199, "/dosmth": 1]

command = "/dosmth -a -b smth.txt"

def checkCommand(command:str, commands:dict) -> int:
    ???
    return commandNumber

result = checkCommand(command, commands) # returns 1

У класса
str для такого случая есть функция
startswith(prefix, start, end).

prefix - строка или кортеж строк, наличие которых в начале этой строки нужно проверить

start - индекс начала, откуда следует начать поиск

end - индекс конца, где следует поиск закончить

Сама функция возвращает булево значение (т.е.
True или
False)


Как получить имена списков из списка (python, json)
Как получить все имена списков из списка
perms ?

  {
        "perms": [
          {
              "VIP": [
                {
                  "da": true
                }
              ],
              "admin": [
                {
                  "da": true
                }
              ]
          }
        ]
    }

Попытался сделать так:

for a in data['perms']:
    for i in range(len(a)):
        return a[i]

но получал KeyError 0

import json

js = '''{
        "perms": [
          {
              "VIP": [
                {
                  "da": true
                }
              ],
              "admin": [
                {
                  "da": true
                }
              ]
          }
        ]
    }'''
dct = json.loads(js)

for dicts in dct["perms"]:
    print(dicts.keys())

# dict_keys(['VIP', 'admin'])

for key, value in dct["perms"][0].items():
    print(key, value)

# VIP [{'da': True}]
# admin [{'da': True}]


Хочу сделать рассылку боту телеграмм
Решил сделать рассылку в боте телеграмм. Попробовал код, который сохраняет id пользователя в chatids.txt и потом бот открывает этот файл, берет оттуда id пользователя/групп и рассылает туда сообщения. Но пишет ошибку. Подскажите что не так пожалуйста:

# рассылка в боте
@dp.message_handler(commands=["rass"])
async def rass(message):
    print(message.chat.id)
    with open("chatids.txt", "a+") as chatids:
        print(message.chat.id, file=chatids)

@dp.message_handler(commands=["send"])
async def send(message):
    if message.chat.id == 5317208950:
        for i in open("chatids.txt", "r").readlines():
            bot.send_message(i, "тут типо сообщение которое будет отправляться")

Ошибка

C:\Users\rizny\OneDrive\Рабочий стол\botik\bot.py:113:
RuntimeWarning:
coroutine 'Bot.send_message' was never awaited
bot.send_message(i, "тут типо сообщение которое будет отправляться")
RuntimeWarning:
Enable tracemalloc to get the object allocation traceback

Перед
bot.send_message забыли добавить
await

@dp.message_handler(commands=["send"])
async def send(message):
  if message.chat.id == 5317208950:
    for i in open("chatids.txt", "r").readlines():
      await bot.send_message(i, "тут типо сообщение которое будет отправляться")


Отсортировать строку с сохранением исходных индексов
Есть строка:
<code>
str = [200, 322, 12, 877, 392, 142, 406]
</code>
Как ее можно отсортировать с последующим сохранением индексов?
Желательно, наиболее быстрым вариантом. То есть, чтобы элемент 12, который после сортировки будет стоять на 1 месте, имел индекс 2, а не 0.
Возможно есть способ сделать это через словарь или добавить доп. список с индексами.

Как вариант могу предложить создание структур
{'salary':x, 'id':i} с которыми потом и работать:

ranked_users = [200, 322, 12, 877, 392, 142, 406]

# добавляем id
users_details = [{'salary':x, 'id':i}
  for i,x in enumerate(ranked_users)]

# cортируем
users_details.sort(key=lambda x: x['salary'])

# делаем любой поиск
user_id = next((x['id']
  for x in users_details if x["salary"] == 12 ), None)

# результат
print(user_id) # 2

Вообще, конечно мне сложно представить ситуацию когда о сотрудниках известно только их порядковый номер и зп, и к тому же этих сотрудников столько, что скорость поиска по ним может быть существенна. Но возможно где-то так и есть. Иначе, я бы предложил использовать все же ООП подход, хотя, в рамках представленного вопроса это излишне.


Как сделать правильные проверки discord.py
Я сделал бота, который создаёт логи почти всех действий на сервере, но есть проблема, когда пользователь включает/выключает микрофон, то бот пишет, что он отключился и подключился к серверу, хотя у меня нет даже проверок на это, как избавиться от этого, пытался через
if len(before.channel.members) == len(after.channel.members):, но так не работает.

if before.channel is not None:
        if before.channel.id == 720295133282566176:
            embed=discord.Embed(
                title='',
                description=f'📤 Пользователь {member.mention} покинул AFK канал.',
                color=0xf04848
            )
            embed.set_author(name=f'{member.name}#{member.discriminator}', icon_url=member.avatar_url)
            embed.set_footer(text=f'ID: {member.id} • Сегодня, в {now.hour}:{now.minute}')

            await bot.get_channel(1000781163696230440).send(embed=embed)
        else:
            embed=discord.Embed(
                title='',
                description=f'📤 Пользователь {member.mention} покинул голосовой канал `{before.channel}`',
                color=0xf04848
            )
            embed.set_author(name=f'{member.name}#{member.discriminator}', icon_url=member.avatar_url)
            embed.set_footer(text=f'ID: {member.id} • Сегодня, в {now.hour}:{now.minute}')

            await bot.get_channel(1000781163696230440).send(embed=embed)

    if not before.afk and after.afk == True:
        embed=discord.Embed(
            title='',
            description=f'😴 Пользователь {member.mention} был перемещён в AFK канал.',
            color=0xfaa41b
        )
        embed.set_author(name=f'{member.name}#{member.discriminator}', icon_url=member.avatar_url)
        embed.set_footer(text=f'ID: {member.id} • Сегодня, в {now.hour}:{now.minute}')

        await bot.get_channel(1000781163696230440).send(embed=embed)

    if member.voice and after.afk == False:
        embed=discord.Embed(
            title='',
            description=f'📥 Пользователь {member.mention} присоединился к голосовому каналу `{member.voice.channel}`.',
            color=0x44b37f
        )
        embed.set_author(name=f'{member.name}#{member.discriminator}', icon_url=member.avatar_url)
        embed.set_footer(text=f'ID: {member.id} • Сегодня, в {now.hour}:{now.minute}')

        await bot.get_channel(1000781163696230440).send(embed=embed)

Это происходит из-за того, что функция
on_voice_state_update вызывается каждый раз, когда пользователь обновляет свой
discord.VoiceState, из-за чего она вызывается в том числе когда пользователь выключает микрофон и т.д. Решается это 1м условием
if before.channel != after.channel:

@bot.event
async def on_voice_state_update(member: discord.Member, before: discord.VoiceState, after: discord.VoiceState) -> None:
    if before.channel != after.channel:
        if before.channel is None and isinstance(after.channel, discord.VoiceChannel):
            print(f'member "{member.name}" connected')
        elif isinstance(before.channel, discord.VoiceChannel) and isinstance(after.channel, discord.VoiceChannel):
            print(f'member "{member.name}" moved')
        elif isinstance(before.channel, discord.VoiceChannel) and after.channel is None:
            print(f'member "{member.name}" disconnected')

Кстати для этого нужно включить определённый intent при создании объекта бота:

intents = discord.Intents.default()
intents.voice_states = True
intents.message_content = True
bot = commands.Bot(command_prefix="!!", intents=intents)


Решал сейчас задание егэ, на сайте пишется одно, получается другое, все перепробовал, но все равно не получилось, что я делаю не так?
Обозначим через m & n поразрядную конъюнкцию неотрицательных целых чисел m и n.
Так, например, 14 & 5 = 11102 & 01012 = 01002 = 4(само условие, 2 означает систему счисления)

x = bin(14)[2:]
y = bin(5)[2:]
y = "0" + y
print(x and y)

Вывод моего кода

0101

Так оператор
and - это логическое И, а не побитовое. Для побитового И можете использовать оператор
&. Т.е.

x = 14
y = 5
print(x & y)


Помогите с сортировкой в обратном порядке
Есть список элементов, который нужно отсортировать по последнему значению (Max Korn 98 - по числу в конце):

dogs = ['Cormen Alex 92',' Knuth Donald 98', 'ssad aospdopasd 99', 'Max Korn 98']
dogs = sorted(dogs, key=lambda points: points[-1])
dogs.reverse()
print(dogs)

Вот в такой комбинации вместо:

['ssad aospdopasd 99', ' Knuth Donald 98', ' Max Korn 98', 'Cormen Alex 92']

выдается:

['ssad aospdopasd 99', 'Max Korn 98', ' Knuth Donald 98', 'Cormen Alex 92']

То есть, Max и Knuth поменялись местами. Мне нужно сортировать по убыванию числовых значений.
Просто добавить
reverse=True  не подойдет, тогда значения с одинаковыми баллами поменяются местами, чего бы мне не хотелось.

Вам надо разделить строку по пробелам и преобразовать в число последний элемент результата
<code>
print(sorted(lst, key=lambda x: -int(x.split()[-1])))
</code>


Как получить state.data определенного юзера aiogram
Кратко: пишу камень ножницы бумага для телеграмм бота.
Есть class RPS в нем 4 стейта

Начало игры
Выбор игрока 1
Выбор игрока 2
Финал

Как реализовать выгрузку date из игрока 2?
Код не могу пока прикрепить, готового решения не жду, мне нужно хотя бы понимание, как можно реализовать основную механику на aiogram

Вот так
<code>
user_id = ...
chat_id = user_id # это если данные в ЛС, а не в группе какой-то,
                  # в целом просто ниже подставьте user_id, а не плодите переменные
# обьект стейта
state_with: FSMContext = dp.current_state(chat=chat_id, user=user_id)
# текущий стейт и дата
current_state = await state_with.get_state()
current_data = await state_with.get_data()

await state_with.set_state(...)
# можно так
await state_with.set_data(...) # <- помещать словарь
# а еще можно открыть дату через прокси
async with state_with.proxy() as data:
    data[...] = ...
</code>


Unsupported operand type(s) for /: 'tuple' and 'int'

def get_month_days ():
    month_days = int(input('Введите дней в месяце  '))
    return month_days

def get_position ():
    get_position = int(input("Укажите должность   1; 2 "))
    if get_position == 1:
        SALARY = 37000
        PIECE_RATE = 822
    else:
        SALARY = 19000
        PIECE_RATE = 653
    return SALARY , PIECE_RATE

def get_working_days ():
    working_days = int(input('введи дни рабочие '))
    return working_days

def calculate_salary (SALARY, month_days, working_days,):
    salary = SALARY / month_days * working_days
    return salary

def main():
    month_days = get_month_days ()
    working_days = get_working_days ()
    SALARY = get_position ()
    salary = calculate_salary (SALARY, month_days, working_days)
    print (f'Оклад: {salary:.2f}')

main ()

во время выполнения функции
calculate_salary() ошибка.

Функция
get_position () возращает 'tuple'

SALARY = get_position ()
print(type(SALARY))
print(SALARY)

>> <class 'tuple'>
>> (19000, 653)

распаковка 'tuple'

SALARY, PIECE_RATE = get_position() # SALARY, _ = get_position()
print(type(SALARY))
print(SALARY)

>> <class 'int'>
>> 19000

или

SALARY = get_position()[0]
print(type(SALARY))
print(SALARY)

>> <class 'int'>
>> 19000

Операторы * и ** в Питоне. Что это и как использовать:

SALARY = get_position()
print(*SALARY, sep=', ')

>> 19000, 653


строчки дублируют друг друга, нужно вынести в функцию
только начинаю питон изучать, никак не может дойти как в функцию вывести
<code>
timeline = input("Есть ли свободный график (да / нет): ");
premium_vakancia = input("Является ли данная вакансия премиум-вакансией (да / нет): ");

if timeline == 'да': timeline = True;
elif timeline == 'нет': timeline = False;

if premium_vakancia == 'да': premium_vakancia = True;
elif premium_vakancia == 'нет': premium_vakancia = False;

print(f'{timeline} ({type(timeline).__name__})\n'
  f'{premium_vakancia} ({type(premium_vakancia).__name__})');
</code>

timeline = (timeline == 'да')
premium_vakancia = (premium_vakancia == 'да')


В поле ввода Entry необходимо ограничить ввод символов, кроме всех цифр и точек
Друзья, знаю что такой вопрос уже был с определенным ответом, но в том ответе можно вводить только одну точку, а я нуждаюсь в вводе большего количества, как минимум 3 точек.
И вопрос может и глупый, но я не могу понять, что нужно изменить в коде, что бы можно было вводить также только цыфры, но с большим количеством точек.
Буду очень признателен за ответ(:
вот код :
<code>
import tkinter as tk

window = tk.Tk()
window.title("Okno")

def validate(new_value):
    try:
        if new_value == "" or new_value == "-" or new_value == "+":
            return True
        _str = str(float(new_value))
        return True
    except:
        return False

que = tk.Label(window, text="Введите цифры")

vcmd = (window.register(validate), '%P')
ans = tk.Entry(window, validate='key', validatecommand=vcmd)

que.grid(row=0, column=0, sticky="e")
ans.grid(row=0, column=1)
ans.focus()

window.mainloop()
</code>

Если допустимы только цифры и точки, то меняете функцию валидации таким образом:

import string

def validate(new_value):
    return all(c in string.digits or c == '.' for c in new_value)

Эта функция проверяет, что все символы в строке соответствуют условию

c in string.digits or c == '.' (т.е. символ или цифра (
digit), или точка).
Пустая строка тоже пройдет через это условие. Если пустые строки недопустимы, то нужно добавить дополнительную проверку:

def validate(new_value):
    return new_value and all(c in string.digits or c == '.' for c in new_value)


Не знаю на сколько это правильно, но я решил это таким способом:
<code>
df_groupGr_gID = df_groupGr.groupby(['bg_id'], as_index=False).agg({i: ', '.join for i in ['g_id', 'gs_width', 'gs_height']})
</code>


Реализация функции после завершения процесса [закрыт]

Закрыт. Этот вопрос не по теме. Ответы на него в данный момент не принимаются.

 Вопрос вызван проблемой, которая больше не воспроизводится, или опечаткой. Хотя похожие вопросы могут быть уместны на этом сайте, решение для этого вопроса вряд ли поможет будущим посетителям. Обычно можно избежать подобных вопросов написанием и исследованием минимальной программы для воспроизведения проблемы до публикации вопроса.

Закрыт 1 год назад.

                        Улучшить вопрос

написал telegram бота, который принимает файл от пользователя, сохраняет, загружает его на сервер и дальше должен удалить файл, но выводится ошибка

PermissionError: [WinError 32] Процесс не может получить доступ к файлу, так как этот файл занят другим процессом: 'files/Новый текстовый документ.txt'

Как я понял, в момент, когда файл загружается на сервер, я пытаюсь его удалить и из-за этого возникает конфликт. Загрузка выполняется на сервер другого приложения путём стороннего API. Как можно реализовать выполнение функции
os.remove() после завершения процесса выгрузки на сервер?
Код отвечающий за эти действия:

def upload(message):
    user_file[message.chat.id] = message.document.file_name
    file_info = bot.get_file(message.document.file_id)
    downloaded_file = bot.download_file(file_info.file_path)

    src = 'files/' + message.document.file_name;
    with open(src, 'wb') as new_file:
            new_file.write(downloaded_file)

    c.upload_attachment(sentik, file_path=f'files/{user_file[message.chat.id]}')
    os.remove(f'files/{user_file[message.chat.id]}')

Решение оказалось довольно простым. После записи файла
(
new_file.write(downloaded_file)) его стоило закрыть, используя
new_file.close()


Расставить операторы между числами чтобы получить значение Python
Нужно расставить операторы между num = 99999 - чтобы получить например number = 100. (num,number) могут быть разными. Что я сделал.

import itertools
from itertools import zip_longest

num = 99999
number = 100
mat_zn = '+-*/'

list_mat_zn = list(mat_zn)
list_num = list(str(num))
iter_mat_zn = list(itertools.product(mat_zn, repeat=len(list_num)-1))

res = []
for zn in iter_mat_zn:
    res.append(list(zip_longest(list_num,zn)))

Получил res, укорочен.

res = [[('9', '+'), ('9', '+'), ('9', '+'), ('9', '+'), ('9', None)], [('9', '+'), ('9', '+'), ('9', '+'), ('9', '-'), ('9', None)]]

Дальше пока теряюсь. Теперь нужно каждый i из res превратить в формулу. Избавившись от None(это не проблема)
Можно через перегрузку операторов в классах, но я там не силен. Еще через operator может быть еще?
Какие еще варианты есть более правильные?

from itertools import product, chain, zip_longest

N = 99999
tgt = 90
nstr = str(N)

for var in filter(lambda expr: eval(expr) == tgt,
                  map(lambda ops: ' '.join(chain(*zip_longest(nstr, ops, fillvalue=""))),
                      product('+-*/', repeat=4))):
    print(f'{var}= {tgt}')  # -> 9 + 9 + 9 * 9 - 9 = 90 ...

Немного комментариев к коду, не являющемуся образцом читаемости.
В первую очередь сделан упор на использование генераторных выражений (
product, map, filter) для ухода от материализации всех промежуточных значений.
Описание самого процесса:

product генерирует все возможные комбинации арифметических знаков.

map передает в лямбду каждую комбинацию, где она "сшивается" (
zip_longest) со строковым представлением набора чисел (операндов).
В лямбде фильтра происходит выполнение выражения и сравнение с искомым значением.


Как проверять условие вхождения в цикл внутри тела цикла
<code>
import time
now = time.time()
trial = 1663764660
while True:
    if now < trial:
        print('Работаем')
    else:
        print('Стоп')
        exit(0)
    time.sleep(2)
</code>
Есть простая програмка, которая в цикле while проверяет условие для вхождения в цикл, как можно её переделать что бы условие проверялось прямо во время работы цикла? Чтоб было более понятно приведу пример: сейчас если условие выполняется при старте то каждые 2 секунды выводит в консоль 'Работаем', если нет то 1 раз выводит 'Стоп', то есть или-или а хотелось бы, чтоб условие как-то проверялось во время работы цикла когда он уже печатает 'Работаем' и если оно изменилось то цикл завершался выводом 'Стоп'

Не уверен, что совсем понял задачу, но вроде бы так ...

from time import time, sleep

trial = time() + 6  # + 6 секунд к текущему времени, чтобы отработать трижды по 2 секунды :)
while time() < trial:
    print('Работаем')
    sleep(2)
print('Стоп')

Работаем
Работаем
Работаем
Стоп


Как уникализировать список?
Есть такой список:
<code>
ls = [{'40', '39'},
      {'40', '39'},
      {'78', '82'},
      {'77', '81'},
      {'78', '82'},
      {'77', '81'},
      {'78', '82'}]
</code>
Я могу, конечно, его уникализировать через циклы, но хочется узнать, есть ли стандартный функционал в Python для этого?


заменить for i in range на while
у меня есть код в котором используется for in range
хочу поменять на while

a = int(input('Введите номер билета: '))
sum_left = 0
sum_right = 0
for i in range(6):
    if i < 3:
        sum_right += a // 10**i % 10
    else:
        sum_left  += a // 10**i % 10
if sum_left == sum_right:
    print('lucky')
else:
    print('unlucky')

С while:

a = int(input('Введите номер билета: '))
sum_left = 0
sum_right = 0
i=1
while i <a:
    if i < 3:
        sum_right += a // 10**i % 10
    else:
        sum_left  += a // 10**i % 10
if sum_left == sum_right:
    print('счастливый билет')
else:
    print('обычный билет')

Вы забыли изменение i в конце цикла

i += 1

Кроме того, условие в while неверное. Вероятно, требуется

i = 0

и

while i < 6:


python как обрабатывать ошибки
у меня возникают разные ошибки сети:

SOCKSHTTPSConnectionPool(host='api.celebe.io', port=443): Read timed out. (read timeout=10)

SOCKSHTTPSConnectionPool(host='api.test.io', port=443): Max retries exceeded with url: /resource/v1/feeds/309026/like (Caused by NewConnectionError('<urllib3.contrib.socks.SOCKSHTTPSConnection object at 0x0000023BCF4BA8C0>: Failed to establish a new connection: 0x04: Host unreachable'))

Как я могу через Exceptions понять что это за ошибка и в зависимости от нее выполнять определенные действие?

Вот так можно получить имя ошибки строкой:
<code>
try:
    #Your code here
except Exception as e:
    eName = e.__class__.__name__
    print(eName)

    if eName == 'ValueError':
        print('OMG! it is value error')
</code>


Почему код иногда выдаёт разные результаты при одинаковых данных
На сбоящем этапе код должен считывать сумму модулей отрицательных нечётных элементов столбцов матрицы и записывать эту сумму в одномерный массив. Но он почему-то иногда и вовсе выдаёт отрицательные значения. Ошибка появляется только, если он добавляет число в ненулевой элемент массива. То есть добавляет число в этот элемент во второй раз. Но даже так, ошибка встречается не каждый раз.
При этом, даже стоящие рядом "print (characteristic[j] + -1 * array[i][j])" и "characteristic[j] += -1 * array[i][j];                 print (characteristic[j])" иногда выдают разные ответы.
Чтобы запустить программу, надо ввести размер матрицы. Так как ошибка не появляется при первом добавлении, нужно создать сравнительно большую матрицу, например 13x13.
<code>
from random import(uniform)
import numpy as np
n = int(input('Введите количество строк матрицы'))
m = int(input('Введите количество столбцов матрицы'))
answer = "z"
array = np.zeros((n,m), dtype="int8")
characteristic = np.zeros((m), dtype="int8") # вот тут ошибка
for i in range(n):
    for j in range(m):
        array[i][j] = uniform(-1000, 0)
        if array[i][j] < 0 and array[i][j] % 2 == 1: #ВОТ ЗДЕСЬ ОШИБКА
            print("___")
            print (array[i][j])
            print (characteristic[j] + -1 * array[i][j]) #ВЫВОД СУММЫ
            characteristic[j] += -1 * array[i][j] #СУММИРОВАНИЕ
            print (characteristic[j]) #ВЫВОД ПОСЛЕ СУММИРОВАНИЯ (ИНОГДА ВЫДАЁТ ДРУГОЙ РЕЗУЛЬТАТ. ЧЕМ БОЛЬШЕ МАССИВ, ТЕМ ВЫШЕ ШАНС ВСТРЕТИТЬ ОШИБКУ)
</code>
Пример вывода, где видно, что ошибка произошла лишь один раз:
Введите количество строк матрицы
5
Введите количество столбцов матрицы
5

-119
119
119

-81
81
81

-3
3
3

-65
65
65

-33
114
114

-89
208
-48
** Process exited - Return Code: 0 **
Press Enter to exit termi

Переменная
c получает тип
int64 из-за умножения на
-1. Значение
b[0] имеет тип
int8 - оно хранится в массиве этого типа. Разница из-за приведения первого ко второму:

import numpy as np

a = np.zeros((1, ), dtype="int8")
b = np.zeros((1, ), dtype="int8")
a[0] = 127
for _ in range(10):
    c = b[0] + -1 * a[0]
    b[0] += -1 * a[0]
    print(type(c), c, type(b[0]), b[0])

$ python temp.py
<class 'numpy.int64'> -127 <class 'numpy.int8'> -127
<class 'numpy.int64'> -254 <class 'numpy.int8'> 2
<class 'numpy.int64'> -125 <class 'numpy.int8'> -125
<class 'numpy.int64'> -252 <class 'numpy.int8'> 4
<class 'numpy.int64'> -123 <class 'numpy.int8'> -123
<class 'numpy.int64'> -250 <class 'numpy.int8'> 6
<class 'numpy.int64'> -121 <class 'numpy.int8'> -121
<class 'numpy.int64'> -248 <class 'numpy.int8'> 8
<class 'numpy.int64'> -119 <class 'numpy.int8'> -119
<class 'numpy.int64'> -246 <class 'numpy.int8'> 10


Почему один код работает по-другому относительно другого? [дубликат]

На этот вопрос уже даны ответы здесь:

Почему list.remove() неправильно удаляет элементы в цикле?

                                (2 ответа)

Закрыт 1 год назад.

Напишите программу, которая считывает три числа и подсчитывает сумму
только положительных чисел.
Написал такой код:

nums = [-31, -11, 5]
for i in nums:
    if i < 0:
        nums.remove(i)
print(sum(nums))

На выходе получаю -6, однако должен получать 5.
Если посмотреть итоговый список, то он получается:

[-11, 5]

Не могу понять, почему остаётся -11, когда в переборе значений условием указано убирать отрицательные числа из списка? Почему это работает только для первого значения изначального списка?
Если попробовать код изменить на такой, то все получится адекватно:

a, b, c = -31, -11, 5
result = 0
if a > 0:
    result += a
if b > 0:
    result += b
if c > 0:
    result += c
if a and b and c < 0:
    print(0)
print(result)

Вывод:

5

Вы редактируете список, пока идёте по ниму в for, из за чего программа пропускает второе значение. Решить можно 3мя способами:
1й и самый протой - ввести переменную - итоговую сумму

nums = [-31, -11, 5]
sum = 0
for i in nums:
    if i > 0:
        sum += i
print(sum)

2й - итерироваться не по самому списку, а по его копии (в данном примере она создаётся с помощью nums[:])

nums = [-31, -11, 5]
for i in nums[:]:
    if i < 0:
        nums.remove(i)
print(sum(nums))

3й - Создать новый список и добавлять туда только положительные числа

nums = [-31, -11, 5]
positive_nums = []
for i in nums:
    if i > 0:
        positive_nums.append(i)
print(sum(positive_nums))

# Укороченная версия
# nums = [-31, -11, 5]
# print(sum([i for i in nums if i > 0]))


как развернуть сокращённую запись комманд на Python
есть вот такой код на питоне
<code>
dict = defaultdict(set)

idx = 'one'
val = 'первый'
dict[idx].add(val)
idx = 'two'
val = 'второй'
dict[idx].add(val)
idx = 'three'
val = 'третий'
dict[idx].add(val)
val = 'четвёртый'
dict[idx].add(val)
idx = 'four'
val = 'пятый'
dict[idx].add(val)
idx = 'five'
val = 'шестой'
dict[idx].add(val)
val = 'седьмой'
dict[idx].add(val)
idx = 'six'
val = 'восьмой'
dict[idx].add(val)

n = sum((len(val) > 1) for idx, val in dict.items())
</code>
подскажите как разложить последнюю строку, что бы получился отдельно цикл в котором что то по условию суммируется
ни как не могу найти объяснения как такое можно сделать

Инициализируем нашу переменную

n = 0

Переписываем наш итератор:

for idx, val in dict.items():

Переписываем тело цикла:

n += len(val)>1

Соединяем

n = 0
for idx, val in dict.items():
    n += len(val)>1

Дополнение:

Вместо
idx, val in dict.items() тут следует написать
val in dict.values()
Не стоит называть переменные зарезервированными словами (
dict,
list,
set, ...)


Проблемы с созданием многоуровнего inline меню в aiogram
Не работает inline меню
random_markup. Первое меню работает отлично (ну как меню, в данных случаях просто одна кнопка, но это не столь важно), а вот уже с меню, которое должно появится после нажатия на
btnRandom возникают проблемы. Что я сделал не так, что второе меню не появляется?

bot = Bot(TOKEN)
dp = Dispatcher(bot)

@dp.message_handler(commands=["random"])
async def process_random(message: types.Message):
    markup = InlineKeyboardMarkup(row_width=1).add(InlineKeyboardButton(text="Рандомное число", callback_data="btnRandom"))
    # markup.add(InlineKeyboardButton(league, callback_data=f"prefix:{league_cd}"))
    await message.answer("Пожалуйста, выберите из списка:", reply_markup=markup)

@dp.callback_query_handler(text_startswith="btnRandom")
async def random_button(callback: types.CallbackQuery):
    data = callback.data
    await callback.answer()
    if data == "btnRandom":
        async def randomizer(message: types.Message):
            random_markup = InlineKeyboardMarkup(row_width=1).add(InlineKeyboardButton(text="Вы выбрали рандом", callback_data="Random"))
            await callback.message.answer("Рандомное меню:", reply_markup=random_markup)

        @dp.callback_query_handler(text_startswith="Random")
        async def random_selected(callback: types.CallbackQuery):
            await callback.message.answer("Вы выбрали рандомное число", reply_markup=random_markup)
            await callback.answer()
    else:
        await callback.message.answer("Вы выбрали другой вариант, но выберите рандом")

if __name__ == "__main__":
    executor.start_polling(dp, skip_updates=True)

Ужас у вас какой-то
<code>
@dp.message_handler(commands=["random"])
async def process_random(message: types.Message):
    markup = InlineKeyboardMarkup(row_width=1).add(
        InlineKeyboardButton("Рандомное число", callback_data="btnRandom"))
    # markup.add(InlineKeyboardButton(league, callback_data=f"prefix:{league_cd}"))
    await message.answer("Пожалуйста, выберите из списка:", reply_markup=markup)

# зачем тебе text_startswith? У тебя же четкий btnRandom, а не какой-то так btnRandom:123
@dp.callback_query_handler(text_startswith="btnRandom")
async def random_button(callback: types.CallbackQuery):
    await callback.answer()
    # зачем это условие? для кого оно? Если хендлер сработал значит дата и будет равана этому значению
    # data = callback.data
    # if data == "btnRandom":
    # а это что за бесмысленная функция? Убери ее
    # async def randomizer(message: types.Message):
    #     random_markup = InlineKeyboardMarkup(row_width=1).add(
    #         InlineKeyboardButton(text="Вы выбрали рандом", callback_data="Random"))
    #     await callback.message.answer("Рандомное меню:", reply_markup=random_markup)
    markup = InlineKeyboardMarkup().add(
        InlineKeyboardButton("Вы выбрали рандом", callback_data="Random"))
    await callback.message.answer("Рандомное меню:", reply_markup=markup)

# и не запихивай хендлер внурь другого хендлера НИКОГДА
@dp.callback_query_handler(text="Random")
async def random_selected(callback: types.CallbackQuery):
    await callback.answer()
    markup = InlineKeyboardMarkup().add(
        InlineKeyboardButton("Вы выбрали рандом", callback_data="Random"))
    await callback.message.answer("Вы выбрали рандомное число", reply_markup=markup)
</code>


Как на языке Python сделать Telegram бота, который будет рассылать сообщения другим пользователям Телеграма, зная TelegramID этого пользователя?
Подскажите, пожалуйста, как на Python сделать Telegram бота, который будет рассылать сообщения другим пользователям Телеграма, зная  TelegramID этого пользователя?

Телеграм-бота, который первый отправляет сообщения, создать невозможно. К боту сначала должен обратиться пользователь. Это предусмотрено телеграмом для контроля спам рассылок. Воспользуйтесь библиотекой telethon для питона. (там есть некоторые примеры). Но это уже будет не бот, а аккаунт.


Как научить юзер-бот группировать вложения в альбом при пересылке сообщений из канала в канала в телеграме с библиотекой telethon python
Вот код:
<code>
client = TelegramClient('anon', API_ID, API_HASH)

@client.on(events.NewMessage(chats=CHANNELS))
async def main(event):
await client.send_message(MY_CHANNEL_ID, event.message)

client.start()
client.run_until_disconnected()
with client:
    client.loop.run_until_complete(main())
</code>
В таком варианте, при пересылке сообщения с множеством вложений разбиваются на отдельные сообщения, а нужно, чтобы пересылался альбом+текст.

Если сообщение является группой нескольких сообщений (альбом из фото или видео), у всех этих сообщений будет одно и то же значение атрибута
grouped_id.
Если же сообщение не альбом, например, одно изображение, или одно видео, значением атрибута
grouped_id будет
None. Вы можете использовать это как проверку.
Сами альбомы можно обрабатывать с помощью специального декоратора
events.Album.

# Декоратор который обрабатывает альбомы c указанных каналов
@client.on(events.Album(chats=CHANNELS))
async def new_album(event):
    await client.send_message(
        entity=MY_CHANNEL_ID, # Канал на который перешлется сообщение
        file=event.messages, # Список сообщений (изображений) из альбома
        message=event.text, # Текст сообщения
    )


код по алгоритму Иосифа Флавия (последний выживший) выдает неправильные результаты с большими числами
Попытался написать программу на нахождение последнего в списке числа. Вводится число n (количество человек) и k (каждый k из списка удаляется). С маленькими числами программа работает корректно, но с большими (например 50 и 25) выдает неправильный ответ. Подскажите пожалуйста что не так)
Прикладываю код:
<code>
n = int(input())
k = int(input())
m = [i for i in range(1, n + 1)]
while len(m) > 1:
    del m[(k - 1) % len(m)]
    m = m[(k - 1) % len(m):] + m[:(k - 1) % len(m)]
print(*m)
</code>

вот вы удалили
(k - 1) % len(m) элемент

del m[(k - 1) % len(m)]

а зачем вы дальше формируете новый массив таким образом

m = m[(k - 1) % len(m):] + m[:(k - 1) % len(m)]

при этом используя новую длину массива
попробуйте так (для теста привел другой код алгоритма)

n = 50 #int(input())
k = 25 #int(input())
m = list(range(1, n + 1))
while len(m) > 1:
    x = (k - 1) % len(m)
    del m[x]
    m = m[x:] + m[:x]
print(*m)

def f(n , m):
    return 1 if n == 0 else 1 + (f(n - 1, m) + m - 1) % n

print(f(n, k))


Возврат значения из цикла без его завершения
Подскажите можно ли как то возвращая элемент из цикла его на этом не прекращать а продолжать выполнение? Пишу асинхронную программу, нужно вернуть
element из функции и продолжить её выполнять, пробовал в очередь его класть, но она до конца работы не доступна так же(через
queue.put(element))

def my_fun()
    for element in elements:
        return element

my_fun()

Пример через
yield:

def my_fun():
    for element in range(5):
        print(f"Создаем элемент {element}")
        yield element

for item in my_fun():
    print(f"Принимаем элемент {item}")

Вывод:

Создаем элемент 0
Принимаем элемент 0
Создаем элемент 1
Принимаем элемент 1
Создаем элемент 2
Принимаем элемент 2
Создаем элемент 3
Принимаем элемент 3
Создаем элемент 4
Принимаем элемент 4


Как в Python упрощать математические выражения с неизвестными переменными?
Пример:
1,75 * x / 1,2 - math.sqrt(x) + (1 - 0,43 * x)
Как упрощать выражения такого типа в Python?

Можно использовать модуль
sympy (
pip install sympy).
При создании выражения он автоматически частично его упрощает:

from sympy import sqrt, Rational
from sympy.abc import x

f = 1.75 * x / 1.2 - sqrt(x) + (1 - 0.43 * x)
print(f)

Вывод:
-sqrt(x) + 1.02833333333333*x + 1
Чтобы избавиться от периодической десятичной дроби, можно преобразовать все значения с плавающей точкой в объекты
Rational (рациональные дроби, т.е. например
Rational("1.75") превратится в дробь
7/4):

f = Rational("1.75") * x / Rational("1.2") - sqrt(x) + (1 - Rational("0.43") * x)
print(f)

Вывод:
-sqrt(x) + 617*x/600 + 1
Для упрощения более сложных выражений можно использовать функцию
symplify. Пример из документации:

from sympy import simplify, cos, sin
from sympy.abc import x, y

a = (x + x**2)/(x*sin(y)**2 + x*cos(y)**2)
print(a)  # (x**2 + x)/(x*sin(y)**2 + x*cos(y)**2)
print(simplify(a))  # x + 1


Как используя keyboard ставить медиа на паузу и обратно?
По типу:
<code>
import keyboard
keyboard.send("next track")
</code>

К сожалению, никак, но можете использовать
pyautogui (
pip install pyautogui). В документации в самом низу можно найти список клавиш, для эмуляции, в том числе нужные вам ("playpause", "prevtrack", "nexttrack") и другие
Вот пример испльзования
pyautogui

import pyautogui # Добавляем pyautogui

pyautogui.press("playpause") # Нажимаем кнопку паузы/воспроизведения


Телеграмм бот. Не приходит результат выполнения функции
При нажатии кнопки "Повторы" должен приходить результат выполнения функции. Функция у меня - это sql запрос. В терминале ответ приходит. Не понимаю как мне осуществить это. Бот присылает ошибку, что сообщение пустое. И как я понимаю, ошибка в том, что сначала должна выполниться функция, но я не понимаю как это реализовать

@bot.message_handler(content_types=["text"])
def handle_text(message):
    if message.text.strip() == 'Повторы':
       bot.send_message(message.from_user.id, repetition())

Функция

def repetition():
    conn = cx_Oracle.connect (username, password, HOST+":"+PORT+"/"+SERVICE_NAME)

    print('Connecting!')
    cursor = conn.cursor()

    sql = q1

    cursor.execute(sql)
    alldata = cursor.fetchall()

    for i in alldata:
        print(i[0])
    cursor.close()
    conn.close()

Нужно переделать функцию для сборка данных в строку и ее вернуть
Пример:

def repetition() -> str:
    conn = cx_Oracle.connect (username, password, HOST+":"+PORT+"/"+SERVICE_NAME)

    print('Connecting!')
    cursor = conn.cursor()

    sql = q1

    cursor.execute(sql)
    alldata = cursor.fetchall()

    lines = []
    for i in alldata:
        lines.append(str(i[0]))
    cursor.close()
    conn.close()

    return '\n'.join(lines)

В одну строку:

    lines = [str(i[0]) for i in alldata]

Без списка:

    return '\n'.join(str(i[0]) for i in alldata)


Как прибавлять числа из списка до определённого значения? [закрыт]

Закрыт. Этот вопрос не по теме. Ответы на него в данный момент не принимаются.

 Учебные задания допустимы в качестве вопросов только при условии, что вы пытались решить их самостоятельно перед тем, как задать вопрос. Пожалуйста, отредактируйте вопрос и укажите, что именно вызвало у вас трудности при решении задачи. Например, приведите код, который вы написали, пытаясь решить задачу

Закрыт 1 год назад.

                        Улучшить вопрос

Я недавно начал изучать свой первый ЯП Python. Появилась такая задача:
например имеется список

a = [1, 2, 4, 8, 16, 32, 64]
Нужно прибавить эти числа так, что бы получилось число 221.
Так же нужен вывод тех чисел, что были прибавлены. В данном случае это: 64 64 64 16 8 4 1. Как это правильно реализовать? Буду благодарен за ответы.

если  нет других ограничений, то алгоритм такой:

идем от большего значения к меньшему
определяем сколько в сумму входит указанных значений
вычитаем это кол-во, умноженное на значение, из суммы

вопрос в том, гарантирует ли такой способ решения задачи нахождение результата (потому что задача может сводиться к перебору)
результат не всегда (если он существует) будет оптимальным (минимальное кол-во слагаемых)


Поочередное суммирование элементов списка Python [закрыт]

Закрыт. Этот вопрос не по теме. Ответы на него в данный момент не принимаются.

 Учебные задания допустимы в качестве вопросов только при условии, что вы пытались решить их самостоятельно перед тем, как задать вопрос. Пожалуйста, отредактируйте вопрос и укажите, что именно вызвало у вас трудности при решении задачи. Например, приведите код, который вы написали, пытаясь решить задачу

Закрыт 1 год назад.

                        Улучшить вопрос

Дан список из чисел A. На выходе необходимо получить список B с суммой всех предыдущих чисел списка A включая число итерируемого индекса.
Например:
На входе:

А=[0,1,2,3,4]

На выходе:

B=[0,1,3,6,10]

вариант 1:

B = [sum(A[:i + 1]) for i in range(len(A))]

вариант 2:

s = 0
B = [s := s + v for v in A]

вариант 3:

from functools import reduce

B = reduce(lambda r, v: r + [r[-1] + v] if r else [v], A, [])

вариант 4:

B = list(map(lambda v: sum(A[:v[0]]) + v[1], enumerate(A)))

или

*B, = map(lambda v: sum(A[:v[0]]) + v[1], enumerate(A))

вариант 5:

def func(A):
    return (func(A[:-1]) + [sum(A)]) if A else []

B = func(A)

вариант 6:

from itertools import accumulate

B = list(accumulate(A))

или

from itertools import accumulate

*B, = accumulate(A)

вариант 7:

import numpy

B = numpy.add.accumulate(A)


Проблема с inline меню в aiogram
При нажатии на любую кнопку из inline меню срабатыватывает не та, которая нужна, а срабатывают все так как на всех кнопках появляются часики. Как это исправить?
<code>
@dp.message_handler(commands=["leagues"])
async def process_leagues(message: types.Message):
    leagues = [("Премьер-лига", "premier_league"), ("Бундеслига", "bundesliga"), ("Бундеслига-2", "bundesliga-2"), ("Чемпионшип", "championship")]
    markup = InlineKeyboardMarkup(row_width=1)
    for league, league_cd in leagues:
        markup.add(InlineKeyboardButton(league, callback_data="prefix:league_cd"))
    await message.answer("Лиги", reply_markup=markup)
</code>

Замени это

callback_data="prefix:league_cd"

На это

callback_data=f"prefix:{league_cd}"


Проверка по внешнему ключу не работает SQLite3 при вводе через discord
Есть три таблицы со связью Многие ко Многим, две primary key и одна связующая их с каскадным обновлением и удалением.
Для удобства понимания:

CREATE TABLE tag_art (
    artID INT NOT NULL
              REFERENCES art (idA) ON UPDATE CASCADE
                                   ON DELETE CASCADE,
    tagID TEXT NOT NULL
              REFERENCES tag (idT) ON UPDATE CASCADE
                                   ON DELETE CASCADE,
    CONSTRAINT fk_tagart PRIMARY KEY (
        artID,
        tagID
    )
);

Если я в sqlite studio или консоль ввожу
INSERT INTO tag_art (artID, tagID) VALUES (1, 'test'), то это не сработает, потому что в таблице tag нет значения test в столбце idT. Всё выполняется правильно. Если вместо test введу существующее значения, то оно позволит такой ввод данных.
Суть: это перестаёт работать, если тот же самый запрос поступает не напрямую, а через discord чат и команду.
Пример:

import discord
from discord.ext import commands
import sqlite3

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix = '!', intents=intents)

with sqlite3.connect("name.db") as adb:
    cur = adb.cursor()

    @bot.command()
    async def test(ctx):
        cur.execute(f"""INSERT INTO tag_art (artID, tagID) VALUES
        ('1', 'test')
        """)
        adb.commit()
        await ctx.send("Данные успешно приняты!")

bot.run('token')

Такой ввод оно пропускает и вводит значение test, обходя ограничение через внешний ключ, хотя запрос идентичный.
Но если ввести уже существующее значение, то оно его заблокирует и не даст выполнить команду, а значит проверка всё же работает, но только частично.
Если вручную затем в программе попробовать изменить это значение на другое неподходящее, то не позволит, как и должно быть.
Если у вас есть идеи почему так происходит, как discord обходит ограничение foreign key и как это можно решить, буду рад любому ответу по делу.

Мне удалось найти решение проблемы. Дело в том, что в SQLite3 необходимо включать проверку ограничения по внешним ключам каждый раз, иначе оно будет пропускать любые значения.
Решается буквально одной строчкой, после подключения к базе:
<code>
with sqlite3.connect("name.db") as adb:
    cur = adb.cursor()
    cur.execute("PRAGMA foreign_keys = ON;")
</code>
Теперь всё работает верно и выдаёт ошибку, если ввести несуществующие значения.
Уверен, многим поможет данная информация.


Поиск одинаковых символов идущих подряд (от 2 до 9)
Всем привет!
Написал функцию, которая проверяет наличие одинаковых цифр идущих подряд, и показывает количество таких блоков.
Выдаёт список с циферками которые показывают сколько блоков есть и по сколько повторений в каждом.
Но меня не оставляют мысли, что можно было сделать это аккуратнее и компактнее.
Подскажите есть какие то библиотеки, функции, регулярки для подобного рода задач?
<code>
def check_repeat_digits(55533):
    a = 0
    score = 0
    score_mass = []
    sid = str(id)
    for i in sid:
        try:
            # проверка среза есть ли в нём дубликаты and предотвращаем выход за границы
            if len(set(sid[a:a+2])) == 1 and a < len(sid)-1: если ОК то
                score += 1
            # если блок одинаковых цифр прервался, заносим инфу в список, и обнуляемся
            elif score > 0:
                # +1 что бы корректно отображалось кол-во символов в блоке
                score_mass.append(score+1)
                score = 0
            else:
                a += 1
                continue
        except:
            exit()
        a += 1
    print(score_mass)

>>> [3, 2]
</code>

используйте регулярку

import re

res = re.findall(r"((\d)\2{1,})", "5551888337771234555")

print(res)

если вам надо искать не 2 и больше, а N и больше символов, то укажите кол-во символов в
{1,}

(от 2 до 9)

будет означать
{1,8}
т.е. ваш код будет выглядеть так:

import re

def check_repeat_digits(value):
    return [len(obj[0]) for obj in re.findall(r"((\d)\2{1,8})", str(value))]


Принятие сообщений в личных сообщениях discord.py
Увидел как чужой бот принимает сообщения из личных сообщений, хочу также.
Суть: пишешь допустим "лол" в личные сообщения боту, он все принимает, а если написал в канале на сервере, то бот игнорил. Короче чтобы принимал сообщения и откликался только в лс. Использовать нужно
async def on_message(message)

<code>
import discord
from discord.ext import commands

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix = '!', intents=intents)

@bot.event
async def on_message(message):
    await bot.process_commands(message)
    if not message.guild:
        await message.author.send("Необходимое ответное сообщение")

bot.run('token')
</code>
Если возникнут вопросы - задавайте. Код проверил, работает.
В случае, если необходимо сделать ответ на конкретную фразу или слово, просто добавьте ещё одно условие с проверкой этого слова или фразы.


Labmda. Конструкция python

arr = [0, 2, 3, 4, -6, -7, -10]

def count_positives_sum_negatives(arr):
    count_pos = 0
    count_neg = 0
    lambda for x in arr: count_pos + 1 if x >= 0 else count_neg + (-1*(x))
    return [count_pos, count_neg*-1]

Выход

Traceback (most recent call last):
  File "/workspace/default/tests.py", line 2, in <module>
    from solution import count_positives_sum_negatives
  File "/workspace/default/solution.py", line 4
    lambda (for x in arr): count_pos + 1 if x >= 0 else count_neg + (-1*(x))
           ^
SyntaxError: invalid syntax

Что делаю не так?
Мне необходимо посчитать количество положительных элементов и сумму отрицательных элементов.
Я решил сделать это через итерацию внутри lambda. Перебирая элементы и добавляю нужные значения в переменные.
Количество элементов не определено.

Пишем "нормальный вариант":

def count_positives_sum_negatives(arr):
    positive_count = 0
    negative_sum = 0
    for x in arr:
        if x<0:
            negative_sum += x
        elif x>0:
            positive_count += 1
    return [negative_sum, positive_count]

Понимаем, что в лямбду если и получиться переписать, то выглядеть это будет очень-неочень.
Но если на производительность можно забить:

negative_sum  = sum(filter(lambda x: x<0, arr))
positive_count = len(list(filter(lambda x: x>0, arr)))

Или так:

negative_sum = sum(x for x in arr if x<0)
positive_count = len([x for x in arr if x>0])

UPD:
Лямба

n, p = (lambda: [sum(x for x in arr if x<0), len([x for x in arr if x>0])])()


В PywinAuto операции с объектами интерфейса некоторых приложений выполняются долго (15-20 секунд). Как можно оптимизировать это?
Всем привет. Может кто сталкивался. Помогите опитимизировать.
В PywinAuto операции с найденными элементами для некоторых приложений выполняются достаточно долго. Например, после того как элемент найден, click_input() по нему выполняется через 9-15 секунд. Отслеживаю дебагом - поиск выполняется достаточно быстро (менее секунды), а вот на самой операции 15-20 секунд. Причем не важно какая операция. Еще пример, операция type_keys(), сама печать - все быстро, а вот перед началом операции печати пауза 15 сек
Приложение desktop карта. При просмотре с помощью inspector элементов приложения достаточно много. Может с этим связано? Есть какие-то варианты оптимизации? Заранее спасибо
Пример кода

search_bar = main_window.child_window(auto_id="FullNameBox", class_name='RadWatermarkTextBox') search_bar.click_input()

Дело в том, что первая строка ещё не выполняет поиск, а только создаёт поисковый объект. Поиск неявно вызывается при попытке вызвать метод
click_input. Чтобы вызвать явно поиск, нужен метод
.wrapper_object() или
.wait('ready', timeout=10). Например:

search_bar = main_window.child_window(auto_id="FullNameBox", class_name='RadWatermarkTextBox').wrapper_object()
search_bar.click_input()

Причём
main_window - скорее всего тоже поисковый объект (типа
WindowSpecification), и по нему поиск запускается в первую очередь. Правда, текущая реализация не позволяет создавать
WindowSpecification от враппера. Попозже сделаем в следующем большом релизе. Есть разные трюки, чтобы оптимизировать поиск:

Не использовать доступ по атрибуту, а юзать только
child_window(...)
Юзать чаще
class_name или
control_type (для
backend="uia"), потому что предварительная фильтрация по типу контрола сильно быстрее, чем по тексту. Если текст есть в критерии, то по нему поиск будет в последнюю очередь, то есть уже среди мЕньшего числа элементов. Получение текста - самая дорогая операция.
Можно ещё ограничивать поиск в глубину параметром
depth=1, но тогда надо больше уровней поиска делать.


Как сделать, чтобы при изменении данных в одном словаре, во втором всё оставалось прежним?
Есть кусок кода:
<code>
import time

class Name:
    def __init__(self, settings: dict) -> None:
        self.settings = eval(str(settings))

    def update(self):
        self.settings["key"] = time.time()

settings = {"key":"value"}
SettingsClass = Name(settings)
print(id(settings) == id(SettingsClass.settings))  # 1 output
while id(settings) != id(SettingsClass.settings):
    SettingsClass.update()
    if SettingsClass.settings != settings:
        print('test') #2 output
        settings = SettingsClass.settings
</code>
Выполнение кода принесет:
False
test
Я где-то видел что, class принимая значения dict|list|tuple, берет только ссылку на переменную. А мне нужно чтобы это были 2 независимые переменные. Чтобы при изменении данных в одном словаре, во втором всё оставалось прежним до тех пор, пока не дойдет очередь до изменения. То есть: чтобы settings не изменялась вместе с SettingsClass.settings, пока не дойдет до кода settings = SettingsClass.settings (хотя именно из-за такого приравнивания, id становаятся одинаковыми и именно в этот момент копируется только ссылка на эту переменную).

Есть два варианта:

Использовать конструктор - подойдет, если у вас в словаре нет вложенных
dict | list | tuple.

class Name:
    def __init__(self, settings: dict) -> None:
        self.settings = dict(settings)

    def update(self):
        self.settings["key"] = time.time()

Использовать
copy.deepcopy - следует использовать, если есть вложенные
dict | list | tuple

import copy

class Name:
    def __init__(self, settings: dict) -> None:
        self.settings = copy.deepcopy(settings)

    def update(self):
        self.settings["key"] = time.time()


Как вернуть 2 значения? (PYTHON)
У меня есть такой код, я хочу вернуть 2 значения
True и
nick, но вот еще, возможно ли при вызове функции выбрать значение, которое хочешь вернуть (например
True)

 def c_nick(id_user):
     with open('nicks.txt') as json_file:
         data = json.load(json_file)
         for i in data['users']:
             if i['id'] == int(id_user):
                 nick = i['nick']
                 return True

Ну можно как-то так сделать:

def c_nick(id_user, ret: ('both', 'bool', 'nick') = 'both'):
    with open('nicks.txt') as json_file:
        data = json.load(json_file)
        for i in data['users']:
            if i['id'] == int(id_user):
                nick = i['nick']
                match ret:
                    case 'both':
                        return (True, nick)
                    case 'bool':
                        return True
                    case 'nick':
                        return nick

Примеры:

c_nice(id_, 'both') # (True, nick)
c_nice(id_, 'bool') # True
c_nice(id_, 'nick') # nick


Как с помощью discord.py отправлять сообщения в чат без команд?
Бот может реагировать на сообщения, а как сделать так, чтобы он сам писал с некоторой периодичностью?

<code>
import discord
import time
from discord.ext import commands

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix = '!', intents=intents)

@bot.event
async def on_ready():
    channel = bot.get_channel(ID текстового канала)
    while True:
        time.sleep(10) #### время в секундах, как часто отсылать
        await channel.send("Отправляемое сообщение")

bot.run('сюда укажите token')
</code>
Проверил, работает исправно. Спрашивайте, если возникнут вопросы.


Словарь Python. Вывод ключа по значению, но есть повторяющиеся значения
Есть словарь, состоящий из пар вида [слово : приоритет в строке]. Слова требуется расставить в порядке приоритета в словаре. Проблема в том, что я не могу придумать, как извлекать слово по его приоритету. Можно было бы реверсировать словарь и извлекать элементы по ключу, но тогда теряются слова с одинаковым приоритетом, например, [таким : 0.6, нашей : 0.6].
Словарь для отладки использую следующий:
<code>
[таким : 0.6, образом : 0.571, постоянное : 0.5,
обеспечение : 0.45, нашей : 0.6, деятельности : 0.5]
</code>
Если возможно сортировать словарь по значению, т.е. в данном случае по приоритету, это будет довольно хорошим решением, но пока мне не удалось реализовать такую сортировку.
.

Попробуйте так:

sorted(dic, key=lambda x: dic[x])

Этот пример сортирует по возрастанию, если вам нужно наоборот то так:

sorted(dic, key=lambda x: dic[x], reverse=True)

(
dic - это ваш словарь)


Как перезапускать скрипт в случае ошибки?
<code>
def do_some_work():   # Функция с периодически запускающимся 'скриптом'

     print("Hello, World!")

while True:   # Бесконечный цикл в котором
    do_some_work()   # Мы запускаем основной код
</code>

Воспользуйся механизмом исключений:
<code>
def do_some_work():   # Функция с периодически запускающимся 'скриптом'
    print("Hello, World!")

while True:   # Бесконечный цикл в котором
    try:
        do_some_work()   # Мы запускаем основной код
    except:
        print(f'some error')
</code>


Как правильно делать запись в json (PYTHON)
Привет, я хотел бы реализовать свою идею с никнеймами.
У меня есть json, но проблема в том, как правильно туда записывать данные?
nicks.txt
<code>
{
    "players": [
        {
            "user_319990365": [
                {
                    "nick" : "developer"
                }
            ],
            "user_1": [
                {
                    "nick" : "admin"
                }
            ]
        }
        ]
}
</code>
Как вы наверное поняли, мне надо в "players" создать "user_АЙДИЮЗЕРА" с параметрами "nick": "текст".

Если вы храните данные в словаре, то воспользуйтесь библиотекой
json

import json

# Data to be written
dictionary ={
    "name" : "sathiyajith",
    "rollno" : 56,
    "cgpa" : 8.6,
    "phonenumber" : "9976770500"
}

with open("sample.json", "w") as outfile:
    json.dump(dictionary, outfile)

Исходик примера


Сокращение кода открытия файлов Python
Мне нужно сократить код:

@my_bot.message_handler(content_types='text')
def get_text(message):
    str_1 = 'привет'
    txt_1 = random.choice(list(open('answer1.txt', 'r', encoding='utf-8')))
    str_2 = 'как дела'
    txt_2 = random.choice(list(open('answer2.txt', 'r', encoding='utf-8')))
    str_3 = 'что делаешь'
    txt_3 = random.choice(list(open('answer3.txt', 'r', encoding='utf-8')))
    str_4 = 'расскажи интересный факт'
    txt_4 = random.choice(list(open('answer4.txt', 'r', encoding='utf-8')))
    str_5 = 'не устал работать'
    txt_5 = random.choice(list(open('answer5.txt', 'r', encoding='utf-8')))
    text_1 = set(str_1.split())
    text_2 = set(str_2.split())
    text_3 = set(str_3.split())
    text_4 = set(str_4.split())
    text_5 = set(str_5.split())
    inp = set(set(message.text.lower().split()))
    if inp & text_1:
        my_bot.send_message(message.chat.id, txt_1)
    elif inp & text_2:
        my_bot.send_message(message.chat.id, txt_2)
    elif inp & text_3:
        my_bot.send_message(message.chat.id, txt_3)
    elif inp & text_4:
        my_bot.send_message(message.chat.id, txt_4)
    elif inp & text_5:
        my_bot.send_message(message.chat.id, txt_5)

У меня получилось так:

@my_bot.message_handler(content_types='text')
def get_text(message):

    txt_1 = random.choice(list(open('answer1.txt', 'r', encoding='utf-8')))
    f1 = set('привет')
    f2 = set('как дела')
    f3 = set('что делаешь')
    f4 = set('расскажи интересный факт')
    f5 = set('не устал работать')
    inp = set(set(message.text.lower()))
    if inp & f1:
        my_bot.send_message(message.chat.id, txt_1)
    elif inp & f2:
        my_bot.send_message(message.chat.id, txt_1)
    elif inp & f3:
        my_bot.send_message(message.chat.id, txt_1)
    elif inp & f4:
        my_bot.send_message(message.chat.id, txt_1)
    elif inp & f5:
        my_bot.send_message(message.chat.id, txt_1)

Помогите, пожалуйста, как можно сократить код открытия файлов?

txt_1 = random.choice(list(open('answer1.txt', 'r', encoding='utf-8')))
txt_2 = random.choice(list(open('answer2.txt', 'r', encoding='utf-8')))
txt_3 = random.choice(list(open('answer3.txt', 'r', encoding='utf-8')))
txt_4 = random.choice(list(open('answer4.txt', 'r', encoding='utf-8')))
txt_5 = random.choice(list(open('answer5.txt', 'r', encoding='utf-8')))

Вы не сократили, а вот что сделали:

str_3 = 'что делаешь'
text_3 = set(str_3.split()) # {'что', 'делаешь'}
f3 = set('что делаешь') # {'е', ' ', 'ч', 'о', 'а', 'ь', 'ш', 'т', 'л', 'д'}

Чтобы сократить нужно писать так:

f3 = set('что делаешь'.split())

Чтобы сократить обращения к файлам - вынесите это в отдельную функцию:

def choice_from_file(path):
    with open(path, 'r', encoding='utf-8') as file:
        choice = random.choice(list(file))
    return choice

txt_1 = choice_from_file('answer1.txt')

set(set(...)) - бесполезная конструкция. одного
set всегда достаточно.


Не получается получить переменную в JSON (PYTHON)
nicks.txt

{
    "players": {
        "name": "users",
        "user_319990365": [
            {
                "id": 319990365,
                "nick": "developer"
            }
        ]
    }
}

Как получить "nick"?
пытался сделать так... (извините, если очень коряво :D )
main.py

async def check_nick(id_member=319990365):
    with open('nicks.txt') as json_file:
        data = json.load(json_file)
        for x in data['players']:
            for y in x['user_{0}'.format(id_member)]:
                return y

,но выскакивала ошибка:

TypeError: string indices must be integers

Цикл с итерацией по 'players' не нужен. Кроме того, не нужен async, потому что нету асинхронных операций. И да, безусловный return на первой же итерации второго цикла выглядел довольно странно — заменил на yield для примера.

def check_nick(id_member=319990365):
    with open('nicks.txt') as json_file:
        data = json.load(json_file)
        for y in data['players']['user_{0}'.format(id_member)]:
            yield y['nick']

Хм... но если немного подумать, кажется, у вас в исходных данных есть ошибка. Если 'players' был бы массивом в
[], то тогда ваши исходные циклы сработали бы.


Навести указатель мыши в pywinauto на элемент, не поддерживающий click()
Всем привет. Подскажите, есть ли возможность в pywinaouto получить координаты rectangle() и записать их в переменные?

Получить координаты курсора - даже не в pywinauto, а в пакете pywin32, от которого pywinauto зависит:

import win32gui
(x, y) = win32gui.GetCursorPos()

А если нужна середина элемента, то

app.MainWindow.OKButton.rectangle().mid_point()
# возвращает объект класса POINT с полями x и y

Сделать натуральный клик на середину элемента:

app.MainWindow.OKButton.click_input()

При желании можно кликать не в середину, передав параметры
coords=(x, y) и
absolute=False.


Как сделать, чтобы бот отвечал на текстовые сообщения Inline кнопками?
Мне надо отправить боту, например, название города, а он чтобы в ответ присылал мне для каждого города свое меню с Inline кнопками и т.д.
Мне подсказали пример кода:

import telebot
from telebot import types

bot = telebot.TeleBot('TOKKEN') #здесь должен быть токкен вашего бота

@bot.message_handler(commands=['start', 'menu'])
def Welcom(message):
 mesg = bot.send_message(message.chat.id, f"Привет, {message.from_user.first_name}. Введите Ваш город")
 bot.register_next_step_handler(mesg, city) #здесь бот ждёт пока пользователь введёт что либо в чат

def city(message):
  if message.text == 'Москва': #здесь мы указываем то что должен ввести пользователь
    bot.send_message(message.chat.id, 'Москва ваш город') #если пользователь ввёл нужное слово или фразу то бот отправит это сообщение
  else:
     bot.send_message(message.chat.id, 'Мне не удалось ничего найти') #если пользователь ввел что-то не то бот отправит это сообщение

bot.polling(none_stop=True)

и сказали, что чтобы Inline кнопки в ответ добавить, их нужно прописать после "if message.text == 'Москва':" , я это делаю, выглядит это вот так:

    def city(message):
  if message.text == 'Москва':
      markup = types.InlineKeyboardMarkup()
      button1 = types.InlineKeyboardButton('Кнопка 1', callback_data='1')
      button2 = types.InlineKeyboardButton('Кнопка 2', callback_data='2')
      markup.row(button1)
      markup.row(button2)
      bot.send_message(message.chat.id, 'Москва ваш город')
  else:
      bot.send_message(message.chat.id, 'Мне не удалось ничего найти')

но после запуска бота кнопки все равно не отображаются. Что мне делать и как вывести Inline кнопки?

Вы же не отправляете кнопки даже
<code>
if message.text == 'Москва':
    markup = types.InlineKeyboardMarkup()
    button1 = types.InlineKeyboardButton('Кнопка 1', callback_data='1')
    button2 = types.InlineKeyboardButton('Кнопка 2', callback_data='2')
    markup.row(button1)
    markup.row(button2)
    bot.send_message(message.chat.id, 'Москва ваш город', reply_markup=markup)
</code>


Не сохраняются данные в FSM Aiogram
Пишу телеграм бот на aiogram.
Eсть FSM которая записывает 2 состояния.
Есть колбек хэндлер, в котором нужно реализовать проверку состояний которые записал выше FSM.
Как это можно реализовать?
Вот здесь загрузил часть кода с этими FSM и нужным колбэком.
Почему-то он не понимает, что находится в
data после записи в FSM

class Form(StatesGroup):
    firstname = State()
    lastname = State()
    reg_state_open = State()
    reg_state_closed = State()

# Close reg now button

@dp.callback_query_handler(text_contains = 'close_now')
async def close_now(message: types.CallbackQuery):
    if message.data == 'close_now':
        await bot.send_message(chat_id=message.message.chat.id, text='Введите 1, чтобы закрыть дальнейшую регистрацию.')
        await Form.reg_state_closed.set() # Далее вводим 1
        await message.answer()

@dp.message_handler(state=Form.reg_state_closed)
async def reg_state_open(message: types.Message, state: FSMContext):
    async with state.proxy() as data1:
        data1['reg_state1'] = int(message.text) # сохраняю состояние 1 в data1['reg_state1']
        await message.answer(text='Регистрация успешно отключена 1')
        print('1:', data1['reg_state1'])
        await state.finish()

# Open reg now button

@dp.callback_query_handler(text_contains = 'open_now')
async def close_now(message: types.CallbackQuery):
    if message.data == 'open_now':
        await bot.send_message(chat_id=message.message.chat.id, text='Введите 0, чтобы открыть дальнейшую регистрацию.')
        await State.set(Form.reg_state_open) # Далее вводим 0
        await message.answer()

@dp.message_handler(state=Form.reg_state_open)
async def reg_state_closed(message: types.Message, state: FSMContext):
    async with state.proxy() as data2:
        data2['reg_state2'] = int(message.text) # сохраняю состояние 0 в data2['reg_state2]
        await message.answer(text='Регистрация включена 0')
        print('0:', data2['reg_state2'])
        await state.finish()

# как в этом колбекхэндлере проверить записанные выше два состояния (1 и 0). Например, если выше я ввел 0 - выполняется проверка 0 ли в data2['reg_state2], если 0 то дальше можно выполнить регистрацию, если же проверка говорит, что там 1 - регистрация недоступна и этот хэндлер выдает сообщение об этом:

# 'Online registration' button from /start menu

@dp.callback_query_handler(text_contains = 'reg')
async def donate (message: types.CallbackQuery):
    if data1['reg_state1'] == 0:
        if not db.exists_list(message.message.chat.id): # проверка существования пользователя в БД с помощью функции db.exists_list
            await bot.send_message(chat_id=message.message.chat.id, text='Для регистрации введите своё имя.')
            await State.set(Form.firstname) # далее вводим имя
            await message.answer(text='')
        else: # если пользователь существует в БД, то выводим:
            await message.answer('Вы уже зарегистрированы')
    else: # data2['reg_state2'] == 1 ? (если рега off то выдаем сообщение:)
        await message.answer('Регистрация уже отключена.')
        await message.answer()

Вам просто нужно сделать некоторые данные не стираемыми всякими
finish,
reset_state.
Вот так примерно. Код не проверял. По идее должно работать.

import typing

from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import StatesGroup, State

import config

# теперь все переменные в дате которые начинаются с _ будут нестираемыми
class GMemoryStorage(MemoryStorage):
    async def reset_state(self, *,
                          chat: typing.Union[str, int, None] = None,
                          user: typing.Union[str, int, None] = None,
                          with_data: typing.Optional[bool] = True):
        await self.set_state(chat=chat, user=user, state=None)
        if with_data:
            new_data = {}
            old_data = await self.get_data(chat=chat, user=user)
            for key, value in old_data.items():
                if key.startswith("_"):
                    new_data[key] = value

            await self.set_data(chat=chat, user=user, data=new_data)
        self._cleanup(chat, user)

bot = Bot(token=config.BOT_TOKEN)
storage = GMemoryStorage()
dp = Dispatcher(bot, storage=storage)

class Form(StatesGroup):
    firstname = State()
    lastname = State()
    reg_state_open = State()
    reg_state_closed = State()

# Close reg now button
# почему именно text_contains? У вас же вроде точное сравнение должно быть
# @dp.callback_query_handler(text_contains='close_now')
@dp.callback_query_handler(text='close_now')
async def close_now(call: types.CallbackQuery):
    # называйте переменные адекватно, колбек - callback_query/callback/call, сообщение - message/msg
    # в идеале делать такой ансвер в начале колбека, чтобы он наверняка сработал
    await call.answer()
    # зачем второй раз проверка?
    # if call.data == 'close_now':
    # нет смысла усложнять себе жизнь юзая bot.send_message если
    # вы отправляете сообщение в этот же чат
    # await bot.send_message(chat_id=call.message.chat.id, text='Введите 1, чтобы закрыть дальнейшую регистрацию.')
    await call.message.answer('Введите 1, чтобы закрыть дальнейшую регистрацию.')
    await Form.reg_state_closed.set()  # Далее вводим 1

@dp.message_handler(state=Form.reg_state_closed)
async def reg_state_open(message: types.Message, state: FSMContext):
    # hint: рекомендую сделать проверку, написал ли юзер число
    async with state.proxy() as data:
        # добавляем _ перед перменной
        # вместо int(message.text) делаем просто True
        data['_reg_off'] = True

    await message.answer('Регистрация успешно отключена 1')
    # смысл его сохранять если вы тут же делате finish?
    # UPD. теперь смысл есть
    await state.finish()

# Open reg now button
@dp.callback_query_handler(text='open_now')
async def close_now(call: types.CallbackQuery):
    await call.answer()
    # то же  самое
    # if message.data == 'open_now':
    # await bot.send_message(chat_id=message.message.chat.id, text='Введите 0, чтобы открыть дальнейшую регистрацию.')
    await call.message.answer('Введите 0, чтобы открыть дальнейшую регистрацию.')
    await State.set(Form.reg_state_open)  # Далее вводим 0

@dp.message_handler(state=Form.reg_state_open)
async def reg_state_closed(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        # если регистрацию не отключали то просто удалим данные из даты
        del data['_reg_off']
        await message.answer('Регистрация включена')
        await state.finish()

# 'Online registration' button from /start menu
@dp.callback_query_handler(text='reg')
async def donate(call: types.CallbackQuery, state: FSMContext):
    await call.answer()

    async with state.proxy() as data:
        # если True то регистрация отключена
        if data.get('_reg_off') is True:
            await call.answer('Регистрация уже отключена.')
        # иначе включена
        else:
            # проверка существования пользователя в БД с помощью функции db.exists_list
            if not db.exists_list(call.message.chat.id):
                await call.message.answer('Для регистрации введите своё имя.')
                # await bot.send_message(chat_id=call.message.chat.id, text='Для регистрации введите своё имя.')
                await State.set(Form.firstname)  # далее вводим имя
            else:  # если пользователь существует в БД, то выводим:
                await call.answer('Вы уже зарегистрированы')

if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)