Как запустить планировщик aioschedule для нескольких юзеров одновременно
Пишу бот-напоминалку на aiogram2, столкнулся со следующей проблемой:
Мой бот записывает данные в две таблицы. Данные о пользователе в одну, данные о его расписании в другую. Когда пользователь завершает ввод всех необходимых данных, в хендлере должен запускаться планировщик, который отсылает ему расписание на день в нужное время, когда расписание заканчивается - планировщик должен прекращать свою работу, а пользователь заново вводить часть данных. При этом программа не должна останавливаться.
Все работает как нужно, пока пользователь один, но как только их становится 2 и больше - программа начинает вести себя неожиданным для меня образом - при выводе данных, вместо вывода расписания на один день, программа выводит столько расписаний, сколько пользователей подключаются, иногда больше.
Подозреваю, что нужно либо создать отдельный поток и запускать планировщик там, либо что то еще.
В силу того, что в программировании я любитель, у меня не получается найти решение проблемы.
Вот мой код, буду признателен за помощь) :
<code>
import time
from datetime import datetime, timedelta
import pytz  # таймзоны
from timezonefinder import TimezoneFinder  # поиск timezone по широте и долготе
import re
from config import TOKEN
import asyncio
import aioschedule
from database_create import DataBase

from aiogram import Bot, Dispatcher  #      _______________________________      импортируем классы бот и диспетчер
from aiogram.utils.executor import start_polling  # _______________________      импортируем бесконечный опрос
from aiogram.dispatcher.filters import Command, CommandStart, StateFilter, Text  # импортируем нужные типы фильтров
from aiogram.dispatcher.filters.state import State, StatesGroup  #  __________   имортируем состояния и группу состояний
from aiogram.dispatcher.filters.state import default_state  #      __________    импортируем состояние по умолчанию
from aiogram.dispatcher.storage import FSMContext  #     ___________________     импортируем класс хранения контекста
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram import types  #     __________________________________________      импортируем типы данных

# функция перерасчета времени по часовому поясу
def determining_user_time(entered_time: str, lng: str, lat: str) -> str:
    hours, minutes = entered_time.split(':')
    entered_time = timedelta(hours=int(hours), minutes=int(minutes))

    tz_str_user: str = TimezoneFinder().timezone_at(lng=lng, lat=lat)

    timezone_server = pytz.timezone('Asia/Oral')  # 'Europe/Moscow'
    timezone_user = pytz.timezone(tz_str_user)

    dt = datetime.utcnow()
    offset_server = timezone_server.utcoffset(dt)
    offset_user = timezone_user.utcoffset(dt)

    if offset_server > offset_user:
        diference = offset_server - offset_user
        user_local_time = entered_time + diference
    elif offset_server < offset_user:
        deference = offset_user - offset_server
        user_local_time = entered_time - deference
    else:
        user_local_time = entered_time

    hours = user_local_time.seconds // 3600
    minutes = (user_local_time.seconds // 60) % 60
    return f'{hours}:{minutes}'

################################ Функция, которую запускает планировщик ########################
# функция отправки сообщения для планировщика
async def reminder(bot: Bot, chat_id, state: FSMContext):
    print('reminder работаеt')
    with DataBase(path_db='bot_reminder.db') as db:
        reminder = db.query_data('SELECT * FROM weekday WHERE id_person = ?', (chat_id,))[0][1:]
        days = [name[0] for name in db.cursor.description][1:]
        days_reminder = [(k, v) for k, v in zip(days, reminder) if v]
        if days_reminder:
            day, text  = days_reminder.pop(0)
            db.execute(f'UPDATE weekday SET {day} = ? WHERE id_person = ?', (None, chat_id))
            db.commit()
            await bot.send_message(chat_id=chat_id, text=text)
        else:
            await bot.send_message(chat_id=chat_id, text='Ваше расписание на неделю закончилось.\n'
                                                         'Что бы установить новое:\n'
                                                         'Введите время ежедневного напоминания в формате чч:мм')
            await state.set_state(FSMstates.fill_time.state)
            aioschedule.clear()
            db.execute('DELETE FROM weekday WHERE id_person = ?', (chat_id,))
            db.execute('DELETEFROM person WHERE person_id = ?', (chat_id,))
            db.commit()
#####################################################################################

# Создаем объекты
storage: MemoryStorage = MemoryStorage()  # хранилище состояний
bot: Bot = Bot(token=TOKEN)  # бот
dispatcher: Dispatcher = Dispatcher(bot=bot, storage=storage)  # диспетчер

# Cоздаем класс, наследуемый от StatesGroup, для группы состояний нашей FSM
class FSMstates(StatesGroup):
    fill_geolocation = State()  # состояние ожидания отправки геолокации
    fill_time = State()  # состояние ожидания корректного времени
    fill_reminder = State()  # состояние ожидания заполнения расписания

@dispatcher.message_handler(CommandStart, state=default_state)
async def start_bot(message: types.Message, state: FSMContext):
    print('start_bot')

    with DataBase(path_db='bot_reminder.db') as db: # создаем базу данных и таблицы, если их нет
        db.execute('''CREATE TABLE IF NOT EXISTS person
                    (person_id INTEGER PRIMARY KEY, time_reminders TEXT, latitude REAL, longitude REAL)''')
        db.execute('''CREATE TABLE IF NOT EXISTS weekday(
                            id_person INTEGER PRIMARY KEY,
                            Monday TEXT,
                            Tuesday TEXT,
                            Wednesday TEXT,
                            Thursday TEXT,
                            Friday TEXT,
                            Saturday TEXT,
                            Sunday TEXT,
                            FOREIGN KEY(id_person) REFERENCES person(person_id))
                        ''')
        db.commit()

    markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
    markup.add(types.KeyboardButton(text='Отправь геолокацию', request_location=True))
    await message.answer(text='Бот начал работу. Отправь свою геолокацию, что бы бот мог определить твой часовой пояс',
                         reply_markup=markup)
    await state.set_state(FSMstates.fill_geolocation.state)

# передаем в handler кастомный фильтр и дефолтное состояние
@dispatcher.message_handler(content_types=['location'], state=FSMstates.fill_geolocation)
# в хендлере стоит конструктор, создающий элемент состояния
async def input_location(message: types.Message, state: FSMContext):
    print('input_location')

    with DataBase(path_db='bot_reminder.db') as db: # записываем id, широту и долготу в базу
        db.execute('INSERT OR IGNORE INTO person (person_id, latitude, longitude) VALUES(?, ?, ?)',
                   (message.from_user.id, message.location.latitude, message.location.longitude))
        db.commit()

    await message.answer(text='Введите время ежедневного напоминания в формате чч:мм',
                         reply_markup=types.ReplyKeyboardRemove())
    await state.set_state(FSMstates.fill_time.state)  # устанавливаем состояние ожидания ввода времени

# передаем в handler фильтр на любой текст и сосотояние ожидания ввода корректного времени
@dispatcher.message_handler(lambda x: True, state=FSMstates.fill_time)
async def input_time(message: types.Message, state: FSMContext):
    print('input_time')
    if bool(re.fullmatch(r'\d{2}:\d{2}', message.text)) != True:  # улучшить проверку
        await message.answer(text='То, что вы ввели, не соответсвует нужному формату')
        return  # прерываем функцию, сохраняя статус ожидания
    else:
        with DataBase(path_db='bot_reminder.db') as db: # записываем время в базу
            db.execute('UPDATE person SET time_reminders = ? WHERE person_id = ?', (message.text, message.from_user.id))
            db.commit()

        await message.answer(f'Время вашего напоминания: {message.text}\n'
                             'Напишите свои задачи на неделю в порядке следования дней недели в формате:\n'
                             '1. задачи\n2. задачи\n3. задачи\n.....')
        await state.set_state(FSMstates.fill_reminder.state)  # устанавливаем состояние ожидания ввода расписания

# передаем в handler фильтр на любой текст и сосотояние ожидания ввода корректного расписания
@dispatcher.message_handler(lambda x: True, state=FSMstates.fill_reminder)
async def input_reminder(message: types.Message, state: FSMContext):
    print('input_reminder')
    reminder_week = tuple(map(lambda x: x[3:], [i for i in message.text.split('\n\n')]))

    with DataBase(path_db='bot_reminder.db') as db:  # заполнение таблицы weekday
        db.execute('INSERT OR IGNORE INTO weekday VALUES(?, ?, ?, ?, ?, ?, ?, ?)',
                   (message.from_user.id, *reminder_week))
        db.commit()
        time_user, lng, lat = db.query_data('SELECT time_reminders, latitude, longitude FROM person WHERE person_id = ?',
                                      (message.from_user.id,))[0]

    user_local_time = determining_user_time(time_user, lng=lng, lat=lat)

    await message.answer('Ваше расписание записано, я напомню вам о нем в заданное время')

###########            Вот тут должен запускаться планировщик     #########################
    aioschedule.every().days.at(user_local_time).do(reminder, bot, message.chat.id, state)
    while aioschedule.jobs:
        await aioschedule.run_pending()
        await asyncio.sleep(0.1)
###########################################################################################

if __name__ == '__main__':
    try:
        start_polling(dispatcher=dispatcher, skip_updates=True)
    except Exception as e:
        print(e)
        time.sleep(5)
</code>

Предполагаю, что проблема в функций input_reminder:

async def input_reminder(message: types.Message, state: FSMContext):
    ...
    while aioschedule.jobs:
            await aioschedule.run_pending()
            await asyncio.sleep(0.1)

Это участок кода запускать один раз, а не для квждого пользователя, например при запуске бота:

...
async def reminder(chat_id):
    ...

async def input_reminder(message: types.Message, state: FSMContext):
    ...
    aioschedule.every().days.at(user_local_time).do(reminder, message.chat.id)

async def on_startup(_):
    asyncio.create_task(run_scheduler())

async def run_scheduler():
    while True:
        await schedule.run_pending()
        await asyncio.sleep(1)

executor.start_polling(dp, on_startup=on_startup)

Нет сброса состояние FSM при завершений диалога с пользователем,
aioschedule.clear() удвлить все задвчи из планировщика. В функций
reminder можно передовать один параметр chat_id
async def reminder(chat_id)


Как сделать методы точнее? Python [закрыт]

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

 Вопросы с просьбами помочь с отладкой («почему этот код не работает?») должны включать желаемое поведение, конкретную проблему или ошибку и минимальный код для её воспроизведения прямо в вопросе. Вопросы без явного описания проблемы бесполезны для остальных посетителей. См. Как создать минимальный, самодостаточный и воспроизводимый пример.

Закрыт 6 месяцев назад.

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

Написал вот такую прогу которая решает функцию разными методами
<code>
import math
def f(x):
    return math.pow(math.log(x), 4.5) # возведение натурального логарифма от x в степень 4,5

a = 2 # отрезок [2;4]
b = 4
exact_value = 0.3077347286 # значение интеграла, найденное с помощью формулы Ньютона-Лейбница

# метод Ньютона-Котеса
def newton_cotes(a, b, n):
    h = (b - a) / n # шаг интегрирования
    x = [a + i * h for i in range(n+1)] # список значений аргумента x
    y = [f(x_i) for x_i in x] # список значений функции f(x) в точках из списка x
    integral = 0
    for i in range(n):
        integral += (y[i] + y[i+1]) / 2 * h
    return integral
# метод прямоугольников
def rectangle(a, b, n):
    h = (b - a) / n # шаг интегрирования
    x = [a + i * h for i in range(n)] # список значений аргумента x
    y = [f((x[i]+x[i])/2) for i in range(n)] # список значений функции f(x) в точках из списка x
    integral = h * sum(y)
    return integral
# метод трапеций
def trapezoid(a, b, n):
    h = (b - a) / n # шаг интегрирования
    x = [a + i * h for i in range(n+1)] # список значений аргумента x
    y = [f(x_i) for x_i in x] # список значений функции f(x) в точках из списка x
    integral = h/2 * (y[0] + 2 * sum(y[1:-1]) + y[-1])
    return integral
# метод Симпсона
def simpson(a, b, n):
    h = (b - a) / n # шаг интегрирования
    x = [a + i * h for i in range(n+1)] # список значений аргумента x
    y = [f(x_i) for x_i in x] # список значений функции f(x) в точках из списка x
    integral = h/3 * (y[0] + 4 * sum(y[1:-1:2]) + 2 * sum(y[2:-2:2]) + y[-1])
    return integral

def simpsonn(f, a, b, n):
    h= (b - a) / n
    k=0.0
    x=a + h
    for i in range(1,n/2 + 1):
        k += 4*f(x)
        x += 2*h
    x = a + 2*h
    for i in range(1,n/2):
        k += 2*f(x)
        x += 2*h
    return (h/3)*(f(a)+f(b)+k)

n = 4

# метод Ньютона-Котеса
integral_nc = newton_cotes(a, b, n) # вычисление приближённого значения определённого интервала методом Ньютона-Котеса на интервалие [a, b] с использованием n интервалов
abs_error_nc = abs(exact_value - integral_nc) # вычисление абсолютной ошибки между точным и приближённым значением
rel_error_nc = abs_error_nc / exact_value # вычисление относительной погрешности путём деления абсолютной ошибки на точное значение
# метод прямоугольников
integral_rect = rectangle(a, b, n) # вычисление приближённого значения определённого интервала методом прямоугольника на интервалие [a, b] с использованием n интервалов
abs_error_rect = abs(exact_value - integral_rect) # вычисление абсолютной ошибки между точным и приближённым значением
rel_error_rect = abs_error_rect / exact_value # вычисление относительной погрешности путём деления абсолютной ошибки на точное значение
# метод трапеций
integral_trap = trapezoid(a, b, n) # вычисление приближённого значения определённого интервала методом трапеции на интервалие [a, b] с использованием n интервалов
abs_error_trap = abs(exact_value - integral_trap) # вычисление абсолютной ошибки между точным и приближённым значением
rel_error_trap = abs_error_trap / exact_value # вычисление относительной погрешности путём деления абсолютной ошибки на точное значение
# метод Симпсона
integral_simp = simpson(a, b, n) # вычисление приближённого значения определённого интервала методом Симпсона на интервалие [a, b] с использованием n интервалов
abs_error_simp = abs(exact_value - integral_simp) # вычисление абсолютной ошибки между точным и приближённым значением
rel_error_simp = abs_error_simp / exact_value # вычисление относительной погрешности путём деления абсолютной ошибки на точное значение
# вывод результатов
print("Метод Ньютона-Котеса:")
print("Приближенное значение интеграла:", round(integral_nc, 8)) # round(integral_nc, 8) - округление до 8 символов после запятой
print("Абсолютная погрешность:", round(abs_error_nc, 8))
print("Относительная погрешность:", round(rel_error_nc, 8))
print()
print("Метод прямоугольников:")
print("Приближенное значение интеграла:", round(integral_rect, 8))
print("Абсолютная погрешность:", round(abs_error_rect, 8))
print("Относительная погрешность:", round(rel_error_rect, 8))
print()
print("Метод трапеций:")
print("Приближенное значение интеграла:", round(integral_trap, 8))
print("Абсолютная погрешность:", round(abs_error_trap, 8))
print("Относительная погрешность:", round(rel_error_trap, 8))
print()
print("Метод Симпсона:")
print("Приближенное значение интеграла:", round(integral_simp, 8))
print("Абсолютная погрешность:", round(abs_error_simp, 8))
print("Относительная погрешность:", round(rel_error_simp, 8))
</code>
Но когда показал преподу код, он сказал что вычисления и погрешности должны быть точнее, особенно в методе Симпсона

Начнем с того, что интеграл ваш равен 3,55381...
А продолжать уже и не надо.


Как написать сообщение, от имени бота, что сообщение удалено?
Подскажите пожалуйста, как прописать код, чтобы бот написал, что сообщение удалено, чтобы, было адресовано пользователю, что администратор, удалил сообщение(публикацию), в группе телеграм.
Есть такой код, но не знаю, как через
for или
if прописать, чтобы писал текст, только, если администратор, удалил сообщение.

@dp.message_handler(content_types=['text'])
async def get_handler(message: types.Message):
    if message.text:
            await bot.send_message(chat_id=message.chat.id, text="\nПубликация удалена, администратором группы.".format(message.text, message.chat.id, message.from_user.id, message.message_id), parse_mode='html', disable_web_page_preview=True)
            return

Нашел, вот такой код, немножко переделал, работает, как надо, но только, по команде, в ответ, на сообщение, прописываю команду del и сообщение удаляется, как его изменить?, чтобы не по команде del

@dp.message_handler(commands=['del'], commands_prefix="!/")
async def cmd_ban(message: types.Message):
    if not message.reply_to_message:
        await message.reply('эта команда должна быть ответом на сообщение!')
        return

    await message.bot.delete_message(chat_id=message.chat.id,message_id=message.reply_to_message.message_id)
    await message.reply("\nПубликация удалена.")

ну написано же там
commands в хендлере, там пишите команды

@dp.message_handler(commands=['удалить', 'del'], commands_prefix="!/")

очень советую посмотреть хотя бы пару видео по python и aiogram


как из датафрейма размером 5*5 сделать датафрейм с одним столбцом
Есть датафрейм размером 3х5

1
2
3

095
093
094

109
NaN
NaN

09
10
NaN

019
020
NaN

04
05
123

Возможно ли из датафрейма 3Х5 сделать датафрейм 1Х11 без пустых значений

1

095

109

09

019

04

093

10

020

05

094

123


Функция принимает список, а возвращает кортеж с максимальным и минимальным значение из списка [закрыт]

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

 Вопросы с просьбами помочь с отладкой («почему этот код не работает?») должны включать желаемое поведение, конкретную проблему или ошибку и минимальный код для её воспроизведения прямо в вопросе. Вопросы без явного описания проблемы бесполезны для остальных посетителей. См. Как создать минимальный, самодостаточный и воспроизводимый пример.

Закрыт 6 месяцев назад.

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

Нужно написать функцию, которая принимает список, а возвращает кортеж из с минимальным и максимальным значениями в списке. (список должен содержать
int).
Что не так?

list1 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
for i in list1:
    if max < i:
        max = i
    if min > i:
        min = i
return tuple(list1[max, min]
print(f"Максимальное значение: {max}", "Минимальное значение {min}")

Много раз переписывал, потерял начало.
def list(myList:list):
    Max
    i = int(input(""))
    for i in range(len(myList)):
        if Max < myList[i]:
            Max = myList[i]
    return tuple([Max, Min])
mylist = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
print(f"Кортеж с минимальным и максимальным значением из списка - {MinMax(example(mylist))}")

Ваш код нужно изменить так:

list1 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]

def get_min_max(lst):
    max = lst[0]
    min = lst[0]
    for v in lst:
        if v > max:
            max = v
        if v < min:
            min = v
    return (min, max)

result = get_min_max(list1)
print(f"Максимальное значение: {result[0]}", f"Минимальное значение {result[1]}")

А можно воспользоваться встроенными функциями
min и
max:

list1 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]

def get_min_max(lst):
    return (min(lst), max(lst))

result = get_min_max(list1)
print(f"Максимальное значение: {result[0]}", f"Минимальное значение {result[1]}")


Перепостроение пиков до нужной ширины
Программа строит дифрактограмму по определенной формуле, которая находит положения дифракционных максимумов по углам (формула - условие Вульфа-Брэгга). Однако, данные максимумы имеют определенную ширину, которая находится по формуле Шеррера. Вопрос, как реализовать построение дифракционных максимумов с определенной шириной (после нахождения этих максимумов) при этом, сами максимумы, в итоге, должны выглядить примерно так.
Код нахождения дифракционных максимумов:
<code>
arr = np.zeros(1800)
for i in range(0, 1800, 1):
    from random import uniform
    arr[i] = uniform(0, 1)
x = np.linspace(0, 180, 1800)

num = 10

for i in range(num):
    from random import randint
        number = randint(0, np.size(D))
        sinthet1 = 1 * lambdal / (2 * D[number - 1])
        sinthet2 = 1 * lambdbt / (2 * D[number - 1])
        if sinthet1 <= 1:
            thet1 = math.degrees(np.arcsin(sinthet1)) * 10
            th1 = np.around(thet1).astype(int)
            thet2 = math.degrees(np.arcsin(sinthet2)) * 10
            th2 = np.around(thet2).astype(int)
            arr[2 * th1] = I[number - 1]
            state = self.ui.filterBox.isChecked()
            if state == False and th2 != th1:
                arr[2 * th2] = round(I[number - 1] / 100 * 40, 1)
</code>


Python. Связь между экземплярами одного класса через обращение к атрибуту
Есть один класс. Есть два экземпляра этого класса.
Один движется (
self.type = 'move'), второй не движется (
self.type = 'stay').
Нужно, чтобы второй тоже двигался по координатам первого.
Может ли
obj2 апеллируя атрибутом
self.type обратиться к
obj1, чтобы наследовать его координаты?
Вариант посредника в виде глобальной переменной известен, но нужно чтобы
obj2 обращался непосредственно к
obj1.
Помогите пожалуйста разобраться.
UPD: Важно, чтобы обращение происходило внутри класса, в методе Update, учитывая, что никакая информация вроде названий или индексов копий неизвестна, известен только атрибут self.type.

import pygame

pygame.init()

WIDTH, HEIGHT = WINDOW_SIZE = 800, 600
FPS = 60

window = pygame.display.set_mode(WINDOW_SIZE)
clock = pygame.time.Clock()

objects = []

class ObjectTest:
    def __init__(self, type, x, y):
        objects.append(self)

        self.type = type

        self.color = 'red'
        self.rect = pygame.Rect(x, y, 64, 64)

    def update(self):
        if self.type == 'move':
            self.rect.x += 1
            self.color = 'green'
        if self.type == 'stay':
            # здесь нужно self.rect.x взять у копии с тайпом 'move'
            self.color = 'white'

    def draw(self):
        pygame.draw.rect(window, self.color, self.rect)

obj1 = ObjectTest('move', 100, 100)
obj2 = ObjectTest('stay', 200, 200)

play = True
while play:

    for event in pygame.event.get():

        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            play = False
            pygame.quit()

    for i in objects: i.update()

    window.fill('black')
    for i in objects: i.draw()

    pygame.display.update()
    clock.tick(FPS)

Кроме переменных экземпляра класса (то есть
self) есть ещё переменные самого класса
ObjectTest. Вы можете поместить список
objects в переменные класса
ObjectTest и при этом обращаться к нему через
self, то есть через экземпляр класса (экземпляры имеют доступ к переменным класса):

class ObjectTest:
    # список объектов теперь принадлежит всем объектам класса
    objects = []

    def __init__(self, type, x, y):
        # добавляем новый экземпляр класса в список объектов класса
        self.objects.append(self)
    ...

    def update(self):
        if self.type == 'move':
            self.rect.x += 1
            self.color = 'green'
        if self.type == 'stay':
            # перебираем объекты класса, ищем движущийся объект
            for obj in self.objects:
                # если нашли, то копируем его координату
                if obj.type == 'move':
                    self.rect.x = obj.rect.x
            self.color = 'white'

Внешне это выглядит похоже на использование глобальной переменной, но является более правильным подходом - список
objects лежит не в глобальном пространстве, где непонятно, к чему он вообще относится, а лежит в классе, объекты которого он содержит.
Можно пойти дальше и, если у вас только по одному объекту каждого
type, то завести словарь, а не список, у которого ключом будет
type объекта. Тогда вам даже не нужно будет перебирать объекты, чтобы найти нужный:

class ObjectTest:
    # словарь объектов
    objects = {}

    def __init__(self, type, x, y):
        # добавляем новый экземпляр класса в словарь объектов класса
        self.objects[type] = self
    ...

    def update(self):
        if self.type == 'move':
            self.rect.x += 1
            self.color = 'green'
        if self.type == 'stay':
            # ищем движущийся объект (он может быть ещё не добавлен)
            obj = self.objects.get('move')
            if obj in not None:
                # если нашли, то копируем его координату
                self.rect.x = obj.rect.x
            self.color = 'white'

И
type - плохое название для параметра функции, оно перекрывает встроенную функцию. Используйте
type_. Вот в переменных класса можно оставить
self.type как есть, насколько я помню.


Как ограничить ввод между значениями 0.2 и 2 (В регулярном выражении)

Как ограничить ввод между значениями не меньше 0.2 и не больше 2

Как написать регулярку такую /
<code>
from PyQt5.Qt import QApplication
from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtWidgets import QWidget, QLineEdit

import sys

class MyWidget(QWidget):
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)
        self.le_input = QLineEdit(self)

        # reg_ex = QRegExp("[0-9]{2,1}+.?[0-9]{,1}")

        reg_ex = QRegExp("^([0-2]|[1-9][0-9]|100)$")   # регулярка на вводимые значения
        input_validator = QRegExpValidator(reg_ex, self.le_input)
        self.le_input.setValidator(input_validator)

if __name__ == '__main__':
    a = QApplication(sys.argv)

    w = MyWidget()
    w.show()

    a.exec()
</code>

^(?:0[,.][2-9]|1(?:[,.][0-9])?|2(?:[,.]0)?)$

^ - начало строки

(?:...) - незахватываемая группа

0[,.][2-9] - цифра 0 после которой идет один из разделителей и цифра в диапазоне от 2 до 9

| - логическое или

1(?:[,.][0-9])? - цифра 1 после которой в группе описан разделитель точка или запятая и любая цифра, на группу установлен квантификатор, что делает ее необязательной

|2(?:[,.]0)? - или 2 c необязательным написание разделителя и ноля

$ - конец строки
Пример на js:

const reg = /^(?:0[,.][2-9]|1(?:[,.][0-9])?|2(?:[,.]0)?)$/gm;
const str = `
0,1
0,2
1,3
2
2.1
2.0
1
,,2
02`;

console.log(str.match(reg));


Деление списка по 2 элемента, с дублированием предыдущего
Как разделить список, на списки по два элемента, с дублированием предыдущего, например:

#На входе
Spisok1=[0,6,7,14]

#На выходе
S1=[0,6]
S2=[6,7]
S3=[7,14]

.

#На входе
Spisok2=[0,2,9,15,17]

#На выходе
S1=[0,2]
S2=[2,9]
S3=[9,15]
S4=[15,17]

Есть простой способ через
zip, правда на выходе будет список кортежей:

Spisok1=[0,6,7,14]
print(list(zip(Spisok1, Spisok1[1:])))

Вывод:

[(0, 6), (6, 7), (7, 14)]


Пакетный POST / PATCH запрос (DRF / Requests)
Возник вопрос, существует ли возможность отправлять / обновлять данные пакетно по REST API (1 http запрос, который создает множество строк в бд, как INSERT INTO
table (c1, c2, c3...) VALUES (v1, v2, v3...), ... ,(v1, v2, v3))
Есть json (постоянно обновляемый) на 30+ тысяч строк и есть API на DRF. Загрузка и обновление данных занимает громадное кол-во времени, и хотелось бы отправлять большой пакет данных одним запросом.
Не могу найти ничего ни в документации DRF, ни в гугле.

Если в эндпоинт сразу залетает весь файл:

Если джанга свежая (с асинхроном) можно побить файл на чанки и пустить обработку/сохранение в асинхроне
Если джанга без асинка, можно подвязать в стек celery/redis и в отдельных тасках обрабатывать эти файлы


model.predict и model.evaluate дают разный результат
Пишу функции для тестирования нейронных сетей и заметил вот такую странность. Сам код:

import shutil
import os
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

from tensorflow.keras.preprocessing.image import ImageDataGenerator

from sklearn.metrics import confusion_matrix, precision_score, \
                            recall_score, roc_auc_score, ConfusionMatrixDisplay

def model_score_evaluate(path_name, model_name):

    metrics = ['accuracy',
               tf.keras.metrics.Recall(),
               tf.keras.metrics.Precision(),
               tf.keras.metrics.AUC()]

    model = tf.keras.models.load_model(model_name, compile=False)

    model.compile(loss="categorical_crossentropy",
                  optimizer="rmsprop",
                  metrics=metrics)

    datagen = ImageDataGenerator(rescale = 1./255)

    generator = datagen.flow_from_directory(path_name,
                                            target_size=(Pic_Y, Pic_X),
                                            batch_size=64,
                                            class_mode='categorical')

    (
    _,
    _,
    test_recall,
    test_precision,
    test_auc
             ) = model.evaluate(generator, steps=len(generator))

    print('Test recall:', test_recall)
    print('Test precision:', test_precision)
    print('Test AUC:', test_auc)

    return

def model_score_predict(path_name, model_name):

    model = tf.keras.models.load_model(model_name, compile=False)

    model.compile(loss="categorical_crossentropy",
                  optimizer="rmsprop",
                  metrics=['accuracy'])

    datagen = ImageDataGenerator(rescale = 1./255)

    generator = datagen.flow_from_directory(path_name,
                                            target_size=(Pic_Y, Pic_X),
                                            batch_size=64,
                                            class_mode='categorical')

    true_labels = generator.classes

    predictions = model.predict(generator)

    predicted_labels = np.argmax(predictions, axis=1)

    recall = recall_score(true_labels, predicted_labels, average='micro')
    precision = precision_score(true_labels, predicted_labels, average='micro')
    auc = roc_auc_score(true_labels, predictions, average='macro',
                        multi_class='ovr')

    print('Test recall:', recall)
    print('Test precision:', precision)
    print('Test AUC:', auc)

    cm = confusion_matrix(true_labels, predicted_labels)

    class_names = list(generator.class_indices.keys())

    disp = ConfusionMatrixDisplay(confusion_matrix=cm,
                                  display_labels=class_names)

    _, ax = plt.subplots(figsize=(10, 10))
    disp.plot(ax=ax, cmap=plt.cm.Blues)

    ax.set_title("Confusion matrix")
    ax.set_xlabel("Predicted label")
    ax.set_ylabel("True label")

    plt.show()

    return

Первая модель определяет перечень метрик при её компиляции. Затем она создает генератор из предложенных данных. Вызывается метод evaluate() и выводятся на печать метрики.
Вторая модель компилируется без дополнительного перечня метрик. У модели вызывается метод predict(), а у генератора - classes. Метрики рассчитываются с помощью библиотеки sklearn. Ну и бонусом вторая функция строит матрицу неточностей.
Приведу результаты работы функций на одних и тех де данных:

path_name = 'to_test'
model_name = 'convnet_from_scratch.h5'

model_score_evaluate(path_name, model_name)

Результат:
    Test recall: 0.9272338151931763
    Test precision: 0.932723343372345
    Test AUC: 0.9822500944137573

model_score_predict(path_name, model_name)

Результат:
    Test recall: 0.13846976993044408
    Test precision: 0.13846976993044408
    Test AUC: 0.4982606769303777

Матрицу неточностей не привожу. Смотреть вообще не на что при таком AUC... Почему такой разный результат?
UPD:
Пощелкал метод model.predict. Формат выходных данных ожидаем:

img = Image.open('to_test/03/55907903_b524_c1222_user_652_T.jpg')
img = np.array(img.resize((Pic_X, Pic_Y))) / 255
img = np.expand_dims(img, axis=0)
model.predict(img)

Результат:
    array([[9.648740e-36, 0.000000e+00, 1.000000e+00, 0.000000e+00,
        7.593448e-24, 0.000000e+00, 1.165523e-33, 0.000000e+00,
        0.000000e+00]], dtype=float32)

Изображение взято из третьей по счёту стопки (с индексом 2). Степень уверенности модели очень высока, как видно.  Так и с прочими, которые я проверил руками.
Содержимое generator.classes без сюрпризов. Данные не перемешиваются, по порядку цифры от 0 до 8 (всего 9 классов).

Всё дело оказалось в том, что метод flow_from_directory имеет атрибут shuffle, который по умолчанию равен True. Из-за этого вектор предсказаний был перемешан относительно статично определенных меток классов у тестовых данных.
<code>
generator = datagen.flow_from_directory(path_name,
                                            target_size=(Pic_Y, Pic_X),
                                            batch_size=64,
                                            class_mode='categorical',
                                            shuffle=False)
</code>
После этого оценки, измеренные обоими методами, примерно совпали. Их различия уже связаны только с методом усреднения при многоклассовой классификации.


Попарно заменить буквы в строке
Есть задание из "TTAGCGCA", вывести "AATCGCGT" используя словарь ретрансляции. Как это сделать?
<code>
table = {
    "A": "T",
    "T": "A",
    "C": "G",
    "G": "C"
}

print(list(table.keys()))
</code>

str.maketrans создаёт таблицу трансляции, str.translate её применяет:

table = {
    "A": "T",
    "T": "A",
    "C": "G",
    "G": "C"
}

trans = str.maketrans(table)
print("TTAGCGCA".translate(trans))

$ python translate.py
AATCGCGT


Как на основе заполнения одной формы и передачи данных в одну модель, передать часть данных в другую?
Я новичок в Django, поэтому если не трудно я бы хотел получить более подробное разъяснение или ссылку на него. У меня есть две модели, статус АСК и компьютер. Между собой они связанный типом "Один к одному". Когда я заполняю объект модели "Статус АСК", у него в поле "компьютер" предлагается выбрать связанный с ним номер компьютера из модели "Компьютер". То есть одному месту соответствует только один номер компьютера ( в самой модели "Компьютер" хранится полная конфигурация компа). Но что если при заполнении формы необходимо указать тот компьютер, которого нет в базе. Вот тут мне и нужна помощь, нужно предложить пользователю выбрать ЛИБО НЕ занятый компьютер (то есть тот, который ещё не привязан к "статус АСК") либо создать свой собственный, то есть необходимо подтвердить валидность формы, записать данные в модель "Статус АСК" и при этом создать новую записать в модели "Компьютер" ( очевидно все колонки кроме номера будут пусты и дальше пользователь сам заполняет данный компьютер). Как это реализовать?
Ниже приведён код:
forms.py:

class ComputerForm(ModelForm):
    class Meta:
        model = Computer
        fields = ["number", "CPU", "RAM", "Power_unit",
                  "Mother_board", "ISA_port", "LPT_port",
                  "COM_port", "PCI_slot", "PCI_express_slot",
                  "Data_storage_device", "video_card", "object_place",
                  "object_work", ]
        widgets = {
            "number": TextInput(attrs={
                'class': 'form-control',

            }),

            "CPU": TextInput(attrs={
                'class': 'form-control',

            }),

            "RAM": TextInput(attrs={
                'class': 'form-control',

            }),

            "Power_unit": TextInput(attrs={
                'class': 'form-control',

            }),

            "Mother_board": TextInput(attrs={
                'class': 'form-control',

            }),

            "PCI_slot": forms.Select(attrs={
                'class': 'form-control',
                'title': 'Наличие PCI порта (Да/Нет)'

            }),

            "PCI_express_slot": forms.Select(attrs={
                'class': 'form-control',
                'title': 'Наличие PCI порта (Да/Нет)'

            }),

            "ISA_port": forms.Select(attrs={
                'class': 'form-control',
                'title': 'Наличие PCI порта (Да/Нет)'

            }),

            "LPT_port": forms.Select(attrs={
                'class': 'form-control',
                'title': 'Наличие PCI порта (Да/Нет)'

            }),

            "COM_port": forms.Select(attrs={
                'class': 'form-control',
                'title': 'Наличие PCI порта (Да/Нет)'

            }),

            "Data_storage_device": TextInput(attrs={
                'class': 'form-control',

            }),

            "video_card": TextInput(attrs={
                'class': 'form-control',

            }),

            "object_place": TextInput(attrs={
                'class': 'form-control',

            }),

            "object_work": TextInput(attrs={

                'class': 'form-control',

            }),
        }
class StatusForm(ModelForm):
    class Meta:
        model = ASKstatus
        fields = ["number", "ASK_number", "name", "product_name", "note", "comps_to_work"]
        widgets = {
            "number": TextInput(attrs={
                'class': 'form-control',
                'placeholder': '№ п/п'

            }),

            "ASK_number": TextInput(attrs={
                'class': 'form-control',
                'placeholder': '№ АСК'

            }),

            "name": TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Название'
            }),

            "product_name": TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Изделие'
            }),

            "note": TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Примечание'
            }),

            "comps_to_work": TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Номер компьютера'
            })
        }

models.py:

class Computer(models.Model):
    CHOICES = [
        ('Да', 'Да'),
        ('Нет', 'Нет'),
    ]
    number = models.CharField('Номер компьютера', max_length=6, blank=True)
    CPU = models.CharField('Процессор', max_length=50, blank=True)
    RAM = models.TextField('Оперативная память', max_length=200, blank=True)
    Power_unit = models.CharField('Блок питания', max_length=50, blank=True)
    Mother_board = models.CharField('Материнская плата', max_length=100, blank=True)
    PCI_slot = models.CharField('PCI слот', max_length=3, blank=True, choices=CHOICES)
    PCI_express_slot = models.CharField('PCI express слот', max_length=3, blank=True, choices=CHOICES)
    ISA_port = models.CharField('ISA порт', max_length=3, blank=True, choices=CHOICES)
    LPT_port = models.CharField('LPT порт/параллельный порт', max_length=3, blank=True, choices=CHOICES)
    COM_port = models.CharField('COM порт/последовательный порт', max_length=3, blank=True, choices=CHOICES)
    Data_storage_device = models.CharField('Устройство хранения данных', max_length=100, blank=True)
    video_card = models.CharField('Видеокарта', max_length=100, blank=True)
    object_place = models.CharField('Место положения', max_length=200, blank=True)
    object_work = models.CharField('Рабочее место', max_length=200, blank=True, null=True)

    def __str__(self):
        return f'{self.number}'

    class Meta:
        verbose_name = 'Компьютер'
        verbose_name_plural = 'Компьютеры'

class ASKstatus(models.Model):
    number = models.CharField('№ п/п', max_length=10, blank=True)
    ASK_number = models.CharField('№ АСК',max_length=10, blank=True)
    name = models.CharField('Название', max_length=100, blank=True)
    product_name = models.CharField('Изделие', max_length=100, blank=True)
    note = models.CharField('Примечание', max_length=100, blank=True)
    comps_to_work = models.OneToOneField('Computer', on_delete=models.SET_NULL, null=True, blank=True)

    class Meta:
        verbose_name = 'Статус'
        verbose_name_plural = 'Статусы'

views.py:

def add_ASK(request):
    error = ''
    if request.method == 'POST':
        form = StatusForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('/index_S')
        else:
            error = 'Неверная форма данных'

    form = StatusForm()
    context = {
        'form': form,
        'error': error
    }
    return render(request, "base_comp/add_ASK.html", context)

Ваш код не стал разбирать. Просто приведу мою реализацию данного функционала:

<form method="post" action="{% url 'rich:change_rich' object.id %}" id="rich_select_form">
    {% csrf_token %}
    Выберите РИЧ для данного РЭС:
    <br>
    <select name="select_rich" id="select_rich" onchange="richFunction()" class="rich_input_class">
    <option value="" selected></option>
    {% for i in related_rich %}
    <option value="{{ i }}">{{ i }}</option>
    {% endfor %}
    <option value="Добавить">Добавить новое разрешение</option>
    </select>
 </form>
 <form id="rich_add" method="post" action="{% url 'rich:add_rich' object.id %}" enctype="multipart/form-data" class="rich_add_form">
    {% csrf_token %}
    {{ rich_form.as_p }}
    </form>
 <div id="rich_buttons">
    <input type="submit" value="Изменить" id="select_rich_button" form="rich_select_form">
    <button onmousedown="showhide_changeform('change_rich')" class="close_button">
     <i class="fa-solid fa-xmark"></i>
     </button>
 </div>

В шаблон передаем две формы. В поле action указываем разные функции view.
При этом форму с id rich_add делаем невидимой при помощи css:

#rich_add {
padding-top: 0;
display: none;
}

Также на первой форме на select добавляем функцию js onchange="richFunction()" которая срабатывает при выборе "Добавить новое разрешение". Ниже сама функция:

function richFunction() {
   var a = document.getElementById('select_rich');
   var e = document.getElementById('rich_add');
   var b = document.getElementById('select_rich_button');
   if (a.value == "Добавить") {
        e.style.display = 'block';
        b.setAttribute("form", "rich_add");
        b.value = 'Добавить';
                               }
   else {
        e.style.display = 'none';
        b.setAttribute("form", "rich_select_form");
        b.value = 'Изменить';
                                }
   }

Функция richFunction() отвечает за смену свойства у элемента rich_add и смену текста кнопки (select_rich_button) и, что самое важное смену целевого id формы (атрибут form кнопки меняем на rich_add и обратно).
Далее просто обрабатываем две различные view функции:

@login_required(login_url='account:login')
@is_staff
def change_rich(request, id):
    res_object = Res.objects.get(id=id)
    if request.method == 'POST':
        rich_name = request.POST['select_rich']
        obj = Rich.objects.get(name=rich_name)
        if obj.end_date < date.today():
            return res_detail(request, id, msg='Вы не можете присвоить РИЧ с истекшим сроком действия!')
        else:
           res_object.related_rich = obj
           res_object.save()
    return redirect('rich:res_detail', id=id)

@login_required(login_url='account:login')
@is_staff
def add_rich(request, id):
    res_object = Res.objects.get(id=id)
    if request.method == 'POST':
        rich_form = RichForm(request.POST, request.FILES)
        file = request.FILES['doc']
        name = file.name.replace(Path(file.name).suffix, '')
        name = name.replace('_', ' ')
        end_date = request.POST['end_date']
        end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
        if rich_form.is_valid() and (Rich.objects.filter(name=name).exists() is False) and (end_date > date.today()):
           a = rich_form.save()
           res_object.related_rich = a
           res_object.save()
           return redirect('rich:res_detail', id=id)
        elif Rich.objects.filter(name=name).exists():
            return res_detail(request, id, msg='Разрешение с таким именем уже существует!')
       elif end_date < date.today():
           return res_detail(request, id, msg='Вы не можете добавить РИЧ с истекшим сроком действия!')
       else:
           msg = form_errors_text(rich_form)
           return res_detail(request, id, msg=msg)
   return redirect('rich:res_detail', id=id)

Их функционал в данном случае неважен.


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

# принятие ответа сервера
    def recv_msg(self):
        data = self.sock.recv(10240)
        data = pickle.loads(data, encoding='utf-8')
        rep_file = data.to_csv('report_df.csv', index=False)
        target_fld = self.get_folder()
        os.path.join(str(target_fld), rep_file)
        print('file upload')
        self.sock.close()

Вот весь код в модуле:

import sys
import os
import socket
import pickle
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QApplication
from upload_client_gui import Ui_MainWindow

class gui(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect(('localhost', 9090))

        self.download_folder = None
        self.ui.pushButton.clicked.connect(self.get_folder)
        self.ui.pushButton_2.clicked.connect(self.send_msg)

    # выбор даты выгружаемого отчета
    def calendar_date(self):
        date = self.ui.calendarWidget.selectedDate()
        string_date = str(date.toPyDate())
        return string_date

    # открывается проводник для выбора папки в которую будет сохраняться файл
    def get_folder(self):
        try:
            self.download_folder = QtWidgets.QFileDialog.getExistingDirectory(self, 'Выберете папку для сохранения')
            os.chdir(self.download_folder)
            print(self.download_folder)
        except:
            pass

    # отправка даты на сервер через сокет
    def send_msg(self):
        msg = self.calendar_date()
        print(msg)
        self.sock.send(msg.encode('utf-8'))

    # принятие ответа сервера
    def recv_msg(self):
        data = self.sock.recv(10240)
        data = pickle.loads(data, encoding='utf-8')
        rep_file = data.to_csv('report_df.csv', index=False)
        target_fld = self.get_folder()
        os.path.join(str(target_fld), rep_file)
        print('file upload')
        self.sock.close()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = gui()
    win.show()
    sys.exit(app.exec())

Выбор папки работает, возвращается абсолютный путь, запрос и ответ сокета тоже есть.
Помогите пожалуйста разобраться где у меня проблема.

возможно ошибка в буфере -> 1024->(0)<-
socket.recv(10240)будет считывать не более 10240 байт, блокируя, если нет данных, ожидающих чтения.
socket.recv также будет заканчиваться пустой строкой, если соединение будет закрыто или возникнет ошибка и вы ничего не узнаете о неполадках.
короче, дынные отправлены, но их размер невелик, а буфер не забит.
попробуй изменить размер буфера.


возвращаете нужные вам значения в виде кортежа из функции через
return
получаете результат работы функции
распаковываете результат-кортеж в отдельные переменные, если нужно

def foo(arr1, arr2):
    zone = []
    zone2 = []
    # основной код функции для примера не важен, я его пропускаю
    ...
    return zone, zone2

x1 = [1.11, 1.11, 1.12, 1.12, 1.13, 1.08, 1.65, 1.65, 1.05, 1.05, 1.05, 1.05, 1.1, 1.1, 1.05]
x2 = [1.66, 1.66, 1.58, 1.58, 1.61, 1.61, 1.82, 1.82, 1.65, 1.65, 1.77, 1.77, 1.65, 1.65, 1.46]

z1, z2 = foo(x1, x2)
print(z1, z2)


Как сделать чтобы бот выводил рандомное значение с базы данных?
Ошибок не выдает. При нажатии на команду ничего не выводит. Что я не так сделал?
Код бота:

import telebot
from FilmDatabase import *

bot = telebot.TeleBot('Token')
prepareDb('db/Films.db')

@bot.message_handler(commands=['start'])
def start(message):
    username = message.from_user.first_name
    bot.send_message(message.chat.id, f'Привіт {username}, я Каспер! Хочешь поговорити зі мною чи є якесь питання?')

@bot.message_handler(commands=['stop'])
def stop(message):
    bot.send_message(message.chat.id, f'Радий був допомогти!\n'
                                      f'Якщо захочете поговорити чи потрібна буде допомога введіть знову команду /start')

@bot.message_handler(content_types=["text"])
def text(message):
    if message.chat.type == 'private':
        if message.text == 'Поговорити':
            bot.send_message(message.chat.id, f'Добре, як настрій?' + '\U0001f642')
        if message.text == 'Так собі':
            bot.send_message(message.chat.id, f'Чому? Щось сталось?'
                                              f'Я можу якось допомогти тобі підняти настрій?' + '\U0001f61f')
        if message.text == 'Можеш порекомендувати якийсь фільм?':
            bot.send_message(message.chat.id, f'Так, звісно! Який жанр вас цікавить?\n'
                                              f'/comedia')

@bot.message_handler(commands=['comedia'])
def comedia(message):
        films = getFilms('db/Films.db')
        bot.send_message(message.chat.id, f'З комедій можу порадити: {films}')

bot.polling(none_stop=True)

Код подключения к БД:

import sqlite3
from sqlite3 import Error

def init_conn(path):
    conn = None
    try:
        conn = sqlite3.connect(path)
        print ("Connection established!")
    except Error as e:
        print (e)
        print ("Connection failed!")
    return conn

def init_tables(connection):
    sql = "CREATE TABLE IF NOT EXISTS Comedia(id integer PRIMARY KEY, name_film text NOT NULL);"
    connection.execute(sql)

    def prepareDb(name):
        conn = init_conn(name)
        init_tables(conn)
        conn.close()

    def getFilms(db):
        sql = "SELECT * FROM `Comedia` ORDER BY RAND() LIMIT 1"
        connection = init_conn(db)
        cursor = connection.cursor()
        connection.set_trace_callback(print)
        cursor.execute(sql)
        connection.commit()
        connection.close()

Измените ваш запрос на:
<code>
SELECT * FROM `Comedia` ORDER BY random() LIMIT 1
</code>


Как при нажатии на кнопку прекратить цикл ? Telebot
Решил сделать игру в тг-боте. Как сделать чтобы при нажатии на кнопки "Стоп" прекращался цикл while и бот выводил сообщение?
Код:
<code>
@bot.message_handler(content_types=['text'])
def sum_bet_func(message):
    global sum_bet1
    sum_bet1 = message.text
    users_id = message.chat.id
    balance1 = (sql.execute("SELECT * FROM users WHERE user_id = ?", (users_id,))).fetchone()[2]
    if sum_bet1.isdigit():
        if sum_bet1.isdigit() and int(sum_bet1) <= balance1:
            bot.send_message(message.chat.id, text=f'💶 Ставка: {sum_bet1}₽\n\nИгра: Crash\nИгра начинается через 10 секунд...')
            x = 1
            while x <= 22:
                if x == 11:
                    global factor
                    factor = random.uniform(1, 5)
                    stop_menu = types.InlineKeyboardMarkup()
                    stop = types.InlineKeyboardButton('СТОП-1', callback_data='stop')
                    stop_menu.add(stop)
                    bot.send_message(message.chat.id, text=f'💻 1/3 nn〽 Множитель: {factor}', reply_markup=stop_menu)
                if x == 16:
                    global factor2
                    factor2 = random.uniform(1, 5)
                    stop_menu2 = types.InlineKeyboardMarkup()
                    stop2 = types.InlineKeyboardButton('СТОП-2', callback_data='stop2')
                    stop_menu2.add(stop2)
                    bot.send_message(message.chat.id, text=f'💻 2/3 nn〽 Множитель: {factor2}', reply_markup=stop_menu2)
                if x == 21:
                    stop_menu3 = types.InlineKeyboardMarkup()
                    stop3 = types.InlineKeyboardButton('СТОП-3', callback_data='stop3')
                    stop_menu3.add(stop3)
                    global factor3
                    factor3 = random.uniform(1, 5)
                    bot.send_message(message.chat.id, text=f'💻 3/3 nn〽 Множитель: {factor3}', reply_markup=stop_menu3)
                if x == 22:
                    bot.send_message(message.chat.id, text=f'Ты проиграл')
                    break
                time.sleep(1)
                x += 1
        else:
            bot.send_message(message.chat.id, text=f'Недостаточно средств на балансе!')
</code>

Заведите bool переменную flag. В цикле добавьте обработчик событий. При нажатии на кнопку смените значение flag на false и закончите цикл.


Пропустить слеши в регулярном выражении, пока не найдётся определённая строка
Недавно я экспериментировал с regex. Тестировал на этом сайте, потом на Python. У меня есть следующее выражение:

^(Resources\/)*

Вот мои строки:

Resources/
Resources/hello
Resources/test
Resources/Resources/abc123
Resources/Hello
Resources/Resources/Resources/sup.txt
Resources/mods/Resources/Unknown.test/test.txt

Ожидаемый вывод:

Resources/
Resources/hello
Resources/test
Resources/abc123
Resources/Hello
Resources/sup.txt
Resources/mods/Unknown.test/test.txt

Полученный вывод:

Resources/
Resources/hello
Resources/test
Resources/Resources/abc123
Resources/Hello
Resources/Resources/Resources/sup.txt
Resources/mods/Resources/Unknown.test/test.txt

Я также пробовал изменять выражение:

^(Resources\/)*
Но результат был тот же самый.
Вот мой код Python:

from re import sub as regexsub
# ...
class ...:
    resfold_nosep = 'Resources'
    sep = '/'
    # ...
    def ...(...):
        # ...
        path = ...
        regexsub("({}{}){2,}".format(self.resfold_nosep, sep), "", path, 1)

Мой вопрос: как сделать так, чтобы в строках заменялись все случаи появления Resources/?

import re

lst = '''
Resources/
Resources/hello
Resources/test
Resources/Resources/abc123
Resources/Hello
Resources/Resources/Resources/sup.txt
Resources/mods/Resources/Unknown.test/test.txt
'''.split()

for s in lst:
    print(re.sub('/Resources', '', s), '<-', s)

Resources/ <- Resources/
Resources/hello <- Resources/hello
Resources/test <- Resources/test
Resources/abc123 <- Resources/Resources/abc123
Resources/Hello <- Resources/Hello
Resources/sup.txt <- Resources/Resources/Resources/sup.txt
Resources/mods/Unknown.test/test.txt <- Resources/mods/Resources/Unknown.test/test.txt

P.S. Namerek в комментарии правильно говорит что регулярное выражание не нужно. Достаточно простой замены:

for s in lst:
    print(s.replace('/Resources', ''), '<-', s)


Построить дерево зависимостей из csv файла
Есть следующего формата csv файл:

parent,child,count,lines
root,log_info,1,15
root,log,1,154
root,log_format_msg,1,86
log_info,log,2,154
log,log_format_msg,1,86

Как построить примерно такое дерево?

root
  |
  |--- log_info [count=1, lines=15]
  |       |
  |       |--- log [count=2, lines=154]
  |             |
  |             |--- log_format_msg [count=1, lines=86]
  |
  |--- log [count=2, lines=154]
  |     |
  |     |--- log_format_msg [count=1, lines=86]
  |
  |--- log_format_msg [count=1, lines=86]

Некоторые библиотеки просто воспринимают узлы (такие как root/log и log_info/log) как дубли. Может файл должен быть другого формата?

Зачем тратить время на библиотеки если можно самим накидать простенькое решение:

import csv

def build_tree(data, parent):
    tree = {}
    for item in data:
        if item['parent'] == parent:
            child = item['child']
            tree[child] = {'count': item['count'], 'lines': item['lines']}
            subtree = build_tree(data, child)
            if subtree:
                tree[child]['subtree'] = subtree
    return tree

def print_tree(tree, indent=0):
    if indent == 0:
        print('root')
    for key, value in tree.items():
        print(f'|{"      " * indent}{"|" if indent > 0 else ""}')
        print(f'|{"      " * indent}{"|" if indent > 0 else ""}--- {key} [count={value["count"]}, lines={value["lines"]}]')
        if value.get('subtree'):
            print_tree(value['subtree'], indent + 1)

with open('test.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    data = [row for row in reader]

tree = build_tree(data, 'root')
print_tree(tree)

Результат:

root
|
|--- log_info [count=1, lines=15]
|      |
|      |--- log [count=2, lines=154]
|            |
|            |--- log_format_msg [count=1, lines=86]
|
|--- log [count=1, lines=154]
|      |
|      |--- log_format_msg [count=1, lines=86]
|
|--- log_format_msg [count=1, lines=86]


Как из текстого документа вытащить определенную строку? [закрыт]

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

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

Закрыт 6 месяцев назад.

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

Есть текстовый файл, где с новый строчки записаны ну допустим id, и мне нужно в вытащить именно вторую строчку из этого документа и вывести ее, как это реализовать ?

with open("file.txt", "r") as f:
    lines = f.readlines()
print(lines[1])  # вывести вторую строку файла


Как сделать движение объекта по направлению курсора?
У меня есть игрок который выпускает пули, и я пытался сделать так, чтоб он стрелял по направлению курсора, чтоб лучше попадать во врагов, но столкнулся с проблемой, что чем дальше я отходил от начала карты (~644, 720), тем выше начинали лететь пули, и они уже не летят по направлению мышки, а лишь вверх в какую-то точку.

if mkeys[0] and not self.attack_pressed:
    self.last_shoot = coltdown
    mouse_pos = pygame.mouse.get_pos()

    # Находим точки начала и конца атаки
    x_start, y_start = self.rect.centerx, self.rect.centery
    x_end, y_end = mouse_pos[0], mouse_pos[1]

    # Добавляем смещение между игроком и точкой начала атаки
    x_offset, y_offset = self.rect.centerx - (map_width / 2), self.rect.centery - (map_height / 2)
    x_start -= x_offset
    y_start -= y_offset
    x_end -= x_offset
    y_end -= y_offset

    # Нормализуем вектор направления атаки
    dx, dy = x_end - x_start, y_end - y_start
    length = math.sqrt(dx ** 2 + dy ** 2)
    dx, dy = dx / length, dy / length

    # Учесть размеры карты
    dx *= map_width / max(map_width, map_height)
    dy *= map_height / max(map_width, map_height)

    atack = Atack(self.rect.centerx, self.rect.centery, (dx, dy))
    sprites.add(atack)

    self.attack_pressed = True

Код выпуска пуль, так сказать.

# атака
class Atack(Item):
    def __init__(self, x, y, direction):
        super().__init__(ATACK_HITBOX, WHITE)
        self.image = pygame.Surface(ATACK_HITBOX)
        self.image.fill(RED)
        self.rect = self.image.get_rect(center=(x, y))
        self.direction = direction
        self.speed = 15
        self.lifetime = 100 # время жизни атаки в кадрах
        self.attack_pressed = False
        self.coltdown = pygame.time.get_ticks()

    # движение атаки
    def move(self):
        # перемещаем атаку вдоль вектора направления с определенной скоростью
        dx = self.direction[0] * self.speed
        dy = self.direction[1] * self.speed
        self.rect.x += dx
        self.rect.y += dy
#другой код.

Код некой пули.

Пытался попросить помощи у нейросети, но ничего не помогло, честно говоря понятия не имею что мне нужно сделать.

Я использую библиотеку PyTMX для импрорта карты! Может это имеет значение?

Если вдруг кому помогу:
Всё это время я допускал огромную ошибку - я вычислял координаты мыши используя координаты игрока, а так как карта большая, то и координаты были больше координат расположения мыши, из-за этого пули стреляли высоко вверх а не по направлению мыши. Решение оказалось проще, чем я думал.
Нужно было считывать координаты мыши и использовать при этом координаты монитора, а не карты, тогда всё заработало.
<code>
# выглядит это так:
screen_size = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)

# Получаем координаты мыши относительно экрана
mouse_pos = pygame.mouse.get_pos()

# Вычисляем координаты мыши относительно центра экрана
mouse_x = mouse_pos[0] - screen_size[0] // 2 + self.rect.centerx
mouse_y = mouse_pos[1] - screen_size[1] // 2 + self.rect.centery

# Вычисляем направление
angle = np.arctan2(mouse_y - self.rect.centery, mouse_x - self.rect.centerx)
dx = np.cos(angle)
dy = np.sin(angle)
self.direction = (dx, dy)

# движение атаки
def move(self):
    # перемещаем атаку
    self.rect.x += self.speed * self.direction[0]
    elf.rect.y += self.speed * self.direction[1]
</code>
Вот так, решение оказалось довольно проще, чем я думал! :)


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

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


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

Для того, что бы увидеть, какие файлы есть в папке, можно использовать модуль
os, с помощью него, можно выполнить команду
dir (если вы на
Windows)

import os

def getFileNames(nameDir, delTemp=True):
    os.system(f"dir {nameDir} /b > temp.txt")

    fileNames=[]

    with open("temp.txt", encoding="cp866") as f:
        fileNames=f.read().splitlines()

    if delTemp:os.system("del temp.txt")
    return fileNames


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

import logging

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
handler = logging.FileHandler('bot.log')
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)

Попробуй убрать
basicConfig и использовать два
handler-а в своем
logger-е

import logging

logger = logging.getLogger(__name__)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)

file_handler = logging.FileHandler('bot.log')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)


Запись чисел в файл - каждое число с новой строки
Задание звучало так: "Создайте текстовый файл с целыми числами, находящимися в
нескольких строках файла, разделенные пробелами внутри строк
(с помощью приложения Блокнот или WordPad). Чтение чисел из
существующего файла и создание двух новых файлов: в один
записываются четные числа, в другой – нечетные (каждое число с
новой строки)."
Файл я создала с помощью блокнота, его содержимое:

6 46 7878
45 428 547 8
4 9876 1 4567 7
0

Код:

c2 = open("C:/Users/user/Desktop/PythonFiles/ch2.txt",'r')
chet = open("chet.txt",'w')
nechet = open("nechet.txt",'w')
for l in c2:
    #print(l.strip()) вывод без преобразования в списки целых чисел
    #print(list(map(int,l.split(' '))))
    chet.write(str([i for i in map(int,l.split(' ')) if i%2 == 0])+'\n')
    nechet.write(str([i for i in map(int,l.split(' ')) if i%2 != 0])+'\n')
chet.close()
nechet.close()
with open('chet.txt','r') as ch:
    print(ch.read())

with open('nechet.txt','r') as nech:
    print(nech.read())
c2.close()

Вывод следующий:

[6, 46, 7878]
[428, 8]
[4, 9876]
[0]

[]
[45, 547]
[1, 4567, 7]
[]

Желаемый вывод:

6
46
7878
428
8
4
9876
0

45
547
1
4567
7

Понимаю, что решение какое-то очевидное, но додуматься не могу. Заранее спасибо за помощь

Записывай каждое число отдельно:

[chet.write(f'{i}\n') for i in map(int, l.split(' ')) if i % 2 == 0]
[nechet.write(f'{i}\n') for i in map(int, l.split(' ')) if i % 2 != 0]

Либо сформируй список, переведи каждое значение в строку и записывай через функцию
join,
<your_path_to_nums> - путь до файла с числами:

with open('<your_path_to_nums>', 'r', encoding='utf-8') as nums:
    nums = nums.read().split()
    odd = [num for num in map(int, nums) if num % 2 != 0]
    even = [num for num in map(int, nums) if num % 2 == 0]

    with open('odd.txt', 'w') as ods:
        ods.write('\n'.join(map(str, odd)))

    with open('even.txt', 'w') as evens:
        evens.write('\n'.join(map(str, even)))


Как задать радиус скругления углам прямоугольника на PyGame?
У меня есть прямоугольник, но углы у него острые, и я хочу добавить некий "радиус" чтоб углы стали глаже. Как это сделать?

pygame.draw.rect(surface, color, self.rect) - сам прямоугольник

Вам может помочь параметр border_radius.
Пример:
<code>
rect = pygame.Rect(100, 100, 200, 100)
radius = 40
pygame.draw.rect(surface, color, rect, border_radius=radius)
</code>


Aiogram. Конвертация jpg в png
День добрый. Создаю бота, цель которого пока что принять от пользователя фото в формате .jpg и конвертировать в .png, ну и отправить пользователю.
Мой код (не работает):
<code>
import logging
import io
import os

from aiogram import Bot, types, Dispatcher
from aiogram.utils import executor
from PIL import Image

# установка уровня логирования
logging.basicConfig(level=logging.INFO)

dp = Dispatcher(bot)

@dp.message_handler(commands=['start'])
async def start_command(message: types.Message):
    await message.reply("Привет. Скинь фотографию в формате .jpg")

@dp.message_handler(content_types=types.ContentType.PHOTO)
async def convert_photo(message: types.Message):
    photo = message.photo[-1]
    file = await photo.get_file()
    photo_info = {'file_id': file.file_id, 'file_size': file.file_size, 'file_path': file.file_path, 'width': photo.width, 'height': photo.height}
    photo_bytes = await file.download()

    with Image.open(io.BytesIO(photo_bytes)) as im:
        with io.BytesIO() as output:
            im.save(output, format="png")
            output.seek(0)
            await message.answer_photo(output.getvalue())

if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)`
</code>
Подскажите в чем проблема, заранее благодарен.

Вот хэндлер, который будет ловить присланную картинку и отправлять обратно
png-файлом. Важно, чтобы бот отвечал именно документом, так как при отправке телеграм конвертирует все картинки в
jpg

@dp.message_handler(content_types='photo')
async def convert_photo(message: types.Message):
    image = io.BytesIO()
    photo = message.photo[-1]
    file = await photo.download(destination_file=image)
    with Image.open(file) as im:
        im.save(image, format="png")
        image.seek(0)
        await message.answer_document(('your_file.png', image))


Представление списка в hex формате
Есть список

List = ['1', '0', '1', '0', '0', '0', '1']

Как привести его к виду
0b1010001, а затем в
hex?

Можно привести к int и далее куда требуется.
<code>
l = ['1','0','1','0','0','0','1']
val_int = int("".join(l), 2)
val_hex = hex(val_int)
val_bin = bin(val_int)
</code>


я в начале кода создал 3 переменые, как их можно вызвать в функциях [закрыт]

Закрыт. Этот вопрос необходимо уточнить или дополнить подробностями. Ответы на него в данный момент не принимаются.

Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение.

Закрыт 6 месяцев назад.

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

я делаю телеграм бота в начале кода я создал 3 переменые как я могу их вызвать в функциях?
<code>
import telebot
bot = telebot.TeleBot(токен)
counter = 0
const = 500
const_number = 500

@bot.message_handler(commands=['start'])
def start(message):
    bot.send_message(message.chat.id, 'Привет, введи число до 1000')
@bot.message_handler(content_types=['text'])
def game(message):
    number = int(message.text)
    while True:
        const_number = const_number // 2
        if const == number:
            bot.send_message(message.chat.id, f'Ваше число {const} я угадал число за {counter} попыток')
            break
        else:
            bot.send_message(message.chat.id, f'Ваше число больше {const} ?')
            @bot.message_handler(content_types=['да'])
            def true(message1):

bot.polling(none_stop=True)
</code>

как я могу их вызвать в функциях?

Никак. Вызывают функции. Переменные используют.
Использовать любую переменную можно в её области видимости. Если переменная определена в самом начале программы, вне любого блока, то её можно использовать в любом месте программы, так как она видна везде. Если она не переопределена внутри какого-то блока.
Однако, в Python использование такой глобальной переменной внутри любого блока (например - функции) разделяется на два типа:

Чтение значения переменной
Присвоение нового значения переменной.

Для первого пункта ничего делать не нужно. Если же вы внутри блока собираетесь менять значение глобальной переменной, то Вы должны явно сказать об этом интерпретатору питона оператором global. Например, в Вашем случае, это должно выглядеть так:
<code>
def game(message):
    global const_number
    . . .
    const_number = const_number + 1
</code>


На сервере не получается запустить сразу 2 программы на python
Я имею сервер на Ubuntu 22.04. Есть скрипт который срабатывает при запуске сервера.
Вот он:
<code>
#!/bin/bash
cd /root/Tic_tak_toe_project_2/Tic_tak_toe_project/
sudo /usr/bin/python3 main.py  > /dev/null
cd ~
cd /root/Scenario_bot/
sudo /usr/bin/python3 main.py  > /dev/null
</code>
Один main.py это сайт, второй это бот в Telegram
Почему-то запускается только main.py отвечающий за сайт(первый), а второй нет. Но если я вручную включаю второй main.py, он работает. Что не так я делаю?

Так происходит по той причине, что у вас не возвращается управление дальше в скрипт.

Оператор & используется для того, чтобы организовать исполнение команд в  фоновом режиме. Если поставить значок & после команды, то оболочка вернет  управление пользователю сразу после запуска команды, не дожидаясь, пока выполнение команды завершится. Например, если задать в командной строке     "command1 & command2 &", то оболочка запустит команду command1, сразу же затем команду command2, и затем немедленно вернет управление пользователю

<code>
#!/bin/bash
cd /root/Tic_tak_toe_project_2/Tic_tak_toe_project/
sudo /usr/bin/python3 main.py  > /dev/null &
cd ~
cd /root/Scenario_bot/
sudo /usr/bin/python3 main.py  > /dev/null &
</code>
По идее так должно сработать


Почему получаю при расчете в скрипте Python только одну итерацию?
При решении уравнения с одной переменной методом дихотомии мне, по условиям задачи, требуется рассчитать количество итераций при нахождении корней. За итерацию, как прочитал, можно принять количество делений отрезка пополам. Как минимум для каждого корня по одному разу отрезок делится. То есть количество итераций явно не будет меньше количества корней. Однако мой счетчик показывает лишь одно деление, то есть одну итерацию. Что не так?
Код:
<code>
import numpy as np
from decimal import *
import pandas as pd

def print_dichotomy(funcs):
    def wrapper(a,b, eps_func, eps_arg):
        *res, func, eps_list = list(funcs(a,b, eps_func, eps_arg))
        result_table = pd.DataFrame()
        result_table['Корни'] = pd.Series(res)
        print('Количество итераций: ', iter_count)
        print(result_table)
    return wrapper

def f(x):
    return 1.2-np.log(x)-4*np.cos(2*x)

@print_dichotomy
def dichotomy(a, b, eps_func, eps_arg):
    # 1. определим глобальную переменную (расчет количества итераций)
    global iter_count

    # 2. определим ограничения на границы отрезка
    assert a != 0, 'a равно 0'
    assert b != 0, 'b равно 0'

    # 3. запросим количество частей n, на которые будет дробиться отрезок
    n = int( input('Введите параметр n (целое число): ') )

    # 5. отделим корни
    # для этого разделим заданный отрезок на n частей
    grid = np.linspace(a, b, n)

    #  6. создадим счетчик для количества итераций
    iter_count = 0

    # 7. уточним наличие корней на каждом отрезке
    for x, y in zip(grid, grid[1:]):
        # 7.1. если на отрезке нет корня, смотрим следующий отрезок
        if f(x) * f(y) > 0:
            continue
        root = None
        # 7.2. уточним корни
        while abs(f((x+y)/2)) > eps_func and ((y - x)/2) > eps_arg:
            if y != x:
                # 7.2.1.1. получаем середину отрезка
                mid = (y + x) / 2
                # 7.2.1.2. пополним счетчик итераций на один (было одно деление пополам)
                iter_count =+ 1
                # 7.2.1.3. корень примем равным серединному значению:
                root = mid
                break
                # 7.2.1.5. иначе если произведение функции в середине отрезка на функцию в т. а <= 0:
                if Decimal(f(mid) * f(x)) <= 0:
                    # 7.2.1.5.1. серединой отрезка признаем точку b:
                    y = mid
                else:
                    # 7.2.1.5.3. в другом случае — точку а:
                    x = mid
        # 8. возвращаем рассчитанный корень
        if root:
            yield root

dichotomy(0.0001, 50, 0.000001, 0.000001)
</code>

В вашем коде вы используете глобальную переменную iter_count для подсчета количества итераций. Однако в строке
iter_count =+ 1 вы используете оператор =+, который присваивает значение 1 переменной iter_count, а не увеличивает ее на 1. Измените на
iter_count += 1


Как создать необязательный аргумент
Не понимаю как сделать необязательный аргумент для слеш команды в discord.py v2. Если я делаю аргумент для команды, он автоматически обязателен для заполнения. Мне нужно сделать так, чтобы он был необязателен.
<code>
#-- Команда чтобы написать человеку в лс --
@tree.command(name="ls_user", description="Написать определённым людям в лс")
async def message_user(ctx, title: str, text: str, url_image: str, people_id: str):
    if title == None:
        embed_send = discord.Embed(
            description=text
        )
    elif text == None:
        embed_send = discord.Embed(
            title=title
        )
    else:
        embed_send = discord.Embed(
            title=title,
            description=text
        )
    if url_image != None:
        embed_send.set_image(url=url_image)
    with io.StringIO(people_id) as f:
        reader = csv.reader(f)
        for row in reader:
            for i in row:
                y = int(i)
                r = bot.get_user(y)
                await r.send(embed=embed_send)
    CHANNEL_LOGS = bot.get_channel(CHANNEL_LOGS_ID)
    embed_log = discord.Embed(
        title = "Отправка в лс",
        description = f"Загаловок: {title}\nТекст: {text}\nURL-картинки: {url_image}\nЛюди: {people_id}",
        colour = 0x66CDAA
    )
    await CHANNEL_LOGS.send(embed=embed_log)
</code>

Почитайте здесь про работу с аргументами в
slash-командах.
Если вкратце, то в качестве аннотации типа лучше указывать не базовые типы, а экземпляр класса
discord.Option, один из параметров которого позволяет сделать аргумент необязательным:

from discord import Option

@bot.slash_command()
async def test(ctx, arg: Option(str, required=False)):
    . . .

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


Как скачать аватарку пользователя telegram с помощью бота?
Пишу с помощью библиотеки
telebot
Моя задача получить аватарку пользователя через телеграмм-бота и скачать её для дальнейшей обработки в библиотеке
Pillow (я это уточняю на случай, если есть возможность как-то интегрировать эти библиотеки)
У меня есть тестовый код, который работает для скачивания отправленной пользователем фотографии, только я попытался адаптировать её для скачивания его аватарки.
Я вывел данные фотографии профиля пользователя и получил это:

{'file_id': 'какой-то id', 'file_unique_id': 'AQAD68oxG4vJoEkB', 'width': 640, 'height': 640, 'file_size': 66835}.

Как видно, здесь нету нужного мне параметра
file_path, необходимого для скачивания.
Если кто знает, подскажите, возможно ли вообще сделать то, что я задумал? Если есть возможность сделать это, используя другую библиотеку для telegramm бота, то я готов её сменить.
Вот мой код:

import telebot
from random import randint as r
from telebot import types
from PIL import Image, ImageDraw, ImageFont
import os

token='TOKEN'
bot=telebot.TeleBot(token)

@bot.message_handler(content_types=['text', 'photo'])
def handle_docs_document(message):

    file_photo = bot.get_user_profile_photos(message.from_user.id)
    print(file_photo.photos[0][2])
    file_name, file_extension = os.path.splitext(file_photo.file_path)

    downloaded_file = bot.download_file(file_photo.file_path)

    src = 'photos/' + message.photo[-1].file_id + '.jpg'
    with open(src, 'wb') as new_file:
        new_file.write(downloaded_file)

bot.infinity_polling()

чтобы сохранить аватарку из
get_user_profile_photos к себе на комп, можно так поступить. После того как получили объект аватарок, заберем из него
id самой актуальной фотографии, а затем через
get_file и
download_file сохраним фотографию себе в систему.

import telebot

# токен
bot = telebot.TeleBot("ТВОЙТОКЕН")

# дефайним /start
@bot.message_handler(commands=['start'])
def send_avatar(message):
    # Получаем ID чата пользователя
    chat_id = message.chat.id

    # Получаем фотографии профиля
    photos = bot.get_user_profile_photos(chat_id)

    # Получаем ID фотографии профиля
    photo_id = photos.photos[0][-1].file_id

    # Скачиваем фото на локальную систему
    file_info = bot.get_file(photo_id)
    file = bot.download_file(file_info.file_path)

    # Сохраняем файл на хосте
    with open('avatar.jpg', 'wb') as f:
        f.write(file)

    # фидбэчим пользователю.
    bot.reply_to(message, "твоя ватарка сохранена")

bot.polling()


Как совершается очистка очереди от задач? / Как удалить задачу из брокера?
Я хочу автоматически очищать выполненные задачи( статус и id) из очереди. Результат задачи я очищаю автоматически прописав
result_expires.
Но  айди и статус все еще в брокере, как это можно очистить? Использую
redis в качестве брокера.
Я нашел вроде бы ответ, но там нужно самому залезать в брокер и очищать руками, хотелось бы делать это через
celery.
И буду очень благодарен, если кто-нибудь объяснит, как работает весь процесс очистки мусора в
celery.

Всё оказалось куда проще:
во-первых,
pending означает, что он не знает о задаче.
По умолчанию, задача всегда
pending до
SUCCESS, если не включен
task_track_started.
Когда, воркер забирает задачу, он ее сразу удаляет из брокера(в моем случае
redis) и хранит о ней состояние уже в backend.
Это можно просмотреть открыв
redis:

redis-cli
keys *
LRange MyQueue 0 -1


Считать и сбрасывать глубину цепочки в DFS Python
Есть граф следующего формата:

graph = {
    '1': ['2', '34', '4'],
    '2': ['4', '9', '3', '65', 14],
    '3': ['18', '7', '1'],
    '4': ['3', '11'],
    '5': ['11', '3', '4'],
    ...
}

Вводная:
Все числа это id пользователей. Сам граф показыват связь учитель-ученик. То есть, например, у юзера 4 есть ученики 3 и 11. В графе также могут присутствовать "двойные" связи, когда оба юзера приходятся друг другу и учителем и учеником.
Задача:
Нужно пройтись по графу и за каждого ученика, внученика, правнученика (и так до последнего "пра") посчитать для учителя определенные очки. Для каждое вну/пра даются свои очки.
Что я делаю:
Я прохожусь по графу DFSом, считаю глубину цепочки и в зависимости от текущей грубины назначаю очки за ученика/внученика/правнученика и т.д. Однако, подсчет глубины цепочки нужно сбрасывать, каждый раз, когда я возвращаюсь обратно к корню графа, чтобы правильно назначать очки за учеников. И вот на этом моменте я сдулся, не помнию, как сбросить счетчик глубины, и точно ли я вообще иду в том направлении. Подскажите/направьте пожалуйста.
Код:

def dfs(visited, graph, node, chain):
    points = 0
    if node not in visited:
        visited.add(node)
        for neighbour in graph[node]:
            if chain == 0:
                points += 2
                chain += 1
            elif chain == 1:
                points += 1
                chain += 1
            elif chain > 1:
                points += 0.1 / chain
                chain += 1
            points += dfs(visited, graph, neighbour, chain)
    return points

def run():
    users = list(users_collection.find({}))
    graph = get_graph(users)
    for user in users:
        visited = set()
        total_points = dfs(visited, graph, str(user['_id']), 0)
        print(user['name'], total_points, user['_id'])

if __name__ == "__main__":
    run()

Уберите все
chain += 1, а вот в рекурсивном вызове

points += dfs(visited, graph, neighbour, chain+1)


Как удалить все что внутри восклицательных знаков?
У меня есть код, который возвращает строку:

Что-то что-то
!Что-то что-то Что-то что-то!
Что-то что-то

Как удалить все что внутри восклицательных знаков, чтобы было вот так:

Что-то что-то
Что-то что-то

Можно попробовать вот так:

# импортируем модуль регулярных выражений
import re
# задаем текст
text = "Что-то что-то\n!что угодно, все что ты захочешь 03245к903ушкаущцойашво мшапкуц0щйл!\nЧто-то что-то"
# используя регулярное выражение, чистим текст
text = re.sub("!.*?!\n", "", text)
# выводим
print(text)

вывод:

Что-то что-то
Что-то что-то

P.S. моё регулярное выражение чистит в том числе и строку, если необходимо просто удалить что-то внутри восклицательных знаков, уберем из регулярного выражения
\n

import re
text = "Что-то что-то\n!что угодно, все что ты захочешь 03245к903ушкаущцойашво мшапкуц0щйл!\nЧто-то что-то"
text = re.sub("!.*?!", "", text)
print(text)

вывод:

Что-то что-то

Что-то что-то


Не работает декоратор метода класса
Пока я использую декоратор без
@, всё вызывается и работает, но когда я пытаюсь вызвать декоратор через
@, декоратор не находит декорируемую функцию. Использовать декоратор без "собачки" можно, но неудобно. Подскажите, пожалуйста, в чем здесь дело? Заранее благодарен!

import time

class Cls:
    def __init__(self, file_name):
        print(f'constructor -> "{file_name}"')  # .....

    def chronometer(self, func):  # Метод-Декоратор
        def wrapper(*args, **kwargs):
            print(f'{func.__name__} - started')
            func(*args, **kwargs)
            print(f'{func.__name__} - finished')

        return wrapper

    @chronometer                    # (Не могу ПРИДЕЛАТЬ декоратор через собачку-@)
    def decorated_fun(self):  # декорируемый Метод
        for i in range(5):
            print(f'  ***** ({i})')  # .....
            time.sleep(0.2)

    def apply(self):  # Метод применения Декоратора
        # --------------------------------------------------------------------------
        # # Вариант 1: - (без собачки-@)  # (РАБОТАЕТ!)
        # self.chronometer(self.decorated_fun)()
        # --------------------------------------------------------------------------
        # # Вариант 2: - (без собачки-@)  # (РАБОТАЕТ!)
        # self.decorated_fun = self.chronometer(self.decorated_fun)
        # self.decorated_fun()
        # --------------------------------------------------------------------------
        # Вариант 3: - (с собачкой-@)  # (НЕ РАБОТАЕТ!)
        self.decorated_fun()
        # --------------------------------------------------------------------------
        pass

# обращение:
cls = Cls('aquarius.dat')
cls.apply()

# Вывод:
# constructor -> "aquarius.dat"
# decorated - started
#   ***** (0)
#   ***** (1)
#   ***** (2)
#   ***** (3)
#   ***** (4)
# decorated - finished

Нужно переделать декоратор,
self убрать во
wrapper:

    def chronometer(func):  # Метод-Декоратор
        def wrapper(self, *args, **kwargs):
            print(f'{func.__name__} - started')
            func(self, *args, **kwargs)
            print(f'{func.__name__} - finished')
        return wrapper

Рецепт подсмотрен на английском СО.
Но вообще так лучше не делать, как написано там же. Декораторы лучше не помещать в классы.


Вложенные списки в python?

Как создать вложенный список
5x5: и добавить в него значение
"MyValue", например, так?:

list[4][4]="MyValue"

Как считать значение вложенного списка в переменную?

Str=list[4][4]

Как итерировать по элементам вложенного списка в цикле(или во вложенном цикле)?

К сожалению, у вас многое неправильно.
Не называйте переменную именем встроенного типа.
Эта конструкция
list=[5],[5] НЕ создает  список 5x5, а делает два списочка по одному элементу со значением 5, и объединяет их в кортеж (tuple)
Чтобы создать двумерный список, можно использовать списковое включение (я сделал покороче)

lst = [[0]*3 for _ in range(3)]

или поэлементно добавляя  одномерные списки

 lst = []
 for i in range(3):
    lst.append([0]*3)

Если вы хотите добавлять элементы к подспискам, то это делается append-ом к элементам первого уровня

lst[2].append(6)

P.S. При сомнениях в правильности получаемых структур просто печатайте их print-ом

[[0, 0, 0], [0, 0, 0], [0, 0, 0, 6], [0, 0, 0], [0, 0, 0]]


Очистка чата пользователя с телеграмм ботом от всех сообщений
Мне нужно очищать приватный чат пользователя с Telegram-ботом от всех сообщений, или как-то пересоздавать для него чат. Допустим, ввожу команду
/start, отображается текст с Inline кнопками. Когда пользователь нажимает на какую-либо из кнопок или пишет команду, с помощью
message.edit_text(), меняется содержимое сообщения от бота. Но когда я ввожу повторно команду
/start, мне нужно чтобы весь чат очищался, хотя бы локально для пользователя.

Примерный код, который должен помочь:

def start(update, context):
    # Получаем chat_id и user_id отправителя сообщения
    chat_id = update.effective_chat.id
    user_id = update.effective_user.id

    # Удаляем все сообщения пользователя и бота в личном чате
    messages = context.bot.get_chat_history(chat_id)
    for message in messages:
        # Проверяем, что сообщение не является командой /start
        if message.text != '/start':
            context.bot.delete_message(chat_id, message.message_id)

В /start

    # Сохраняем id нового сообщения пользователя в контекст
    context.chat_data['user_messages'] = [message.message_id]

таким образом, используя
context можно хранить в нем ид пользователя и при втором вызове
/start чистить лс.


Как написать сам метод для получения людей, и цикл, которые будет смотреть их online статус?
Делаю команду /members, которая будет выводить что-то следующее:
<code>
Количество участников в беседе: 3, из них онлайн онлайн: 2 #например

1. Петя Иванов (онлайн)
2. Иван Петров (оффлайн)
3. Пиван Итров (онлайн)
</code>
С количеством людей всё хорошо ('messages.getConversationMembers', {'peer_id': msg['peer_id'], 'fields': 'count'), но вот с онлайн не могу разобраться.
Можете, кому не сложно, написать сам метод для получения людей, и цикл, которые будет смотреть их online статус.

Удивительно, но метод для получения людей это
users.get с дополнителным полем онлайна (
fields="online"). Цикл писать не нужно, вы можете передавать несколько пользователей через запятую. Дальше обработка json в удобный формат.

Код писать не буду, поскольку реализация идеи будет отличаться в разных библиотеках.


Как закрепить камеру на персонаже в pygame? [закрыт]

Закрыт. Этот вопрос необходимо уточнить или дополнить подробностями. Ответы на него в данный момент не принимаются.

Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение.

Закрыт 6 месяцев назад.

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

<code>
import pygame as pg
from level_1 import*
pg.init()
tiles = 30
window=pg.display.set_mode((tiles*50,tiles*30))
pg.display.set_caption('Mario')

mario_walk = 0

class Game_sprite():
    def __init__(self, image, x,y , w,h, speed):
        self.image=pg.transform.scale(pg.image.load(image),(w,h))
        self.w=w
        self.h=h
        self.speed=speed
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.isJump = False
        self.jumpCount=10
    def reset(self):
        window.blit(self.image,(self.rect.x,self.rect.y))

class Player(Game_sprite):
    def control(self):
        global mario_walk
        keys=pg.key.get_pressed()
        if keys[pg.K_SPACE]:
            self.isJump = True
        if self.isJump is True:
            if self.jumpCount >= -10:
                if self.jumpCount < 0:
                    self.rect.y += (self.jumpCount ** 2) // 2
                else:
                    self.rect.y -= (self.jumpCount ** 2) // 2
                self.jumpCount -= 1
            else:
                self.isJump = False
                self.jumpCount = 10

        if keys[pg.K_d]:
            self.rect.x+=self.speed

            self.image=pg.transform.scale(pg.image.load(f'images/mario_walk_right/mario_walk-{mario_walk}.png'),(self.w,self.h))
            mario_walk+=1
            if mario_walk>7:
                mario_walk=0

            if self.isJump == True:
                self.image = pg.transform.scale(
                pg.image.load("images/mario_walk_right/mario_walk-4.png"), (self.w, self.h)
                )

        if keys[pg.K_a] and self.rect.x>0:
            self.rect.x-=self.speed
            self.image=pg.transform.scale(pg.image.load(f'images/mario_walk_left/mario_walk-{mario_walk}.png'),(self.w,self.h))
            mario_walk+=1
            if mario_walk>7:
                mario_walk=0

            if self.isJump == True:
                self.image = pg.transform.scale(
                pg.image.load("images/mario_walk_left/mario_walk-4.png"), (self.w, self.h)
                )

platform = []

for i in range(len(map_list)):
    for j in range(len(map_list[i])):
        print(map_list[i][j])
        if map_list[i][j]=='1':
            platform.append(Game_sprite('images/objects/platform.png',j*tiles,i*tiles,tiles,tiles,0))
bg = Game_sprite('images/bg/bg.png', tiles-tiles, tiles-tiles, tiles*50,tiles*30, 0)
mario = Player('images/mario_walk_right/mario_walk-0.png', tiles, tiles*26, tiles*2, tiles*2, 15)
game = True
while game:
    pg.time.Clock().tick(120)
    for i in pg.event.get():
        if i.type==pg.QUIT:
            exit()
    bg.reset()
    mario.reset()
    mario.control()
    for i in platform:
        i.reset()
    pg.display.flip()
</code>

import pygame as pg
from level_1 import*
pg.init()
tiles = 30
window=pg.display.set_mode((tiles*50,tiles*30))
pg.display.set_caption('Mario')

mario_walk = 0

class Game_sprite():
    def __init__(self, image, x,y , w,h, speed):
        self.image=pg.transform.scale(pg.image.load(image),(w,h))
        self.w=w
        self.h=h
        self.speed=speed
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.isJump = False
        self.jumpCount=10
    def reset(self):
        window.blit(self.image,(self.rect.x,self.rect.y))

class Player(Game_sprite):
    def control(self):
        global mario_walk
        keys=pg.key.get_pressed()
        if keys[pg.K_SPACE]:
            self.isJump = True

        if self.isJump is True:
            if self.jumpCount >= -10:
                if self.jumpCount < 0:
                    self.rect.y += (self.jumpCount ** 2) // 2
                else:
                    self.rect.y -= (self.jumpCount ** 2) // 2
                self.jumpCount -= 1
            else:
                self.isJump = False
                self.jumpCount = 10

        if keys[pg.K_d]:
            if self.rect.x<=tiles*25:
                self.rect.x+=self.speed
            else:
                for i in s:
                    i.rect.x -= self.speed

            self.image=pg.transform.scale(pg.image.load(f'images/mario_walk_right/mario_walk-{mario_walk}.png'),(self.w,self.h))
            mario_walk+=1
            if mario_walk>7:
                mario_walk=0

            if self.isJump == True:
                self.image = pg.transform.scale(
                pg.image.load("images/mario_walk_right/mario_walk-4.png"), (self.w, self.h)
                )

        if keys[pg.K_a] and self.rect.x>0:
            if self.rect.x>tiles*10:
                self.rect.x-=self.speed
            else:
                if ground[0].rect.x<0:
                    for i in s:
                        i.rect.x += self.speed

            self.image=pg.transform.scale(pg.image.load(f'images/mario_walk_left/mario_walk-{mario_walk}.png'),(self.w,self.h))
            mario_walk+=1
            if mario_walk>7:
                mario_walk=0

            if self.isJump == True:
                self.image = pg.transform.scale(
                pg.image.load("images/mario_walk_left/mario_walk-4.png"), (self.w, self.h)
                )

s = []

pipe = []
pipe_s = []
box = []
platform = []
ground = []
for i in range(len(map_list)):
    for j in range(len(map_list[i])):
        if map_list[i][j]=='p':
            pipe.append(Game_sprite('images/objects/pipe.png',j*tiles,i*tiles,tiles,tiles,0))

for i in range(len(map_list)):
    for j in range(len(map_list[i])):
        if map_list[i][j]=='s':
            pipe.append(Game_sprite('images/objects/pipe_s.png',j*tiles,i*tiles,tiles,tiles,0))

for i in range(len(map_list)):
    for j in range(len(map_list[i])):
        if map_list[i][j]=='b':
            box.append(Game_sprite('images/objects/box.png',j*tiles,i*tiles,tiles,tiles,0))

for i in range(len(map_list)):
    for j in range(len(map_list[i])):
        if map_list[i][j]=='1':
            platform.append(Game_sprite('images/objects/platform.png',j*tiles,i*tiles,tiles,tiles,0))

for i in range(len(map_list)):
    for j in range(len(map_list[i])):
        if map_list[i][j]=='g':
            ground.append(Game_sprite('images/objects/ground.png',j*tiles,i*tiles,tiles,tiles,0))

bg = Game_sprite('images/bg/bg.png', tiles-tiles, tiles-tiles, tiles*50,tiles*30, 0)
mario = Player('images/mario_walk_right/mario_walk-0.png', tiles*10, tiles*26, tiles*2, tiles*2, 15)
game = True

for i in ground:
    s.append(i)
for i in platform:
    s.append(i)
for i in pipe:
    s.append(i)
for i in pipe_s:
    s.append(i)
for i in box:
    s.append(i)
s.append(bg)
while game:
    pg.time.Clock().tick(120)
    for i in pg.event.get():
        if i.type==pg.QUIT:
            exit()
    bg.reset()
    mario.reset()
    for i in pipe:
        i.reset()
    for i in pipe_s:
        i.reset()
    for i in box:
        i.reset()
    for i in platform:
        i.reset()
    for i in ground:
        i.reset()
    mario.control()
    pg.display.flip()


Как называется функция в пайтоне подобная map в arduino wiring и processing?
В arduino wiring и processing, как я помню, есть функция
map(), которая принимает значение,которое меняется пропорционально другим значениям. Например:

int val_out = (int)map(val_in, 0, 10, 0, 100); // если val_in = 5, то val_out = 50

Как называется подобная функция в PYTHON?

Простую пропорцию можно написать за пару минут.
Вроде бы так, если нигде в синтаксисе не напутал (python - не моё...)
<code>
def map(x,a,b,c,d):
   return (x-a)*(d-c)/(b-a)+c
</code>


Регулярное выражение четных чисел
Нужно написать регулярное выражение, которое будет соответствовать любому (положительному или отрицательному) четному числу, например, -4, 1000, -20и т. д.
У меня не получается

(?<![-\d])(?<!\d[.,])\d*\[24680](?![.,]?\d)

(?<![-\d])(?<!\d[.,])\d*\[24680](?![.,]?\d)

не работает

Для того чтобы написать регулярное выражение, которое будет соответствовать любому четному числу включая отрицательные, можно использовать следующее выражение:
<code>
^-?\d*[02468]$
</code>
Это выражение состоит из нескольких частей:

^ - начало строки
-? - необязательный символ минуса
\d* - любое количество цифр
[02468] - одна из цифр 0, 2, 4, 6, 8
$ - конец строки

Таким образом, выражение будет соответствовать любому числу, начинающемуся с необязательного символа минуса, за которым следует любое количество цифр, заканчивающихся четной цифрой.


не могу найти ошибку в коде на питоне
я решала следующую задачу на питоне:

Найти минимальное и максимальное из чётных положительных чисел,
записанных в файле input.txt . Количество чисел неизвестно.  Если в
файле нет чётных положительных чисел, нужно вывести число 0.
Результат записать в файл output.txt .

Причем в задаче ввод вывод должны быть выполнены в двух файлах. У меня получился код:
<code>
with open ("input.txt") as file:
    counter=0
    mi=100001
    ma=0
    for line in file:
        num=int(line)
        if num%2==0 and num>=0:
            if num<mi:
                mi=num
                counter+=1
            if num>ma:
                ma=num
                counter+=1
            else:
                counter+=1
    if counter==0:
        print(0, file=open("output.txt", "w"))
    else:
         print(mi, ma, file=open("output.txt", "w"))
</code>
Моя проблема в том, что после отправки кода в проверяющую систему (информатикс) оказалось, что на 7 тестов программа выдает неверный ответ (к сожалению, эти тесты неизвестны). Как исправить?

Откуда вы знаете, что минимум меньше
100001? Используйте
None в качестве индикатора отсутствия значения:

mi = None
...
            if mi is None or num < mi:
                mi = num

Файл для вывода нужно открывать так же через
with, как и для ввода. Иначе нет гарантии, что содержимое буфера будет уже записано в файл в момент проверки.

Положительное число - это число строго больше нуля, так что не
num >= 0, а
num > 0 проверка должна быть.

Ну и тут не сказано, какой должен быть формат вывода в файл, если минимум и максимум найдены. Может там они на отдельных строках должны быть, например?


Как из переменной переданной в функцию использовать его значение?
Подскажите пожалуйста как мне использовать значение переменной? Работаю с ORM peewee, и при измененении, необходимо обновить значение в SQL базе. Это общая функция на несколько таблиц, с разными названиями столбцов. active_column как раз содержит названия столбца и это название надо прокинуть в update.
<code>
def update_row_tabl(self, row, column, text_cell, table_used, hat_name):
    active_column = list(hat_name)[column]
    table_used.update(active_column = text_cell).where(table_used.id == (row + 1)).execute()
</code>
Отрабатывает с ошибкой: peewee.OperationalError: near "WHERE": syntax error

Спасибо, Acinit! Это рабочий вариант:
**{active_column: text_cell}