Как упростить код функции?
Задача: вернуть список заказов с опциональной передачей аргументов
limit (это максимум сколько записей вернуть), и
offset (это сколько сместить с начала)
Вот мой код, он работает, но мне кажется можно записать попроще, но не приходит в голову, как?
Основная проблема в том, что их могут и не передать, или передать только один, поэтому приходится каждый случай портянками обрабатывать...

def get_queryset(self):
    limit = self.request.query_params.get('LIMIT')
    offset = self.request.query_params.get('OFFSET')
    limit = int(limit) if limit else None
    offset = int(offset) if offset else None
    if limit and offset:
        return Orders.objects.all()[offset:offset+limit]
    if limit:
        return Orders.objects.all()[:limit]
    if offset:
        return Orders.objects.all()[offset:]
    return Orders.objects.all()

Для наглядности

data = [1, 2, 3, 4, 5]
offset = 3
limit = 2

data[(offset or 0):(offset or 0)+(limit or 0)]
# [4, 5]

В вашем случае

def get_queryset(self):
# Можно так если отсутствие лимита означает максимальный лимит
# (При наличии большого набора данных может быть тяжко)
#    limit = int(self.request.query_params.get('LIMIT', len(Orders.objects.all())))
# Или так. Если считать отсутствие лимита как то, что его забыли указать
    limit = int(self.request.query_params.get('LIMIT', 0))
    offset = int(self.request.query_params.get('OFFSET', 0))
    return Orders.objects.all()[offset: offset + abs(limit)]


disnake реакция на сообщение
Я пытаюсь понять как сделать реакцию на сообщение, но никак не получается, ищу в документации disnake, ничего. Одна и таже ошибка:

@bot.slash_command()
async def reaction(inter):
    emoji = "👍"
    message = await inter.response.send_message("Окей")
    await message.add_reaction(emoji)

Ошибка:

Ignoring exception in slash command 'reaction':
Traceback (most recent call last):
  File "/home/runner/ThinWirelessMigration/venv/lib/python3.10/site-packages/disnake/ext/commands/slash_core.py", line 730, in invoke
    await call_param_func(self.callback, inter, self.cog, **kwargs)
  File "/home/runner/ThinWirelessMigration/venv/lib/python3.10/site-packages/disnake/ext/commands/params.py", line 1022, in call_param_func
    return await maybe_coroutine(safe_call, function, **kwargs)
  File "/home/runner/ThinWirelessMigration/venv/lib/python3.10/site-packages/disnake/utils.py", line 599, in maybe_coroutine
    return await value
  File "main.py", line 194, in reaction
    await message.add_reaction(emoji)
AttributeError: 'NoneType' object has no attribute 'add_reaction'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/runner/ThinWirelessMigration/venv/lib/python3.10/site-packages/disnake/ext/commands/interaction_bot_base.py", line 1353, in process_application_commands
    await app_command.invoke(interaction)
  File "/home/runner/ThinWirelessMigration/venv/lib/python3.10/site-packages/disnake/ext/commands/slash_core.py", line 739, in invoke
    raise CommandInvokeError(exc) from exc
disnake.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'add_reaction'

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


Как используя add_radiobutton() для каскада в Menu() из Tkinter установить галочку по умолчанию напротив одного из значений?
Когда запускается программа с размерами по умолчанию, например 10х10, в подменю size галочка уже должна стоять напротив строки
10х10. Пробовал ответ отсюда, но тогда изначально галочки все равно нет, а если её поставить, то она уже не снимается. Нужно изначально указать один из вариантов, а дальше чтобы можно было выбирать любой вариант

from tkinter import Tk, Menu

root = Tk()
menubar = Menu(root)
size = Menu(menubar, tearoff=0)
size.add_radiobutton(label='5x5')
size.add_radiobutton(label='10x10')  # <- Нужно чтобы тут сразу стояла галочка при запуске.
                                     # А при выборе другого варианта она снималась,
                                     # как и в данном примере
size.add_radiobutton(label='15x15')
menubar.add_cascade(label='Size', menu=size)
root.config(menu=menubar)
root.mainloop()

В англоязычной версии сайта подсказали как правильно использовать
IntVar со значением по умолчанию,
variable и
value. В реальности я это всё в методе класса применял, поэтому чтобы заработало пришлось
self.size_var использовать. В остальном способ идеально решил проблему

from tkinter import Tk, Menu, IntVar

root = Tk()
menubar = Menu(root)
size = Menu(tearoff=0)
size_var = IntVar(value=10)
size.add_radiobutton(label='5x5', variable=size_var)
size.add_radiobutton(label='10x10', variable=size_var, value=10)
size.add_radiobutton(label='15x15', variable=size_var)

menubar.add_cascade(label='Size', menu=size)
root.config(menu=menubar)
root.mainloop()


Ошибка добавления элементов в список [дубликат]

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

Копируются списки

                                (4 ответа)

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

Почему элементы дублируются в списках
a и
b, если добавляется только в
a

a = []
b = a
for i in range(10):
    a.append(i)
print(f'{a=} {b=}')

Списки не переприсваиваются на прямую. Нужно делать копию, чтобы на разную память ссылались.
<code>
a = []
b = a.copy()
for i in range(10):
    a.append(i)
print(f'{a=} {b=}')
</code>


Добавить пропущенные даты к каждой группе
Есть датафрейм:

df = pd.DataFrame({'id':['b21', 'b21', 'c56', 'b21', 'c56', 'c56'],
              'status':['created', 'delivered', 'created', 'done', 'delivered', 'done'],
              'date':['2023-01-13', '2023-01-15', '2023-01-15', '2023-01-18', '2023-01-19', '2023-01-20']})
df['date'] = pd.to_datetime(df['date'])

id
status
date

b21
created
2023-01-13

b21
delivered
2023-01-15

c56
created
2023-01-15

b21
done
2023-01-18

c56
delivered
2023-01-19

c56
done
2023-01-20

Необходимо добавить даты, которых нет в датафрейме и заполнить их предыдущими значениями. При этом заполнить так, чтобы для каждого id даты не выходили за рамки даты старта (status = 'created') и даты окончания (status = 'done')
В итоге должен получиться такой датафрейм:

id
status
date

b21
created
2023-01-13

b21
created
2023-01-14

b21
delivered
2023-01-15

c56
created
2023-01-15

b21
delivered
2023-01-16

c56
created
2023-01-16

b21
delivered
2023-01-17

c56
created
2023-01-17

b21
done
2023-01-18

c56
created
2023-01-18

c56
delivered
2023-01-19

c56
done
2023-01-20

Похожий вопрос уже существует, однако решение, которое там предлагают, не работает из - за пересечения дат в разных группах. Это приводит к ошибке
ValueError: cannot reindex on an axis with duplicate labels
P.S. Нашёл способ сделать это через цикл:

result = pd.DataFrame()
for i in df['id'].unique():
    new_df = df[df['id'] == i]
    d_range = pd.date_range(new_df['date'].min(), new_df['date'].max(), freq='D').to_frame(name='date')
    new_df = new_df.merge(d_range, how='right', on='date').fillna(method = 'ffill')
    result = pd.concat([result, new_df]).sort_values(['date', 'id'])
result

Однако реальный датасет будет довольно объёмным, поэтому хотелось бы найти способ увеличить производительность методами pandas

Можно использовать
groupby()

result = df.groupby('id', group_keys=False).apply(
    lambda x: x.merge(pd.date_range(x['date'].min(), x['date'].max(), freq='D').to_series(name='date'), how='right',
                      on='date').fillna(method='ffill')).sort_values('date')

    id     status       date
0  b21    created 2023-01-13
1  b21    created 2023-01-14
2  b21  delivered 2023-01-15
0  c56    created 2023-01-15
3  b21  delivered 2023-01-16
1  c56    created 2023-01-16
4  b21  delivered 2023-01-17
2  c56    created 2023-01-17
5  b21       done 2023-01-18
3  c56    created 2023-01-18
4  c56  delivered 2023-01-19
5  c56       done 2023-01-20


Убрать обратную связь related_name
Мне нужно убрать не нужную связь
related_name для оптимизации, как это можно сделать?

Вам необходимо присвоить
related_name='+', когда создаёте связи типа
ForeignKey или
ManyToManyField


где ошибка в бинарном поиске?

def binary_search(array, item):
    low = 0
    high = len(array) - 1
    while low < high:
        mid = (low + high)//2
        solve = array[mid]
        if solve == item:
            return mid
        if solve > item:
            high = solve - 1
        else:
            low = solve + 1
    return None

haha = [2,3,4,5,12,20,32]
print(binary_search(haha, 12))

Все должно работать правильно, у меня отсортированный массив, число 3,4,5 из массива алгоритм находит, но почему при поиске 12,20,32 пишет что таких чисел в массиве нет. Так же первое число массива, если я ставлю
low<=high, выписывает ошибку что array[mid] выходит за рамки.
Функция простая, при входе даешь массив и число, которое найти надо, при выходе получаешь позицию этого числа в массиве

Нужно поменять переменную с
solve на
mid при вычислении
low и
high, а также заменить
< на
<= в
while

def binary_search(array, item):
    low = 0
    high = len(array) - 1
    while low <= high:
        mid = (low + high) // 2
        solve = array[mid]
        if solve == item:
            return mid
        if solve > item:
            high = mid - 1
        else:
            low = mid + 1
    return None

haha = [2, 3, 4, 5, 12, 20, 32]
print(binary_search(haha, 12)) # 4


Какие значения могут быть ключами словаря?
Документация гласит, что ключами могут быть только неизменяемые типы данных.
Почему в данном случае не возникает ошибка?
<code>
class Test:
    pass

t = Test()
print({t: 1})
</code>

Попробую ответить, т.к. вопрос интересный и сам не знал почему.
Коротко: причина в наличии магическом методе
__hash__
Если мы используем словарь как ключ:

t = dict()
d = {t: 1}

То получаем ошибку:

TypeError: unhashable type: 'dict'

Но, вообще-то, эту же ошибку получим, если попробуем получить хеш:

t = dict()
print(hash(t))

У не хешируемых типов, магический метод
__hash__ отсутствует:

t = dict()
print(t.__hash__)
# None

Вот так выглядит наличие этого метода:

print(Test.__hash__)
# <slot wrapper '__hash__' of 'object' objects>

t = Test()
print(t.__hash__)
# <method-wrapper '__hash__' of Test object at ...

Мы это легко проверим на нашем классе
Test:

class Test:
    __hash__ = None

t = Test()
d = {t: 1}

Знакомая ошибка:

TypeError: unhashable type: 'Test'

ℹ Выходит, что у классов, по-умолчанию, есть метод
__hash__, поэтому их можно использовать в ключах словаря и в других местах (типа множеств), реализованных через хеши

Кст, по-умолчанию, хеш высчитывается из
id объекта деленного на 16.
Тут будет одинаковый результат:

class Test:
    pass

t = Test()

print(hash(t))
print(hash(id(t) // 16))


python удаленное управление windows
Скажите можно ли через python управлять пк(windows) удаленно используя библиотеку socket, смысл такой на пк запущен сервер, клиент подключается и внутри системы выполняет какие-то команды, и так чтобы командная строка не открывалась просто и тихо(все в благих целях!)

Есть такая библиотека для работы с Windows pywinrm попробуйте ее трассировать на ваши требования


Запуск кода powershell в программе python в контейнере docker
На сервере linux имеется 3 контейнера docker (postgres, python app, python app), основанные на образах python:3.10.9-slim-buster, postgres:latest.
К ним необходимо добавить еще один контейнер, содержащий приложение python. Проблема в том, что это приложение использует команды powershell для получения информации из ActiveDirectory.
Функция для запуска команд powershell:

def execute(powershell_script):
    args = ['powershell.exe', powershell_script]
    p = subprocess.Popen(args, stdout=subprocess.PIPE)
    result = p.communicate()[0]
    return result

И в дальнейшем команда запускается:

command = f"$host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.Size(8192,500);" \
              f"get-aduser -filter * -properties PasswordNeverExpires " \
              f"| Where {{$_.passwordNeverExpires -eq 'true' -and $_.enabled -eq 'true'}} " \
              f"| Select-Object DistinguishedName, SamAccountName | Format-Table -AutoSize"
res = execute(command)

Это приложение мне нужно запустить в контейнере, но я не понимаю как это сделать.
Первый вариант - запустить контейнер на образе windows, но объем образа очень большой и я не уверен что можно запускать одновременно linux и windows контейнеры.
Второй вариант - запустить контейнер на том же образе python с установленным pwsh. Но на текущий момент мне не удается подключить модуль activedirectory:

The term 'get-aduser' is not recognized as a name of a cmdlet,
function, script file, or executable program

Как этот вопрос решается?

Из представленной информации я предполагаю что вам нужен инструмент который позволит общаться с AD доменом. Сейчас для этого вы используете команды powershell внутри linux контейнера, что является в корне неправильным подходом. Используя python вам стоит обратить внимание на различные библиотеки для взаимодействия с AD доменом. Например, в коде вы используете команду
get-aduser, и я нашёл на просторах интернета такое решение которое использует библиотеку
python-ldap.

user_filter = '(sAMAccountName={})'.format(search_username)
base_dn = 'DC={},DC=com'.format(domain)
result = connection.search_s(base_dn, ldap.SCOPE_SUBTREE, user_filter)
print result

P.s - судя по виду кода используется python2.
В любом случае я думаю что вам придётся самостоятельно декомпозировать задачу и искать ответы на многие вопросы, пока что вопрос слишком общий.


Как именованный кортеж добавить в словарь?
В функцию передают список именнованных кортежей с котиками. Функция должна возвращать список словарей с "ключами" именованного кортежа. У меня в итоге добавляется только последний котик. И можно ли как-нибудь напрямую взять "ключи" кортежа и сделать из них ключи словаря чтобы не прописывать вручную строчку для каждого ключа?
<code>
import collections

Cat = collections.namedtuple("Cat", ["nickname", "age", "owner"])

def convert_list(cats):
    to_dict = {}
    list_of_dict_cats = []
    if isinstance(cats[0], tuple):
        for cat in cats:
            to_dict['nickname'] = cat.nickname
            to_dict['age'] = cat.age
            to_dict['owner'] = cat.owner
            list_of_dict_cats.append(to_dict)
    print(list_of_dict_cats)

convert_list([Cat("Mick", 5, "Sara"), Cat("Barsik", 7, "Olga"), Cat("Simon", 3, "Yura")])
</code>

Нужно перенести создание словаря
to_dict внутрь цикла. Из-за того что вы создаете словарь до цикла, в список каждый раз добавляется один и тот же словарь. Все элементы списка у вас - это один и тот же словарь, и изменения в словаре отображаются во всех элементах списка.
Проверку
isinstance(cats[0], tuple), если она действительно нужна, лучше внести в цикл, т.к. то что первый элемент списка -
tuple, не гарантирует, что другие элементы - тоже
tuple. К тому же, при типа значения первого элемента у вас отсутствует проверка, что список не пустой, но если внести проверку в цикл, то дополнительная проверка будет не нужна.
И то что объект -
tuple не гарантирует, что у объекта будут поля
nickname,
age,
owner, поэтому лучше явно проверять, что объект относится к классу
Cat

for cat in cats:
    if isinstance(cat, Cat):
        to_dict = {}
        to_dict['nickname'] = cat.nickname
        to_dict['age'] = cat.age
        to_dict['owner'] = cat.owner
        list_of_dict_cats.append(to_dict)

Также, для преобразования
namedtuple в словарь можно использовать метод
_asdict:

for cat in cats:
    if isinstance(cat, Cat):
        list_of_dict_cats.append(cat._asdict())

Ну и по условию вам нужно создать функцию, которая должна возвращать список словарей, а вы его печатаете, вместо этого нужно делать
return list_of_dict_cats, а результат функции уже печатать:

import collections

Cat = collections.namedtuple("Cat", ["nickname", "age", "owner"])

def convert_list(cats):
    list_of_dict_cats = []

    for cat in cats:
        if isinstance(cat, Cat):
            list_of_dict_cats.append(cat._asdict())

    return list_of_dict_cats

print(convert_list([Cat("Mick", 5, "Sara"), Cat("Barsik", 7, "Olga"), Cat("Simon", 3, "Yura")]))


Выбор в выборе select menu discord py
Я хочу, чтобы после выбора первого варианта у меня был выбор между двумя другими вариантами, например вопрос в вопросе. Можно ли это сделать? Вот мой код:
<code>
import discord
from discord.ext import commands

class Dropdown(discord.ui.Select):
    def __init__(self):
        options = [
            discord.SelectOption(label='Акрополь', description='Будет отправлен баннер "Акрополь"', emoji='🏛'),
            discord.SelectOption(label='Год Кролика', description='Будет отправлен баннер "Год Кролика"', emoji='🐇'),
            discord.SelectOption(label='Зевс', description='Будет отправлен баннер "Зевс"', emoji='⚡'),
        ]

        super().__init__(placeholder='Выберете ваш любимый цвет...', min_values=1, max_values=1, options=options)

    async def callback(self, interaction: discord.Interaction):
        if self.values[0] == 'Акрополь':
            await interaction.response.send_message('Баннер "Акрополь"',file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Akropol.png'))
        elif self.values[0] == 'Год Кролика':
            await interaction.response.send_message('Баннер "Год Кролика"',file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Kroll.png'))
        elif self.values[0] == 'Зевс':
            await interaction.response.send_message('Баннер "Зевс"', file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Zevs.png'))

class DropdownView(discord.ui.View):
    def __init__(self):
        super().__init__()
        self.add_item(Dropdown())

class Bot(commands.Bot):
    def __init__(self):
        intents = discord.Intents.default()
        intents.message_content = True

        super().__init__(command_prefix=commands.when_mentioned_or('$'), intents=intents)

    async def on_ready(self):
        print(f'Logged in as {self.user} (ID: {self.user.id})')
        print('------')

intents = discord.Intents.all()
bot = commands.Bot(command_prefix='+', intents=intents)

@bot.command()
async def banner(ctx):
    """Отправляет сообщение с выбранным баннером"""

    view = DropdownView()

    await ctx.send('Выберете нужный баннер:', view=view)

@bot.command()
async def Молодец(ctx):
    await ctx.send(f"{ctx.author.mention} молодец")

bot.run('bottoken')
</code>

Я думаю это можно сделать путем изменения сообщения на которое отреагировали:

await interaction.message.edit(view=DropdownView2())

Далее всё так же..

class DropdownView2(discord.ui.View):
    def __init__(self):
        super().__init__()
        self.add_item(Dropdown2())

И снова создаем нужные варианты:

class Dropdown2(discord.ui.Select):
    def __init__(self):
        options = [
            #варианты
        ]

        super().__init__(placeholder='Выберите один из следующих вариантов..', min_values=1, max_values=1, options=options)

    async def callback(self, interaction: discord.Interaction):
        #варианты


Как поместить message.text в caption для фото в aiogram API python?
Как поместить message.text в caption для фото в aiogram API python? Делаю тг бота для своих нужд, хочу чтобы при рассылке я могу просто отправить фото с текстом как в обычном лс чате и ровно так же отправилось всем пользователям. Но вот незадача aiogram обрабатывает только по одному типу сообщений и я не знаю как message.text впихнуть в caption для send_photo. Помогите люди добрые

@dp.message_handler(content_types=['photo'])
async def handle_docs_photo(message: types.Message):
    await bot.send_photo(message.chat.id, photo=message.photo[0].file_id, caption=message.caption)

Так же на сколько я вас понял вы бы хотели отправить это всем пользователям, что означает что у вас есть какой то список всех телеграм id пройдясь по которому вы можете отправить "всем" фото с нужным для вас описанием. Это можно сделать примерно так:

idList = []  # массив с telegram id юзеров
for ID in idList:
    await bot.send_photo(ID, photo=message.photo[0].file_id, caption=message.caption)


Не отвечает на сообщения в тг
Бот добавляет кнопки,но не отвечает при нажатии на них
<code>
import telebot
import config
from telebot import types

bot = telebot.TeleBot(config.TOKEN)

@bot.message_handler(commands=['start'])
def start(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
    button1 = types.KeyboardButton("Дароу")
    button2 = types.KeyboardButton("Зачем ты существуешь?")
    markup.add(button1,button2)
    bot.send_message(message.chat.id, "Привет, {0.first_name}!.".format(message.from_user), reply_markup=markup)
@bot.message_handler(content_types=['text'])
def message(message):
    if message.chat.type == 'privat':
        if message.text == button1:
            bot.send_message(message.chat.id,"Салам брооууу")
        elif message.text == button2:
            bot.send_message(message.chat.id,"Что бы быть брооууу")

print('Started')

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

Нужно сравнивать сообщение с текстом, который находится на кнопке:

if message.text == "Дароу":
    bot.send_message(message.chat.id,"Салам брооууу")
elif message.text == "Зачем ты существуешь?":
    bot.send_message(message.chat.id,"Что бы быть брооууу")

Еще надо заменить
if message.chat.type == 'privat': на
if message.chat.type == 'private':, так как
'private' - корректное написание типа чата.
Возможно, проблема еще в том, что вы не указали обработчик события для кнопок. Для этого нужно использовать декоратор
@bot.callback_query_handler(func=lambda call: True).

@bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
    if call.message:
        if call.data == "button1":
            bot.send_message(call.message.chat.id,"Салам брооууу")
        elif call.data == "button2":
            bot.send_message(call.message.chat.id,"Что бы быть брооууу")

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

button1 = types.KeyboardButton("Дароу", callback_data='button1')
button2 = types.KeyboardButton("Зачем ты существуешь?", callback_data='button2')


Python метод replace и f-string
Есть f-строка с текстом, который мне нужно изменить. Изменить не только значение переменной, но и сохранить изменения в файл, чтоб при перезапуске программы строка не возвращалась к своему изначальному значению.
Вот так всё работает правильно:

text = "Simple text."

def text_change(new_text):
    global text
    old = text
    new = new_text

    text = text.replace(old, new)  # меняю значение переменной

    with open("main.py", "r") as file:  # открываю файл
        old_data = file.read()

    new_data = old_data.replace(old, new)  # нахожу в нём нужную мне строку и изменяю её

    with open("main.py", "w") as file:  # сохраняю изменения в файле
        file.write(new_data)

    file.close()  # закрываю поток

text_change(new_text="New simple text.")  # запускаю функцию

Функция корректно работает, изменяется значение переменной, файл перезаписывается, при перезапуске программы изменения сохраняются.
Но если изменить переменную text на:

f_text = "f-string"
text = f"Simple text with using\n" \
       f"{f_text}"

Текст в переменной меняется, но изменения не записываются в файл. При перезапуске программы, переменная text возвращается к своему стандартному значению.
Как правильно адаптировать мою функцию под изменение f-строк?

Функция
text_change ищет и заменяет строку
old в файле
main.py, но когда вы используете f-строку, строка old не совпадает с текстом в файле, поскольку она может иметь разный формат. Чтобы адаптировать ф-ю для f-строк, вы можете задать строку old как конкретную f-строку, которую вы хотите изменить :

old = f"Simple text with using\n{f_text}"

Если вам нужно заменить множество f-строк в файле, стоит смотреть в сторону регулярных выражений.

import re

def text_change(new_text):
    global text
    old = f"Simple text with using\n{f_text}"
    new = new_text

    text = re.sub(old, new, text)

    with open("main.py", "r") as file:
        old_data = file.read()

    new_data = re.sub(old, new, old_data)

    with open("main.py", "w") as file:
        file.write(new_data)

    file.close()

text_change(new_text="New simple text.")

или так:

    import ast

    def text_change(new_text):
        global text
        old = f"Simple text with using\n{f_text}"
        new = new_text

        text = ast.literal_eval(f"f'{old}'").replace(f_text, new_text)
 with open("main.py", "r") as file:
        old_data = file.read()

    new_data = old_data.replace(old, text)

    with open("main.py", "w") as file:
        file.write(new_data)

    file.close()

text_change(new_text="New simple text.")


Python tkinter gui. При вызове нескольких изображений показывает только последнее
Пытаюсь создать симулятор игральных костей с имитацией броска. Программа в целом работает, за исключением того, что из двух запланированных кубиков отображается только последний, указанный в коде. Т.е. функция roll, в которой указаны команды на создание двух изображений кубиков, выводит на экран только последнее.
<code>
from tkinter import *
import random, time

def sides():
    global side
    d1 = PhotoImage(file=('d1.png'))
    d2 = PhotoImage(file=('d2.png'))
    d3 = PhotoImage(file=('d3.png'))
    d4 = PhotoImage(file=('d4.png'))
    d5 = PhotoImage(file=('d5.png'))
    d6 = PhotoImage(file=('d6.png'))
    side = random.choice([d1,d2,d3,d4,d5,d6])
    return side

def button():
    throw.config(state='active')

def roll():
    global dice_l, dice_r
    throw.config(state='disabled')
    for i in range(15):
        dice_l = canvas.create_image(270,250,image=sides())
        dice_r = canvas.create_image(530,250,image=sides())
        window.update()
        time.sleep(0.1)
    button()

window = Tk()
window.title('Dice')
window.resizable(height=False, width=False)
window.iconphoto(True, PhotoImage(file=('ikonka.png')))

canvas = Canvas(window, width=800, height=500)
canvas.pack()

bgrd = PhotoImage(file=('stol2.png'))

canvas.create_image(400,250,image=bgrd)

throw = Button(window, text='ROLL', command=roll)
throw.place(relx=0.5, rely=0.9, anchor=S)

roll()

window.mainloop()
</code>
Изначально пробовал делать через Label с указанием места размещения меток с привязкой к ним кубиков в теле программы, ссылаясь на них в функции roll. Но прозрачность пнг-изображений в таком случае выключалась, и вокруг кубиков появлялся серый фон, потому и перешёл на canvas.
Так-то я только начал питон изучать, и где-то на начальном уровне сейчас, и потому возможно не вижу очевидного. Есть ли какое-то решение данной проблемы?

Чтобы сборщик мусора не удалял изображения, объекты
PhotoImage нужно после создания куда-то сохранять (если одно - просто в глобальную переменную, если их много - то например в список). См. вопрос: Не отображается изображение в Label.
Чтобы новые изображения не создавались каждый раз при вызове
roll, нужно изображения один раз загрузить при старте программы, потом только выбирать одно из них из списка:

sides_images = []

def load_images():
    for name in ('d1.png', 'd2.png', 'd3.png', 'd4.png', 'd5.png', 'd6.png'):
        sides_images.append(PhotoImage(file=name))

# Загружаем изображения при старте
load_images()

def sides():
    # Не грузим изображения заново,
    # просто выбираем случайное изображение из ранее загруженных
    side = random.choice(sides_images)
    return side


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

async def get_from_table1():
    return pd.read_sql_query('SELECT * FROM [table1]', conn)

// conn - подключение к бд через sqlalchemy
Далее вызываю список функций следующим образом без ошибок и точно асинхронно(проверил по time):

async def main():
    await asyncio.gather(
        asyncio.create_task(view_to_pd.get_from_db_table1()),
        asyncio.create_task(view_to_pd.get_from_db_table2()),
        asyncio.create_task(view_to_pd.get_from_db_table3()),
        asyncio.create_task(view_to_pd.get_from_db_table4()),
        asyncio.create_task(view_to_pd.get_from_db_table5()),
        asyncio.create_task(view_to_pd.get_from_db_table6())
    )

asyncio.run(main())

Однако я не знаю как мне получить данных которые я возращаю. Как можно это сделать? Я новичок в асинхронном программировании. Извините за глупый вопрос.

В общем, благодаря пользователям andreymal и insolor +- разобрался в данном вопросе. Здесь воспользовался библиотекой aioodbc (бд у меня была mssql)
Первым делом я изменил функцию main:

async def main():
    res = await asyncio.gather(
        asyncio.create_task(view_to_pd.get_from_db_table1()),
        asyncio.create_task(view_to_pd.get_from_db_table2()),
        asyncio.create_task(view_to_pd.get_from_db_table3()),
        asyncio.create_task(view_to_pd.get_from_db_table4()),
        asyncio.create_task(view_to_pd.get_from_db_table5()),
        asyncio.create_task(view_to_pd.get_from_db_table6())
    )
return res

Однако теперь мне нужно преобразовать функции get_from_db_table в асинхронные. Т.к. у меня есть библиотека aioodbc, то я буду получать данные списком кортежей, а мне нужно вернуть DataFrame. Мне нужно было написать строчку:

await pd.DataFrame(rows, columns=columns)

Но она вызывает ошибку. Прошерстив немного интернет, я понял, что нет библиотеки для pandas, следовательно придется использовать костыльную функцию:

async def to_df(content, columns):
    return pd.DataFrame(np.array(content), columns=columns)

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

async def get_from_db_table1():
    loop = asyncio.get_event_loop()
    conn = await aioodbc.connect(dsn=conn_str, loop=loop)
    crs = await conn.cursor()
    await crs.execute("SELECT * FROM [table1]")
    rows = await crs.fetchall()
    await conn.close()
    res = await asyncio.gather(to_df(rows, columns=columns_table1]))
    return res[0]

Итого: на получение данных из 8-ми таблиц синхронным способом у меня ушло 15 секунд, а асинхронным 7 секунд!


Как реализовать правильно функцию чтения и разделения?
Всем привет. Что то совсем запутался с реализацией кода

import io

def separator(argument):
    return '.\n'.join(argument.split('. '))

with io.open(r'C:\dset\test.txt', 'r', encoding='utf-8') as file:
    for num, line in enumerate(file, 1):
        print(separator('НОМЕР ПРЕДЛОЖЕНИЯ - ' + str(num) + ' - ' + line.strip()))

Данный код показыват это

НОМЕР ПРЕДЛОЖЕНИЯ - 1 - Мы ехали в музей.
Они пили малако.
Есть один пример.
 лаг был еще целый.

А мне нужно что бы прописалось и про нумеровалось каждое предложение вот так:

НОМЕР ПРЕДЛОЖЕНИЯ - 1 - Мы ехали в музей.
НОМЕР ПРЕДЛОЖЕНИЯ - 2 - Они пили малако.
НОМЕР ПРЕДЛОЖЕНИЯ - 3 - Есть один пример.
НОМЕР ПРЕДЛОЖЕНИЯ - 4 -  лаг был еще целый.

file = 'Мы ехали в музей. Они пили малако. Есть один пример. лаг был еще целый.'
print(*(f'НОМЕР ПРЕДЛОЖЕНИЯ - {num} - {line.strip()}.'
        for num, line in enumerate(file.split('.'), 1) if line),
      sep='\n')

НОМЕР ПРЕДЛОЖЕНИЯ - 1 - Мы ехали в музей.
НОМЕР ПРЕДЛОЖЕНИЯ - 2 - Они пили малако.
НОМЕР ПРЕДЛОЖЕНИЯ - 3 - Есть один пример.
НОМЕР ПРЕДЛОЖЕНИЯ - 4 - лаг был еще целый.


Как реализовать unixtime без datetime?
На курсах дали задание реализовать unixtime. Вот как я реализовала
<code>
from datetime import datetime
timestamp = int(input('Enter the number of seconds: '))
dt = datetime.fromtimestamp( timestamp )
print( dt )
</code>
Но ментор вернул мне задание, потому что ему нужно без использования данной библиотеки. Вопрос как это реализовать без библиотеки..? Может кто-либо с этим помочь...?

Если нельзя использовать библиотеку datetime то можно попробовать использовать модуль time:
<code>
import time

timestamp = int(input('Enter the number of seconds: '))
time_struct = time.gmtime(timestamp) # Преобразуем unixtime в UTC time объект
print(time.strftime("%Y-%m-%d %H:%M:%S", time_struct)) # Выводим в формате ГГГГ-ММ-ДД ЧЧ:ММ:СС
</code>


Process finished with exit code 0 в коде работы телеграмм бота

Process finished with exit code процесс сам по себе завершается, не могу понять в чём причина

import openai
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor

token = 'token'
openai.api_key = 'token'

bot = Bot(token)
dp = Dispatcher(bot)

@dp.message_handler()
async def send(message : types.Message):
    response = openai.completion.create(
        model="text-davinci-003",
        promt=message.text,
        temperature=0.5,
        max_tokens=1000,
        top_p=1.0,
        frequency_penalty=0.5,
        presence_penalty=0.0,
    )

    await message.answer(response['choices'][0]['text'])

    executor.start_polling(dp, skip_updates=True)

Нужно вынести
executor.start_polling(dp, skip_updates=True) из функции:

...
@dp.message_handler()
async def send(message : types.Message):
    ...
    await message.answer(response['choices'][0]['text'])

executor.start_polling(dp, skip_updates=True)

Теперь бот должен запуститься и процесс не завершится, пока бот работает


"TypeError: 'module' object is not callable"
не судите строго, только начал учить python ошибка: "dp = dispatcher(bot)
TypeError: 'module' object is not callable" в коде
<code>
import openai
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor

token = "token"
openai.api_key = "token"

bot = Bot(token)
dp = Dispatcher(bot)

@dp.message_handler()
async def send(message : types.Message):
    response = openai.completion.create(
        model="text-davinci-003",
        promt=message.text,
        temperature=0.5,
        max_tokens=1000,
        top_p=1.0,
        frequency_penalty=0.5,
        presence_penalty=0.0,
    )

    await message.answer(response['choices'][0]['text'])

executor.start_polling(dp, skip_updates=True)
</code>

Но
dispatcher - это действительно модуль, как и написано в ошибке. Вероятно, вы хотели создать объект
Dispatcher:

from aiogram.dispatcher import Dispatcher
                               ^^^^^^^^^^ с большой буквы!!
    ...
    bot = Bot(token)
    dp = Dispatcher(bot)
         ^^^^^^^^^^ с большой буквы!!


Как сравнить значения словаря в dict comprehension
Написал функцию которая принимает словарь months с месяцами и средней температурой и число temperature. Эта функция должна вернуть словарь с месяцами, средняя температура которых больше temperature. Использовать нужно только dict comprehension.
Помогите понять как можно сравнить значение полученного словаря с температурой.
Написал код:

def average_temperature(months: dict, temperature: int) -> dict:
    return {x: temperature for x in months if months.values() > temperature}

Не проходит сравнение months.values() > temperature так как months.values() это dict_values(), а как достать оттуда значения не могу додуматься, пробовал запаковывать в list и сравнивать но тоже не вариант, пробовал интовать тоже не вариант, понимаю что скорей всего нужен дополнительный цикл что бы пробежаться по значениям months.values() но как его написать и где не могу додуматься??
Возвращать функция как пример должна вот такие словари:

months = {'Dec': -4.9, 'Jan': -2.2, 'Feb': 2.1}
temperature = 5
average_temperature(months, temperature) == {}
Нет месяцев со средней температурой больше 5

months = {'Jun': 18, 'Jul': 23.8, 'Aug': 22.9}
temperature = 20
average_temperature(months, temperature) == {'Jul': 23.8, 'Aug': 22.9}
Два месяца со средней температурой больше 20

Попробуйте так
<code>
def average_temperature(months: dict, temperature: int) -> dict:
    return {x: temp for x, temp in months.items() if temp > temperature}
</code>


Зачем в Python нужен self если можно создать простую функцию и передать ей переменную
Вот здесь на сайте объясняется суть
self: Для чего в python нужен self?
Вопрос: зачем зачем создавать эти страшные конструкции типа
__init__ и
self если указанная ниже функция выдаст тоже самое?

def Dog(name):
   return f'Имя моей собаки {name}'

nick_name = Dog('Rex')
print(nick_name)

А что вы будете делать, когда от
Dog вам нужно будет не одно свойство получить, а два, десять, сто свойств? Будете писать сто отдельных функций? Будете писать одну мега-функцию с параметром, в котором будете передавать, какое свойство вы хотите получить или изменить?
А если вы захотите от
Dog каких-то действий, зависящих от его внутреннего состояния? Например, у него есть уровень сытости и вы хотите, чтобы он по-разному гавкал в зависимости от этого уровня?
А если вы захотите иметь несколько разных
Dog с разным состоянием - вы будете это состояние хранить где-то снаружи и передавать в ваши функции каждый раз вручную?

Просто нужно чуть продолжить мысль о том, что вам может понадобиться от класса и как этим всем было бы удобно пользоваться - и тогда необходимость инкапсуляции, т.е. включения/скрытия полей (переменных) и методов (функций) внутри класса и его объектов, придёт к вам сама собой.
Собственно,
self как-раз и представляет собой собой ссылку на объект класса, на его состояние.
А конструктор
__init__ нужен, чтобы в удобной форме задать первоначальное состояние экземпляра объекта. Например, имя для собаки. Вряд ли это имя поменяется в течении жизни объекта "собака", так что очень удобно задать это имя сразу при создании объекта. Так исторически и возникла необходимость в конструкторе класса.
И так со всеми штуками, относящимися к классам. Если начать разбираться, то все они нужны как-раз для удобства программиста.


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

def start_shell():
    host = '127.0.0.1'
    port = 8888
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((host, port))
    server.listen()
    while True:
        user, adress = server.accept()
        while True:
            data = user.recv(4096)
            if not data:
                continue
            print(data.decode('utf-8'))

if __name__ == '__main__':
    try:
        import socket
    except:
        exit()

    start_shell()

И код клиента

import socket
host = '127.0.0.1'
port = 8888

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))

while True:
    result = input('>>> ')
    if result == 'exit' or result == 'close':
        break
    client.send(result.encode('utf-8'))

Отладил сервер. Причина в зацикливании, когда данных нет.
Вам нужно прерывать цикл через
break:

...
    while True:
        user, adress = server.accept()
        while True:
            data = user.recv(4096)
            if not data:
                break
            print(data.decode('utf-8'))


async def использование if-else
Хочу выдавать разную keyboard buttom для разных статусов юзеров. При добавлении if/else клавиатура в целом перестает отображаться, так же пытался сделать ветвление в клавиатуре, пробовал изменить SQL запрос. Скорее всего, вопрос простой, но сижу долго не могу понять в чем проблема:

@dp.message_handler(commands=['start'])
async def start(message: types.Message):
    name = message.chat.first_name
    users = db.status(message)
    await db.add_new_sub(message)
    for user in users:
        if not user:
            await message.answer(f'Привет, {name}!',
                                 reply_markup=get_start_kb())

        else:
            await message.answer(f'Привет, {name}!',
                                 reply_markup=get_start_approve_kb())

функция status:

def status(message):
stat = cur.execute("SELECT * FROM users WHERE user_id=? AND status='Current_group_member'", (message.chat.id,))
return stat

Клавиатуры:

def get_start_kb() -> ReplyKeyboardMarkup:
kb = ReplyKeyboardMarkup(keyboard=[
    [KeyboardButton('О группе')],
    [KeyboardButton('Техническая поддержка')],
    [KeyboardButton('Купить подписку')],
],
    resize_keyboard=True,
    input_field_placeholder='Бот распознаёт только нажатие кнопок')
return kb

def get_start_approve_kb() -> ReplyKeyboardMarkup:
    kb = ReplyKeyboardMarkup(keyboard=[
        [KeyboardButton('О группе')],
        [KeyboardButton('Техническая поддержка')],
        [KeyboardButton('Состояние подписки')],
    ],
        resize_keyboard=True,
        input_field_placeholder='Бот распознаёт только нажатие кнопок')
    return kb

Не обязательно создавать новую клавиатуру под каждый статус пользователя, достаточно создать одну которая будет отображаться по разному зависимости от статуса.
Вот пример кода клавиатуры с использованием aiogram v3.0.0b6

def menu_keyboard(user):
    level = 0
    builder = InlineKeyboardBuilder()
    builder.add(
        InlineKeyboardButton(text='🎾 Начать раздачу',
                             callback_data=MenuCd(
                                 level=level,
                                 callback='start_giveaway').pack()
                             ),
        InlineKeyboardButton(text='💰 Баланс',
                             callback_data='balance'
                             ),
        InlineKeyboardButton(text='🎯 Активные раздачи',
                             callback_data=MenuCd(
                                 level=level,
                                 callback='active_giveaway').pack()
                             )
    )
    builder.adjust(2)
    if not user.subscription:
        builder.row(
            InlineKeyboardButton(text='💵 Купить подписку',
                                 callback_data=MenuCd(
                                     level=level,
                                     callback='buy_subscription'
                                 ).pack()
                                 )
        )
    else:
        builder.row(
            InlineKeyboardButton(text='💵 Продлить подписку',
                                 callback_data=MenuCd(
                                     level=level,
                                     callback='buy_subscription'
                                 ).pack()
                                 )
        )

    if user.status == 'admin':
        builder.row(
            InlineKeyboardButton(text='⚙ Админка',
                                 callback_data='admin_menu')
        )

    return builder.as_markup()

Пример использования:

async def start(message: types.Message | types.CallbackQuery,
                db_requests: DbRequests):
    user = await db_requests.get_user(user_id=message.from_user.id)
    config_db = await db_requests.get_config()
    buttons = await db_requests.get_advert_buttons()

    if not user:
        user = await db_requests.add_user(
            user_id=message.from_user.id,
            full_name=message.from_user.full_name,
            username=message.from_user.username,
        )
        logging.info(f'Added user {message.from_user.full_name}')

    if user.full_name != message.from_user.full_name \
            or user.username != message.from_user.username:
        user = await db_requests.update_user(
            user_id=message.from_user.id,
            update_fields={
                "full_name": message.from_user.full_name,
                "username": message.from_user.username,
            }
        )

    markup = menu_keyboard(user)

    if isinstance(message, types.Message):
        await message.answer('💎', reply_markup=advert_keyboard(buttons))
        await message.answer_photo(config_db.image_url,
                                   '\n'.join(start_message(user, message)),
                                   reply_markup=markup
                                   )

    elif isinstance(message, types.CallbackQuery):
        call = message
        await call.message.edit_reply_markup(markup)

    else:
        pass


Не ищется элемент с помощью text(), если название содержит кавычки xpath selenium python
Ищу элемент в браузере с помощью xpath запроса

//*[@class = 'CustomFieldValueGroupedList__value']//*[text()='Экран "Рассчитанные цены"']

Ввожу этот запрос в среду разработки

driver.find_element('xpath', "//*[@class = 'CustomFieldValueGroupedList__value']//*[text()='Экран "Рассчитанные цены"']")

Из-за того, что в названии присутствуют кавычки, этот запрос горит с ошибкой.
Как правильно заменить кавычки в данном случае, чтобы запрос отработал?

Вам нужно применить обратные кавычки (`) вместо обычных кавычек ("), чтобы экранировать текст внутри кавычек:

driver.find_element('xpath', '//*[@class = "CustomFieldValueGroupedList__value"]//*[text()="Экран `Рассчитанные цены`"]')

Либо можно использовать символ слеша
() перед кавычками внутри текста

driver.find_element('xpath', "//*[@class = 'CustomFieldValueGroupedList__value']//*[text()='Экран \"Рассчитанные цены\"']")

Есть еще такие варианты:
Использование апостроф
(') вместо кавычек в тексте:

driver.find_element('xpath', "//*[@class = 'CustomFieldValueGroupedList__value']//*[text()='Экран 'Рассчитанные цены'']")

сохранение текста в переменной:

search_text = "Экран 'Рассчитанные цены'"
driver.find_element('xpath', f"//*[@class = 'CustomFieldValueGroupedList__value']//*[text()='{search_text}']")

метод
translate для замены:

search_text = "Экран \"Рассчитанные цены\""
search_text = search_text.translate(str.maketrans({'"':'\''}))
driver.find_element('xpath', f"//*[@class = 'CustomFieldValueGroupedList__value']//*[text()='{search_text}']")


Нужно из списка вытащить части элементов
Есть примерно такой список

lst = [Таблица 1. Население,
учтенное при Всероссийской переписи населения 2020 года,
Таблица 2. Изменение численности
населения России,
Таблица 3. Число муниципальных образований, внутригородских районов, округов города, межселенных территорий и населенных пунктов,
по субъектам Российской Федерации]

Из него нужно вытащить все ссылка на файлы .xlsx, то есть подобные: /storage/mediabank/tab-1_VPN-2020.xlsx. После чего все эти ссылки добавить в другой список.

Например, с помощью регулярного выражения:

import re

lst = ['<a href="/storage/mediabank/tab-1_VPN-2020.xlsx">Таблица 1. Население, учтенное при Всероссийской переписи населения 2020 года</a>',
       '<a href="/storage/mediabank/tab-2_VPN-2020.xlsx">Таблица 2. Изменение численности населения России</a>',
       '<a href="/storage/mediabank/tab-3_VPN-2020.xlsx">Таблица 3. Число муниципальных образований, внутригородских районов, округов города, межселенных территорий и населенных пунктов</a>',
       '<a href="/storage/mediabank/tab-3_VPN-2020.xlsx">по субъектам Российской Федерации</a>']

rx = re.compile('href="([^"]+)"')
result = [rx.findall(line)[0] for line in lst]
print(result)

Вывод:

['/storage/mediabank/tab-1_VPN-2020.xlsx',
 '/storage/mediabank/tab-2_VPN-2020.xlsx',
 '/storage/mediabank/tab-3_VPN-2020.xlsx',
 '/storage/mediabank/tab-3_VPN-2020.xlsx']

А так то ваш список некорректный, я его привёл к нормальному питоновскому виду.


Как перевести строку со временем в секунды?
Есть строка с датой и временем в формате:

date = "23-01-25 08:48:35"

Нужно получить строку с той же датой, но в секундах (от 1970). Как это сделать правильно? Пробовал так:

import datetime
date = "23-01-25 08:48:35"
datetime.strptime(date, "%S")

Но это выдает ошибку

ValueError: unconverted data remains: 23-01-25 08:48:35

Если от 1970  года:

import datetime
date = "23-01-25 08:48:35"
print(datetime.datetime.strptime(date, '%Y-%m-%d %H:%M:%S').timestamp())

Вывод:

1674622115.0


Какие алгоритмы и паттерны должен знать каждый junior Python разработчик? [закрыт]

Закрыт. На этот вопрос невозможно дать объективный ответ. Ответы на него в данный момент не принимаются.

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах.

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

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

посоветуйте какие алгоритмы и паттерны должен знать каждый Junior Python разработчик? Я только сортировку пузырьком знаю, ну и рекурсию, если это алгоритм, а среди паттернов проектирования понятие не имею , что приоритетно

Не существует какого-то списка алгоритмов и паттернов, обязательных для того или иного профессионального уровня.
Работать программистом начального уровня вполне можно и без их знания. Хотя знать всё-таки лучше, чем не знать. Но в целом их изучение нужно больше для того, чтобы развивать "мышление программиста", а не для того, чтобы прямо использовать их в повседневной практике. (Я сейчас не говорю про какие-то очень специальные ниши, где алгоритмы всё-таки непосредственно используются).
Я бы порекомендовал на данном этапе сконцентрироваться не на алгоритмах и паттернах, а на том, чтобы наработать практику в написании хотя бы не очень больших, но уже настоящих программ, которые решают настоящие задачи - какие-нибудь телеграмм-боты, веб-парсеры и т.п.
Изучение паттернов гораздо проще происходит, когда у вас уже наработан опыт написания кода, который по размеру побольше, чем просто сортировка.


ошибка sqlite3.OperationalError: near "": syntax error
<code>
print(cursor.execute("SELECT like FROM users WHERE id {}".format(ctx.author.id)).fetchone()[0])
</code>
вот код на что получаю ошибку sqlite3.OperationalError: near "514814879845187587": syntax error
id получаю именно автора

Ошибка в том, что не указано сравнение в условии WHERE. Вместо "id {}" должно быть "id = {}" или "id IN {}" в зависимости от значения ctx.author.id.


Ошибка при добавлении нового ключа и значения в словарь
Создай функцию who_is_online, которая принимает список friends словарей и определяет кто из них online, offline или away. Если пользователь имеет статус online, но его не было в сети более 10 минут (lastActivity > 10), то можно считать, что практически его статус уже away.
Результат должен быть таким:
{ "online": ["Alice"], "offline": ["Lucy"], "away": ["Bob"]}
Если в чате нет активных юзеров то результат такой:{"offline": ["Lucy"], "away": ["Bob"]}
Если друзей вообще нет в чате то тогда тогда в функцию передается пустой список , и функция должна вернуть пустой список.
Написал функцию, но она выдает ошибку KeyError: 'away'
<code>
def who_is_online(friends: list) -> dict:
    new_dict = {}
    for dictinary in friends:
        current_status = dictinary["status"]
        if current_status == "online" and dictinary["lastActivity"] > 10:
            current_status = "away"
            if current_status not in new_dict:
                new_dict[current_status].append(friends["username"])
    return new_dict

friends = [{
  "username": "Alice",
  "status": "online",
  "lastActivity": 10
}, {
  "username": "Lucy",
  "status": "offline",
  "lastActivity": 22
}, {
  "username": "Bob",
  "status": "online",
  "lastActivity": 104
}]

print(who_is_online(friends))

</code>

from typing import Dict

friends = [
    {
        "username": "Alice",
        "status": "online",
        "lastActivity": 10
    }, {
        "username": "Lucy",
        "status": "offline",
        "lastActivity": 22
    }, {
        "username": "Bob",
        "status": "online",
        "lastActivity": 104
    }
]

def effective_status(data: dict):
    if data.get('status') == 'online' and data.get('lastActivity') > 10:
        data['status'] = 'away'
    return data

def who_is_online(user_list: list):
    users: Dict[str, list] = dict()
    for elem in map(effective_status, user_list):
        users[
            elem.get('status')
        ] = users.get(
        elem.get('status'), []
        ) + [
            elem.get('username')
        ]
    return users

print(
    who_is_online(
        friends
    )
)

{'online': ['Alice'], 'offline': ['Lucy'], 'away': ['Bob']}


Pandas сравнение с нулëм
Как а pandas dataFrame вычислить столбец, равный максимуму между значениями имеющегося столбца и нулём ? При коде
df['new']=max(df['num_col'],0) возникает ошибка Truth value of a Series is ambiguous. Как быть? )

Один из вариантов - создаем временный столбец из нулей и берем максимум по оси 1

df = pd.DataFrame({'numbers':np.random.randint(-10,10,10)})
df['max0'] = df.assign(zero=0).max(axis=1)
print(df)

Другой вариант c
where() - если в первом аргументе условие истинно (т.е. число больше 0), то остается это число, иначе заменяется на 0:

df['max0'] = df.numbers.where(df.numbers.gt(0), 0)

Еще вариант с
mask() - почти то же самое, что предыдущий вариант, только логика наоборот - меняются на 0 те элементы, где условие в первом аргументе истинное

df['max0'] = df.numbers.mask(df.numbers.lt(0), 0)

   numbers  max0
0        3     3
1       -2     0
2        0     0
3        4     4
4        8     8
5        9     9
6       -1     0
7      -10     0
8        5     5
9       -7     0


Есть приложение Django на VDS, которое работает, но при подключении .DLL возникает ошибка 'clr' has no attribute 'AddReference'
Не могу устранить ошибку:

module 'clr' has no attribute 'AddReference'

VDS Ubuntu22+Apache2 +Python3.10.9+ Django 4, 1, 5 +ip и доменное имя, все работает нормально, но мне нужно подключить dll (.net7.0)(
dotnet build --runtime ubuntu.22.04-x64 --self-contained)- если вы подключаетесь к VDS через клиент Openssh, то .dll подключится в среде python3, которая там есть, но при загрузке страницы возникает ошибка

module 'clr' has no attribute 'AddReference'

единственное отличие, которое я заметил, заключается в том, что сайт выдает
Python.version=3.10.6 (main, Nov 14 2022, 16:10:14) [ GCC 11.3.0], (
import sys; sys.version) , когда я нахожусь в клиенте Openssh, он пишет
3.10.9 (main, Jan 24 2023, 10:16:41) [GCC 11.3.0], может быть, это какая-то причина?
вот что я имею за Traceback загрузки сайта :

Traceback (most recent call last):
  File "/home/djangoexample4/env/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/djangoexample4/env/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/djangoexample4/mainapp/views.py", line 135, in index
    clr.AddReference('/home/djangoexample4/btclinux2/MyLibraryName/bin/Debug/net7.0/ubuntu.22.04-x64/MyLibraryName.dll')

Exception Type: AttributeError at /
Exception Value: module 'clr' has no attribute 'AddReference'

если через openSSH client подключатся к VDS, то ни какой ошибки уже почемуто нет:

# monop -r /home/djangoexample4/btclinux2/MyLibraryName/bin/Debug/net7.0/ubuntu.22.04-x64/MyLibraryName.dll

Assembly Information:
MyLibraryName
Version=1.0.0.0
Culture=neutral
PublicKeyToken=null
MyLibraryName.Class1
Total: 1 types.

исходный C# (класс проекта classlib , созданного на vds dotnet-ом, и потом dotnet build --runtime ubuntu.22.04-x64 --self-contained, чтобы появился наш dll):

namespace MyLibraryName
{
    public class Class1
    {
        public int method1()
        {
            return 777;
        }
    }
}

вот это при обращении через консоль на этом VDS:

# python3
>>> import clr
>>> clr.AddReference('/home/djangoexample4/btclinux2/MyLibraryName/bin/Debug/net7.0/ubuntu.22.04-x64/MyLibraryName.dll')
<System.Reflection.RuntimeAssembly object at 0x7f9c3b928640>
>>> from MyLibraryName import Class1
>>> variable = Class1().method1()
>>> print(variable)
777

вот это тоже делал:

pip uninstall clr
pip uninstall pythonnet
pip install pythonnet

функция
dir() возвращает список имён, определяемых объектом:
dir(clr) через openSSH client:

['AddReference', 'FindAssembly', 'GetClrType', 'ListAssemblies', '__class__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_add_pending_namespaces', '_available_namespaces', '_extras', '_load_clr_module', 'clrmethod', 'clrproperty', 'getPreload', 'loader', 'setPreload']

dir(clr) при загрузке страницы:

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'load']

добавить
WSGIApplicationGroup %{GLOBAL} в
/etc/apache2/sites-enabled/youdomain.conf

<VirtualHost *:80>
 . . .
WSGIApplicationGroup %{GLOBAL}
</VirtualHost>

И это все заработало!


Использование PyQt5 и Pygame в одном файле
Нужно, чтобы при нажатии кнопки в PyQt сама программа закрывалась и открывалась игра на Pygame. Пытался сделать по-разному, но не вышло. Все открывается одновременно.

from PyQt5.QtWidgets import QWidget, QApplication, QLineEdit, QPushButton, QPlainTextEdit, QVBoxLayout, QCheckBox, \
    QMainWindow, QComboBox
from pong2 import Ui_MainWindow
import sys
import os
import pygame
from random import randint, randrange

class PongInterface(QMainWindow, Ui_MainWindow):

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.col1 = 'black'
        self.col2 = 'black'
        self.fps = 60
        self.pushButton.clicked.connect(self.start)

    def start(self):
        self.col1 = self.comboBox.currentText()
        self.col2 = self.comboBox_2.currentText()
        self.fps = self.spinBox.text()
        writer = open('settings.txt', 'w')
        writer.write(self.col1 + '\n' + self.col2 + '\n' + self.fps)
        writer.close()
        QApplication.quit()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = PongInterface()
    win.show()

pygame.init()
all_sprites = pygame.sprite.Group()
horizontal_borders = pygame.sprite.Group()
vertical_borders = pygame.sprite.Group()

class Ball(pygame.sprite.Sprite):
    def __init__(self, radius, x, y):
        super().__init__(all_sprites)
        self.radius = radius
        self.radius = radius
        self.image = pygame.Surface((2 * radius, 2 * radius),
                                    pygame.SRCALPHA, 32)
        pygame.draw.circle(self.image, pygame.Color('red'),
                           (radius, radius), radius)
        self.rect = pygame.Rect(x, y, 2 * radius, 2 * radius)
        self.x = randint(-5, 5)
        self.y = randrange(-5, 5)

    def update(self):
        self.rect = self.rect.move(self.x, self.y)
        if pygame.sprite.spritecollideany(self, horizontal_borders):
            self.y = -self.y
        if pygame.sprite.spritecollideany(self, vertical_borders):
            self.x = -self.x

class Border(pygame.sprite.Sprite):
    def __init__(self, x1, y1, x2, y2):
        super().__init__(all_sprites)
        if x1 == x2:
            self.add(vertical_borders)
            self.image = pygame.Surface([1, y2 - y1])
            self.rect = pygame.Rect(x1, y1, 1, y2 - y1)
        else:
            self.add(horizontal_borders)
            self.image = pygame.Surface([x2 - x1, 1])
            self.rect = pygame.Rect(x1, y1, x2 - x1, 1)

size = width, height = 1000, 800

if type(size[0]) == type(size[1]) == int:
    screen = pygame.display.set_mode(size)
else:
    print('Неправильный формат ввода')
firstplatformcolor = pygame.Color('black')
secondplatformcolor = pygame.Color('black')
ballcolor = pygame.Color('red')

pressed_up1 = pressed_down1 = False
up1 = pygame.K_i
down1 = pygame.K_k

up2 = pygame.K_w
down2 = pygame.K_s

firstplatformcords = [0, 0, 7, 80]
secondplatformcords = [width - 7, height - 80, 7, 80]
ballcords = [width // 2, height // 2]

Border(5, 5, width - 5, 5)
Border(5, height - 5, width - 5, height - 5)

Ball(10, ballcords[0], ballcords[1])

fps = 60 # количество кадров в секунду
clock = pygame.time.Clock()
running = True
while running: # главный игровой цикл
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            if event.key == up1:
                pressed_up1 = True
                firstplatformcords[1] -= 30
            if event.key == down1:
                firstplatformcords[1] += 30
                pressed_down1 = True

            if event.key == up2:
                pressed_up1 = True
                secondplatformcords[1] -= 30
            if event.key == down2:
                secondplatformcords[1] += 30
                pressed_down1 = True

        if event.type == pygame.KEYUP:
            if event.key == up1:
                pressed_up1 = False
            if event.key == down1:
                pressed_down1 = False
        # обработка остальных событий
        # ...
    # формирование кадра
    # ...

    screen.fill(pygame.Color('white'))
    all_sprites.draw(screen)
    all_sprites.update()
    pygame.draw.rect(screen, firstplatformcolor, firstplatformcords)
    pygame.draw.rect(screen, secondplatformcolor, secondplatformcords)
    # pygame.draw.circle(screen, ballcolor, ballcords, 10)
    # Ball(10, ballcords[0], ballcords[1])
    pygame.display.flip() # смена кадра
    # изменение игрового мира
    # ...
    # временная задержка
    clock.tick(fps)

Файл pong2:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'pong2.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(789, 382)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(240, 10, 281, 121))
        font = QtGui.QFont()
        font.setPointSize(28)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(210, 260, 351, 101))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(210, 161, 171, 51))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.comboBox.setFont(font)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(240, 130, 111, 20))
        self.label_2.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.label_2.setTextFormat(QtCore.Qt.AutoText)
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(420, 130, 111, 20))
        self.label_3.setObjectName("label_3")
        self.comboBox_2 = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox_2.setGeometry(QtCore.QRect(390, 160, 171, 51))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.comboBox_2.setFont(font)
        self.comboBox_2.setObjectName("comboBox_2")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(340, 210, 81, 21))
        self.label_4.setObjectName("label_4")
        self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
        self.spinBox.setGeometry(QtCore.QRect(340, 230, 81, 22))
        self.spinBox.setObjectName("spinBox")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "Лаунчер понга"))
        self.pushButton.setText(_translate("MainWindow", "Играть"))
        self.comboBox.setItemText(0, _translate("MainWindow", "Red"))
        self.comboBox.setItemText(1, _translate("MainWindow", "Black"))
        self.comboBox.setItemText(2, _translate("MainWindow", "Green"))
        self.comboBox.setItemText(3, _translate("MainWindow", "Blue"))
        self.comboBox.setItemText(4, _translate("MainWindow", "Yellow"))
        self.label_2.setText(_translate("MainWindow", "Цвет первого игрока"))
        self.label_3.setText(_translate("MainWindow", "Цвет второго игрока"))
        self.comboBox_2.setItemText(0, _translate("MainWindow", "Red"))
        self.comboBox_2.setItemText(1, _translate("MainWindow", "Black"))
        self.comboBox_2.setItemText(2, _translate("MainWindow", "Green"))
        self.comboBox_2.setItemText(3, _translate("MainWindow", "Blue"))
        self.comboBox_2.setItemText(4, _translate("MainWindow", "Yellow"))
        self.label_4.setText(_translate("MainWindow", "Частота кадров"))

Нет времени разбирать ваши скрипты, но покажу примерно как должно быть.
main.py

import sys
from PyQt5.QtWidgets import *

from game import Game

class LauncherWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Лаунчер для игры на PyGame")
        self.setGeometry(100, 100, 600, 400)
        self.ui_components()
        self.show()

    def ui_components(self):
        button = QPushButton("Запустить игру", self)
        button.setGeometry(200, 150, 100, 30)
        button.clicked.connect(self.handler)

    def handler(self):
        self.hide()
        QApplication.exit(0)
        my_game = Game()
        my_game.run()

def main():
    application = QApplication(sys.argv)
    window = LauncherWindow()
    sys.exit(application.exec())

if __name__ == '__main__':
    main()

game.py

import sys
import pygame

class Game:
    def __init__(self):
        # Инициализирует игру и создает объекты экрана
        pygame.init()
        self.screen = pygame.display.set_mode((1200, 800))
        pygame.display.set_caption("Alien Invasion")
        bg_color = (230, 230, 230)
        self.screen.fill(bg_color)

    @staticmethod
    def run():
        # Запуск основного цикла игры
        while True:
            # Отслеживание событий клавиатуры и мыши
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()

            # Отоброжение  последнего прорисованного экрана
            pygame.display.flip()


Написал бота, который должен удалять все сообщения начинающиеся с '+' через определенное время,но выдает ошибку
Ошибка: telebot.apihelper.ApiTelegramException: A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: message identifier is not specified
После первого цикла он удаляет все сообщения,не записывает новые и выдает ошибку
<code>
import datetime
import telebot
import sqlite3
import schedule
import time

token='<TOKEN>'
bot=telebot.TeleBot(token,parse_mode='MARKDOWN')
timeformat="%Y-%m-%d"
now = datetime.datetime.now()
now=f'{now:{timeformat}}'
db= sqlite3.connect('server.db',check_same_thread=False)
sql = db.cursor()
sql.execute("""CREATE TABLE IF NOT EXISTS users(
   messageid BIGINT,
   date TEXT,
   message TEXT);
""")
db.commit()

@bot.message_handler(content_types=['text'])
def chatting(message):
    a=list(message.text)
    if a[0]=='+':
        sql.execute(f"INSERT INTO users
VALUES('{message.message_id}','{now}','{message.text}');")
        db.commit()

def job():
    sql.execute("SELECT messageid FROM users")
    b = sql.fetchall()
    for i in range(len(b)):
        bot.delete_message(chat_id='-1001615667874',message_id=b[i])
        sql.execute("UPDATE users SET messageid = NULL")
        db.commit()

schedule.every(10).seconds.do(job)

bot.polling()

while True:
    schedule.run_pending()
    time.sleep(1)
</code>

Функция
fetchall возвращает список из кортежей. Каждый кортеж хранит запрашиваемые из
SELECT значения
Если у вас в
users в
messageid будут 4 строки с значениями 1, 2, 3, 4, то
fetchall вернет
[(1,), (2,), (3,), (4,)]
При получении значений из
fetchall по индексам
b[i] вы получите кортежи т.е.
(1,) и т.п.
Правильно будет доставать значения из кортежей. Кроме того, тут цикл использует индексы, а вы можете напрямую доставать элементы
Пример:

    sql.execute("SELECT messageid FROM users")
    for row in sql.fetchall():
        bot.delete_message(chat_id='-1001615667874', message_id=row[0])

Можно сразу в цикле сделать распаковку в переменные:

    for message_id, in sql.fetchall():
        bot.delete_message(chat_id='-1001615667874', message_id=message_id)

Поместите запуск задачи в отдельный поток и до
bot.polling():

from threading import Thread
...

def do_schedule():
    while True:
        schedule.run_pending()
        time.sleep(1)

Thread(target=do_schedule).start()

bot.polling()


Умножение элементов списка справа и слева
Написал функцию которая должна брать элемент списка, и возвращать список такого же размера, где каждый элемент равен произведению элементов справа и элементов слева.
<code>
def product_list(numbers: list) -> list:
    new_list = []
    for i in range(0, len(numbers) - 1):

        numbers[i] = numbers[0: i-1] * numbers[i+1:]  # беру элементы слева jn i и умножаю на элементы справа

    return print(new_list)

product_list([12, 20])  # == [20, 12]
product_list([9, 9, 9, 9, 9])  # == [6561, 6561, 6561, 6561, 6561]
product_list([1, 5, 2])  # == [10, 2, 5]
product_list([4, 3, 9]) # == [27, 36, 12]
product_list([4, 5, 2, 19, 8, 80])  # == [121600, 97280, 243200, 25600, 60800, 6080,]
product_list([2, 8, 22, 76, 9])  # == [120384, 30096, 10944, 3168, 26752,]

</code>
Выдает ошибку что срезы нельзя между собой умножать (TypeError: can't multiply sequence by non-int of type 'list'), дайте подсказку как правильно помножить значения.

numbers[0: i-1] * numbers[i+1:] на втором примере (со списком из 9) даст два списка, допустим
[9, 9] и
[9, 9]. Понятное дело, что будет указанная ошибка, т.к. нельзя совершить операцию
[9, 9] * [9, 9]. Поэтому нужно или идти по списку, поочередно умножая все элементы, пропустив текущий, или, как предложено в комментарии – перемножить все элементы, а потом делить произведение на текущий элемент (если он не 0).


Не работает import wx хотя wxPython установлен
Столкнулся с проблемой, при попытке импортировать в проект библиотеку wx командой
import wx PyCharm выдает следующую ошибку:

ModuleNotFoundError: No module named 'wx'

Версия Python 3.10.9, дополнительно установленные библиотеки:

numpy 1.24.1;
Pillow 9.4.0;
six 1.16.0;
wxPython 4.2.0.

Операционная система Windows 10.
Установку проводил командой:

pip3 install wxPython

При попытке вызвать в cmd еще раз установку пишет следующее:

Requirement already satisfied: wxPython in c:\users\user\appdata\local\programs\python\python310\lib\site-packages (4.2.0)

Requirement already satisfied: pillow in c:\users\user\appdata\local\programs\python\python310\lib\site-packages (from wxPython) (9.4.0)

Requirement already satisfied: numpy in c:\users\user\appdata\local\programs\python\python310\lib\site-packages (from wxPython) (1.24.1)

Requirement already satisfied: six in c:\users\user\appdata\local\programs\python\python310\lib\site-packages (from wxPython) (1.16.0)

Вопрос разрешился. Подсказал insolor в комментариях.
Действительно я совсем забыл, что в PyСharm в File -> Settings -> Project: pythonProject в разделе Python Interpreter должны стоять библиотеки для того проекта над которым сейчас работаешь. А wxPython я установил в стандартную директорию с python, а не туда, где у меня проект сейчас.


найти пару с заданной суммой в массиве [закрыт]

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

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

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

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

нужна функция, которая принимает на вход массив
x и число
y и возвращает массив из двух элементов
x, сумма которых равна
y
получилось сделать подобную функцию с словарем, но мне именно нужно чтобы на выходе был массив

Один из вариантов:
<code>
def func(x, y):
    for i in range(len(x)-1):
        for j in range(i+1, len(x)):
            if x[i] + x[j] == y:
                return [x[i], x[j]]
</code>


Как в python сохранять записанные данные в файл сразу?
Насколько я знаю, при записи текста в файл .txt, данные будут записаны в файл после выполнения программы, при выполнении кода
file.close()
Как сохранять записанные данные в файл сразу после записи ? Или мне придётся каждый раз открывать и закрывать файл для сохранения записи в нём ?

Документация - великая вещь! ;)
Инициирует сброс данных из буфера в файл.

file.flush()

Ввиду того, что вывод в файл буферизируется, данные, записанные при помощи
file.write() и
file.writelines() в файловую систему могут попасть не сразу. Для форсирования сброса содержимого можно использовать данный метод, а можно дождаться отработки
file.close()


schedule python запуск в конкретные минуты каждого часа
Всем привет, есть задача запускать задачу несколько раз в час.
Например в 0, 15, 45 минут, или же в 0, 15, 30, 45. Понятное дело что можно сделать запуск таски каждые 15 минут
<code>
every(15).minutes.do
</code>
Но такое выражение мне не подходит, потому что таска должна запускаться ровно в n минут.

В первом примере в документации есть такая строка:

schedule.every().minute.at(":17").do(job)

Что означает "выполнять каждую минуту в 17 секунд". Аналогично можно задать для часа, например:

# Выполнять каждый час в 15 минут
schedule.every().hour.at(":15").do(job)
# Если запускать из интерактивного режима Python, то выведет:
# Every 1 hour at 00:15:00 do job() (last run: [never], next run: 2023-01-24 12:15:00)

Нужно таким образом задать время запуска для 0 минут, 15 минут, 30 минут, 45 минут:

import schedule

def job():
    print("I'm working...")

schedule.every().hour.at(":00").do(job)
schedule.every().hour.at(":15").do(job)
schedule.every().hour.at(":30").do(job)
schedule.every().hour.at(":45").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)


Функция подсчета лидера чисел
Создать функцию которая рассчитывает число лидер. Число считается Лидером, если оно больше суммы всех элементов справа от него.
Основные условия:

Входящий список содержит не менее 3 элементов.
Список входных чисел может содержать как положительные, так и отрицательные числа.
Числа могут повторяться
Возвращаемый список должен содержать числа в том же порядке, в котором они встречаются в исходном списке.
Отсутствие элементов справа от числа расценивается как 0.
Написал функцию, но она почему то не выводит последнее число и не выводит отрицательные числа.

<code>
def get_leaders(numbers: list) -> list:
    new_list = []
    for i in range(0, len(numbers)-1):
        if numbers[i] == 0:
            return []
        if numbers[i] >= numbers[i+1] + numbers[i+1]:
            new_list.append(numbers[i])
    return new_list

print(get_leaders([1, 2, 3, 4, 0]))  # == [4]
print(get_leaders([16, 17, 4, 3, 5, 2]))  # == [17, 5, 2]
print(get_leaders([16, 8, 4, 2, 1]))  # == [16, 8, 4, 2, 1]
print(get_leaders([0, 0, 0, 0]))  # == []
print(get_leaders([-1, -1, -1, -1]))   # == [-1, -1]
print(get_leaders([-45, -23, -16, -1, 1]))  # == [1]
print(get_leaders([0, -1, -29, 3, 2]))  # == [0, -1, 3, 2]
print(get_leaders([5, -2, 0]))  # == [5]

</code>


Как в aiogram отправлять сообщение в конкретный чат?
Как можно отправить сообщение в конкретный чат имея ID чата?

Можно использовать Telethon. Намного проще в использовании
Пример:
<code>
await client.send_file(id_chanel, event.media, event.message)
</code>


Как с помощью python вставить страничку из одного PDF в другой
Есть код, который в конец файла test.pdf вставляет страничку из файла last.pdf

import fitz

original_pdf_path = "test.pdf"
extra_page_path = "last.pdf"
output_file_path = "example-extended.pdf"

original_pdf = fitz.open(original_pdf_path)
extra_page = fitz.open(extra_page_path)

original_pdf.insert_pdf(extra_page, to_page=0)
original_pdf.save(output_file_path)

Все прекрасно работает, но теперь мне нужно из файла
five.pdf взять страничку и вставить ее пятой по номеру в файл test.pdf

original_pdf.insert_page(second_page_copy, 1) не помогло

original_pdf.insert_pdf(five_page_path, to_page=0, start_at=1)
выдает ошибку

Traceback (most recent call last):
  File "/Users/iriska/Projects/test/stati/pdf.py", line 14, in <module>
    original_pdf.insert_pdf(extra_page_path, to_page=0, start_at=1)
  File "/Users/iriska/Projects/test/stati/venv/lib/python3.11/site-
 packages/fitz/fitz.py", line 4589, in insert_pdf
    if self._graft_id == docsrc._graft_id:
                         ^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute '_graft_id'

Я не знаю, которую именно страницу вы хотели взять из файла
five.pdf, потому пусть ее номер в переменной
n (для первой примените
n=0, для второй
n=1, и т.д.).
Сделайте так:

n = 1            # вторая страница (например) из файла `five.pdf`

five_page_doc = fitz.open(five_page_path)
original_pdf.insert_pdf(five_page_doc, from_page=n, to_page=n, start_at=4)

Объяснение:

Ваша первая попытка:

original_pdf.insert_page(second_page_copy, 1) не помогло

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

Ваша вторая попытка — правильный метод, неправильные параметры:

original_pdf.insert_pdf(five_page_path, to_page=0, start_at=1) выдает ошибку

Я предполагаю, что ваш первый аргумент
five_page_path не документ, а только путь к нему (т.е. строка). Надо сначала документ открыть

five_page_doc =  fitz.open(five_page_path)

а только зятем применить его как первый аргумент метода
.insert_pdf():

original_pdf.insert_pdf(five_page_doc, from_page=n, to_page=n, start_at=4)
                        ^^^^^^^^^^^^^
                      открытый документ

(Я исправил значение параметра
start_at т.к. вы хотели вставить ее пятой по номеру.)


Как преобразовать 2 строки в словарь?
<code>
a = "16:00"
b = "go"
</code>
Есть 2 такие строки, как добавить их в словарь, так чтобы 16:00 было ключом, а "go" было значением?

Можно сделать этот словарь так:
<code>
d = {a: b}
</code>


Как запустить повторяющуюся блокирующую функцию в разных threads с помощью asyncio, python
Есть блокирующая функция, для примера возьмем:

def blockme(n):
    x = random.random() * 2.0
    time.sleep(x)
    return n, x

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

if __name__ == '__main__':
    i = 0
    while True:
        i += 1
        threading.Thread(target=blockme, args=(i,)).start()

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

как это сделать с помощью
asyncio, так как
asyncio также поддерживает треды и прочие
concurrent.futures
что не менее важно, а стоит ли это делать с помощью
asyncio? Что даст
asyncio? Простоту синтаксиса? Более читаемый код?
а вообще это возможно?

Я уже задал этот вопрос на Stackoverflow.com, правда с момента, как я его задал я уже получил ряд промежуточных знаний и поэтому вопрос модифицировался и отличается от оригинального. На данный момент, обсуждение на SO.com продолжается, задача не решена, но я получил следующую проблему. Один из участников предложил решение:

import asyncio
import random
import time

def blockme(n):
    x = random.random() * 2.0
    time.sleep(x)
    return n, x

def cb(fut):
    print("Result", fut.result())

async def main():
    loop = asyncio.get_event_loop()
    futs = []
    for n in range(20):
        fut = loop.run_in_executor(None, blockme, n)
        fut.add_done_callback(cb)
        futs.append(fut)
    await asyncio.gather(*futs)
    # await asyncio.sleep(10)

asyncio.run(main())

Тут он еще добавил футуры, подразумевая, что нам еще нужны результаты работы (для моей задачи это не обязательно, если ваше решение будет без футур - мне тоже подойдет). И в таком виде, как он написал - все как-будто работает. Но тут есть нюанс: он утверждает, что если заменить
for n in range(20) на
while True, то все тоже будет работать, но у меня так не работает. Код что-то начинает делать в бесконечном цикле, но никакого вывода результатов не происходит. У меня есть подозрение, что то, что лежит в теле цикла не запускает функцию, а лишь определяет и собирает футуры в список. И без
await asyncio.gather(*futs) работать не будет, а значит,  задачу не решает, так как бесконечный цикл невозможен.
Так что есть еще вопросы:

А у вас этот код работает, если заменить ограниченый цикл на бесконечный?
Если - "да", то есть варианты почему он не работает у меня? Проблема в окружении (версии модулей, настройки ОС и т.д.)?

PS.
На русском SO я нашел еще вот такой вопрос, он похож, но во-первых, нет речи про бесконечный цикл, а, во-вторых, предложенное решение, все равно использовало
threading в явном виде и коллеги критиковали использование
asyncio, но одно дело - критиковать, а другое - можно ли это в принципе сделать.

Футуры выполняются при вызове await другой функции или при выходе в другую асинхронную функцию.

while True: записывай как
while await asyncio.sleep(0, result=True): и тогда треды будут запускаться на каждом круге.
Экзекутор нужно определить чтоб ограничить количество тредов. По умолчанию количество ядер умноженное на 5.

pool = concurrent.futures.ThreadPoolExecutor(max_workers=40)

...

while  await asyncio.sleep(0, result=True):
    fut = loop.run_in_executor(pool, blockme, n)
    ....

Но при этом футуры будут всё ещё набиваться в очередь. Не знаю что стоит за причиной запускать бесконечное число потоков, но тут надо бы какой семафор поставить чтоб не забивать. Хотя бы тупой

if len(futs)>40:
   completed, futs = await asyncio.wait(futs, timeout=5)


Ошибки в методах поиска минимального и максимального значения в бинарном дереве
Выдает ошибки при вызове методов поиска минимального и максимального значения в бинарному дереве. Не могу разобраться в чем ошибки?
<code>
class Node:
    """Клас для создания вершини бинарного дерева"""
    def __init__(self, data):
        self.data = data
        self.left = self.right = None

class Tree:
    """Класс для работы з бинарным деревом"""
    def __init__(self):
        self.root = None

    def __find(self, node, parent, value):
        """Метод поиска вершины дерева к которой необходимо добавить значение"""
        if node is None:
            return None, parent, False

        if value == node.data:
            return node, parent, True

        if value < node.data:
            if node.left:
                return self.__find(node.left, node, value)

        if value > node.data:
            if node.right:
                return self.__find(node.right, node, value)

        return node, parent, False

    def append(self, obj):
        """Метод для добавления к бинарному дереву новых елементов из списка"""

        if self.root is None:
            self.root = obj
            return obj

        s, p, fl_find = self.__find(self.root, None, obj.data)

        if not fl_find and s:
            if obj.data < s.data:
                s.left = obj
            else:
                s.right = obj

        return obj

    def show_tree(self, node):
        """Метод для отображения бинарного дерева"""
        if node is None:
            return

        self.show_tree(node.left)
        print(node.data)
        self.show_tree(node.right)

    def show_wide_tree(self, node):
        """Метод для отображения бинарного дерева в ширину"""
        if node is None:
            return
        v = [node]
        while v:
            vn = []
            for x in v:
                print(x.data, end=' ')
                if x.left:
                    vn +=[x.left]
                if x.right:
                    vn +=[x.right]
            print()
            v = vn

    def __del_leaf(self, s, p):
        """Метод для удаления листовой вершины"""
        if p.left == s:
            p.left = None
        elif p.right == s:
            p.right = None

    def __del_one_child(self, s, p):
        """Метод для удаления вершини с одним потомком"""
        if p.left == s:
            if s.left is None:
                p.left = s.right
            elif s.right is None:
                p.left = s.left

        elif p.right == s:
            if s.left is None:
                p.right = s.right
            elif s.right is None:
                p.right = s.left

    def __find_min(self, node, parent):
        """Метод для поиска минимального значения для удаления"""
        if node.left:
            return self.__find_min(node.left, node)

        return node, parent

    def del_node(self, key):
        """Метод для удаления из бинарного дерева"""
        s, p, fl_find = self.__find(self.root, None, key)
        if not fl_find:
            return None
        if s.left is None and s.right is None:
            self.__del_leaf(s, p)
        elif s.left is None or s.right is None:
            self.__del_one_child(s, p)
        else:
            sr, pr = self.__find_min(s.right, s)
            s.data = sr.data
            self.__del_one_child(sr, pr)

    def min_node(self):
        """Метод лля поиска минимального значения"""
        if self.left is None:
            return self.node
        return self.left.min_node()

    def max_node(self):
        """Метод лля поиска максимального значения"""
        if self.right is None:
            return self.node
        return self.right.max_node()

v = [10, 5, 7, 16, 13, 2, 20, 14, 54]
t = Tree()
for x in v:
    t.append(Node(x))

t.del_node(14)
t.show_wide_tree(t.root)
t.min_node()
t.max_node()

</code>

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

    def min_node(self):
        """Метод лля поиска минимального значения"""
        node = self.root
        data = node.data
        while node:
            data = node.data
            node = node.left
        return data

    def max_node(self):
        """Метод лля поиска максимального значения"""
        node = self.root
        data = node.data
        while node:
            data = node.data
            node = node.right
        return data

Я тут только не обработал вариант, когда дерево пустое, т.е.
self.root == None, сделайте это самостоятельно.


Не работает lru_cache(None)
Хоть я и выставил неограниченное количество рекурсии, но программа все равно заканчивается на ошибке RecursionError: maximum recursion depth exceeded
<code>
from functools import *
@lru_cache(None)

def foo(n):
    if n >= 10000:
        return n
    if (n < 10000) and (n % 2 == 0):
        return 1 + foo(n / 2)
    if (n < 10000) and (n % 2 == 1):
        return (n ** 2) + foo(n + 2)

for i in 9, 192:
    foo(i)
</code>

Если в
foo подаётся нечётное число, то она начинает рекурсивно ходить по одной и той же ветке кода:

    if (n < 10000) and (n % 2 == 1):
        return (n ** 2) + foo(n + 2)

Потому что
n + 2 - это тоже нечётное число в случае, если
n было нечётное. Перебираются все нечётные числа подряд, начиная с начального:

9
11
13
15
...
9997
9999
10001

Таким образом, в этой ветке будет совершено
(10000 - n - 1) / 2 рекурсивных итераций. Для
n = 9 с которого вы начинаете, это будет
4995, не каждый интерпретатор питона может выдержать такую степень рекурсии, даже если вы и повысите её лимит.
Причём, повышать уровень рекурсии нужно выше этого числа, там есть и другие накладные расходы.
P.S. С чётной веткой у вас тоже смешно. Если напечатать
n с которым происходит обращение к функции, то получится:

192
96.0
48.0
24.0
12.0
6.0
3.0
5.0
7.0
9.0
11.0
13.0
15.0
...

То есть сначала чётное число, которого, конечно же, нет в кэше, потом чётные числа с плавающей точкой, которых опять же нет в кэше, а дальше числа нечётные, но не целые, как было при первом прогоне с
n = 9, а с плавающей точкой. Для кэша целые числа и числа с плавающей точкой - это разные числа!
В итоге кэш у вас вообще ни разу не сработал, это можно проверить по статистике использования кэша:

print(foo.cache_info())
# CacheInfo(hits=0, misses=10003, maxsize=None, currsize=10003)

Значение
hits=0 говорит нам о том, что значение из кэша ни разу не было использовано.
И да, я надеюсь вы понимаете, что
for i in 9, 192: - это цикл всего по двум числам:
9 и
192? Это кортеж. Вот если бы вы сделали такой цикл
for i in range(9, 192):, то кэш мог бы быть использован и довольно эффективно. А сейчас у вас что есть кэш, что нет - абсолютно никакой разницы, он совсем не используется.


Как в модуле smtplib отправлять письма по порту 465?
Подскажите, что я делаю не так?
Получаю ошибку:

smtplib.SMTPResponseException: (500, b'5.5.1 Invalid command')

Вот мой код:

#импорт библиотек для отправки электронных писем
import smtplib
from smtplib import SMTP_SSL as SMTP
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders

#отправка заполненной формы электронным письмом
from_addr = "[email protected]"
password = "***************"
to_addr = "[email protected]"

msg = MIMEMultipart()
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = "Тема письма"
body = "Тут письмо со вложением"
msg.attach(MIMEText(body, 'plain'))
filename = "письмо.docx"
attachment = open("письмо.docx", "rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
smtp_ssl_obj = smtplib.SMTP_SSL("server.smtp.com", 465)
smtp_ssl_obj.starttls()
smtp_ssl_obj.login(from_addr, password)
text = msg.as_string()
smtp_ssl_obj.sendmail(from_addr, to_addr, text)
smtp_ssl_obj.quit()

Спасибо комментатору, решением было убрать эту строку:
<code>
smtp_ssl_obj.starttls()
</code>