Задать вопрос
  • Как из main.py запустить несколько других файлов .py, чтобы они работали параллельно?

    Vindicar
    @Vindicar
    RTFM!
    Другие идеи есть в документации, просто её надо читать.

    subprocess.Popen() БЕЗ использования wait() или communicate().
    Ответ написан
  • Можно ли узнать возврат функции при использовании многопоточности Thread на Python?

    Vindicar
    @Vindicar
    RTFM!
    Лучше используй долгоживущие потоки и пару queue.Queue. Из первой потоки в цикле извлекают задания и обрабатывают их, во вторую складывают ответы. Главный поток - наоборот, кладёт задания в первую очередь и извлекает ответы из второй.

    См. также: паттерн "поставщик-потребитель".
    Ответ написан
    Комментировать
  • Как сделать вывод в лог logging python?

    Vindicar
    @Vindicar
    RTFM!
    Добавь помимо FileHandler еще и StreamHandler.

    И да, я бы не советовал настраивать логи в конструкторе класса. Пусть класс использует getLogger() и пишет в лог, но определять уровни и места, куда лог пишется, должна основная программа.
    Ответ написан
    Комментировать
  • Как убрать лишние знаки?

    Vindicar
    @Vindicar
    RTFM!
    Ещё один не выучил основы языка, но пытается работать с БД.

    fectchone() возвращает кортеж, в твоём случае кортеж с одним элементом. Скобки - это строковое представление кортежа. Как вытащить значение из кортежа - читай по ссылке.

    Кортежи, списки и словари - это вообще азы языка. Их надо знать, и узнавать с первого взгляда.
    Ответ написан
    Комментировать
  • Сделать, что бы две функции работали?

    Vindicar
    @Vindicar
    RTFM!
    asyncio создаёт цикл-реактор (loop) только для главного потока. Если тебе нужен отдельный реактор в другом потоке (что само по себе повод остановиться и задуматься - нахрена?), создавай его сам в начале потока, потом уже вызывай асинхронный код.
    См. asyncio.new_event_loop() и asyncio.set_event_loop().
    Ответ написан
    1 комментарий
  • Почему 2-handler не запускается?

    Vindicar
    @Vindicar
    RTFM!
    @bot.message_handler() означает, что следующая функция будет обслуживать ВСЕ входящие сообщения, независимо от их содержимого. Соответственно, будет вызываться она, а последующие обработчики сообщений - нет.
    Либо используй параметры message_handler(), чтобы сузить круг обрабатываемых этой функцией сообщений.
    Либо помещай всю логику обработки сообщений в эту функцию, т.е. соедини оба обработчика в один.
    Ответ написан
    Комментировать
  • В чем преимущество статического массива перед динамическим?

    Vindicar
    @Vindicar
    RTFM!
    Насколько мне известно...
    Статический массив:
    - Размер должен быть известен на момент компиляции. Твой пример - это нестандартная фишка ряда компиляторов, по-хорошему для статического массива размер не должен быть динамическим (определяться во время выполнения).
    + Компилятор сам позаботится об удалении массива.

    Динамический массив:
    + Размер может определяться во время выполнения.
    - Нужно не забыть освободить память массива самостоятельно.

    А вообще, если нет причин делать иначе, используй std::vector. Если тебе понадобится именно массив в стиле C, вектор позволяет его легко получить методом .data().
    + Размер не просто динамический, вектор может переаллоцировать свою память по мере надобности. Так что для ситуаций, когда размер заведомо неизвестен, вектор весьма удобен.
    + Вектор сам управляет своей памятью. Убил вектор - убил управляемый им массив.
    Ответ написан
    1 комментарий
  • Из за чего появляется ошибка в строке client.run(config.TOKEN)import discord?

    Vindicar
    @Vindicar
    RTFM!
    В чём моя проблема ?

    1. В том, что ты не знаешь питон, а рвёшься писать ботов. Иначе знал бы, что client.run(config.TOKEN)import discord - это и впрямь неверный синтаксис.
    2. В том, что ты не осилил редактор текста на этом сайте, и не озаботился отформатировать код.
    3. Ну и в том, что ты, походу, вставил код бота в файл дважды.
    Ответ написан
    Комментировать
  • Как ипортировать функции из файлов?

    Vindicar
    @Vindicar
    RTFM!
    Ещё один товарищ не учил Питон, но рвётся написать божественного бота...

    Когда ты импортируешь файл (модуль), этот модуль выполняется - практически так же, как если бы ты его запустил непосредственно. Различие есть, но небольшое. Теперь посмотрим на твои файлы.
    В первом файле ты объявляешь переменную bot. Она существует в пространстве имён первого файла (модуля).
    Если ты в нём делаешь import second_file, в нём тоже присутствует создание переменной bot - в локальном пространстве имён этого модуля. Это две разные переменные, и два разных экземпляра класса Telebot.
    Поэтому когда ты выполняешь в одном файле bot.run() (ну или как там бот запускается), ты запускаешь только один экземпляр. Второй остаётся неактивированным, и всё, что к нему привязано, не работает.

    Тебе надо как-то передать переменную bot во-второй файл, не нарвавшись при этом на циклический импорт (чтобы не было "первый импортирует второй, а второй - первый").
    Тут поможет ещё один простой факт: в питоне всё - операторы. Т.е. объявление функции - это оператор. Его можно помещать куда угодно, внутрь любого блока программы: внутрь if, внутрь цикла, внутрь другой функции. Он выполнится при выполнении соответствующего блока.
    Так что ты можешь завернуть свои обработчики из второго файла в функцию, принимающую ссылку на bot. А потом импортировать эту внешнюю функцию в первый файл и там её вызвать.
    #второй файл, second_file.py
    import telebot
    from telebot import types
    # эта функция создаст все обработчики и зарегистрирует их в предоставленном боте
    # вызывай её строго один раз за скрипт
    def register_handlers(bot):
        # а тут уже пошли обработчики
        @bot.message_handler(commands=['start'])
        def start(message):
            markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
            btn0 = types.KeyboardButton(' Каталог фильмов')
            btn1 = types.KeyboardButton(" Каталог фильмов")
            btn2 = types.KeyboardButton(' Случайный фильм')
            btn3 = types.KeyboardButton(' Предложить фильм')
            markup.add(btn0, btn1, btn2, btn3)
            bot.send_message(message.from_user.id, ' Привет, {0.first_name}. Я Kinomorph - бот, с которым ты можешь найти интересный фильм для просмотра вечером\n \n Если у тебя есть номер или название фильма, ввести его можно прямо сейчас'.format(message.from_user), reply_markup=markup)
    
    # любой код, который не должен исполняться при импорте, оформляй так:
    if __name__ == '__main__':   # переменная __name__ содержит имя, под которым импортируется модуль
        print('Этот код выполнится ТОЛЬКО если файл запущен напрямую.')
        print('Он не выполнится при импорте файла.')


    # первый файл, main.py
    import telebot
    import config
    import second_file  # модуль импортируется - в нём __name__ будет равно "second_file", а не "__main__"
    
    # инициализация
    bot = telebot.TeleBot(config.Token)
    second_file.register_handlers(bot)  # тут вызывается импортированная функция
    Ответ написан
    Комментировать
  • Почему не работает bot_func.stop(Client, module Pyrogram)?

    Vindicar
    @Vindicar
    RTFM!
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    Зачем?!
    Если у тебя бот асинхронный, просто сделай саму функцию GetUserByUsername() async.
    Ответ написан
  • Как получить списки в переменные?

    Vindicar
    @Vindicar
    RTFM!
    list_of_lists = [spisok[i:i + n] for i in range(0, len(spisok), n)]
    Ответ написан
    Комментировать
  • Как исправить "io.UnsupportedOperation: read"?

    Vindicar
    @Vindicar
    RTFM!
    fp = open(f'captcha_{str(ran)}.jpg', 'wb')
    fp.write(res.content)

    Ты открыл файловый объект для записи, а чтобы его отправить, нужно чтение.
    Или открой объект для модификации ("wb+") и сделай fp.seek(0, 0) после записи, чтобы вернуться в начало файла.
    Или закрой файл, и открой его снова, уже для чтения ("rb").
    Ответ написан
  • Не выполгяется последняя часть кода @bot.callback_query_handler(func=lambda call:True) def callback2(call): почему и как исправить?

    Vindicar
    @Vindicar
    RTFM!
    @bot.callback_query_handler(func=lambda call:True)
    func говорит боту, когда вызывать обработчик. Бот вызывает только ОДИН обработчик (первый подходящий).
    func=lambda call:True означает, что обработчик должен вызываться для ВСЕХ кнопок.
    Научись различать обработчики по call.data. Например, пусть у одной группы кнопок data начинается с "foo.", а у другой - с "bar.".
    item = types.InlineKeyboardButton('4', callback_data='foo.question1')
    item2 = types.InlineKeyboardButton('3', callback_data='foo.question2')

    gotov = types.InlineKeyboardButton('Готов', callback_data='bar.gotov')

    Тогда ты сможешь прописать два обработчика:
    @bot.callback_query_handler(func=lambda call:call.data.startswith('foo.'))

    и
    @bot.callback_query_handler(func=lambda call:call.data.startswith('bar.'))


    Разумеется, вместо foo и bar можно придумать свои префиксы, в том числе многоуровневые (типа callback_data='questions.q1.answer1').
    Ответ написан
    1 комментарий
  • Sqlite3 операционная ошибка, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    c.execute(f"SELECT * from banking_application WHERE name_p IS {pop}")

    За такое бьют линейкой по пальцам. Собственно, ты уже наткнулся на одну из причин почему. Вторая тут.
    Ну и да, IS используется только как IS NULL или IS NOT NULL. Надо вот так:
    c.execute("SELECT * from banking_application WHERE name_p = ?", pop)
    Ответ написан
  • Как обратится к функции вне handler?

    Vindicar
    @Vindicar
    RTFM!
    global resault_func
    resault_func = fi(fil)

    Примерно так и обращайся.
    Ответ написан
    1 комментарий
  • Как корректно разобрать последовательность байт из COM-порта в python?

    Vindicar
    @Vindicar
    RTFM!
    Но почему каша в serial, и как его ответ сделать только bytes без исключения, требует размышления и осознания. Ведь переменная a - это bytes, и binascii.hexlify(a) это тоже bytes...

    Потому что никакой каши нет. Ответ уже только bytes.
    Просто когда выкидывашеь их в консоль, питон (точнее, метод __str__() класса bytes) пытается их представить "как можно читабельнее", т.е. пробует декодировать как ascii-строку что получится, а что не получится, представляет escape-последовательностями \x??.
    Доказать легко:
    b1 = bytes([1,2,3])
    print(b1)  # b'\x01\x02\x03'
    # начиная с Python 3.8 можно указать разделитель в методе hex()
    print(b1.hex(' ')) # 01 02 03
    
    b2 = bytes([0x57, 0x54, 0x46])
    print(b2)  # b'WTF'
    print(b2.hex(' ')) # 57 54 46

    Как видим, работает идентично
    Ответ написан
    Комментировать
  • Как добавлять произвольные данные в extra в logging python?

    Vindicar
    @Vindicar
    RTFM!
    Чем не устраивает вариант с непосредственной подстановкой данных в строку?
    logger.info("New log data: param1 = %s, param2 = %s", value1, value2)

    Просто если у тебя так много разных вариантов подставляемых данных, то проще это решать на уровне отдельного обращения к логгеру.
    Ответ написан
  • Почему не работает replace в python, json?

    Vindicar
    @Vindicar
    RTFM!
    akitaino = input
    Ты не вызываешь функцию input(), чтобы ввести строку с клавиатуры.
    Ты помещаешь ссылку на функцию input() в переменную akitaino.
    Что-то мне подсказывает, что ты не этого хотел.
    Ответ написан
  • Как понять каррирование и частичное применение функции? В чём их различия?

    Vindicar
    @Vindicar
    RTFM!
    plyk, вот частичное применение в упрощённом варианте для двух аргументов.
    def partial(func: typing.Callable[[int, int], int], arg1: int) -> typing.Callable[[int], int]:
        def wrapper(arg2: int) -> int:
            return func(arg1, arg2)
        return wrapper
    
    def add (x: int, y: int) -> int:
        return x + y
    
    def div(x: int, y:int) -> int:
        return x // y
    
    add_42 = partial(add, 42)
    print(add_42(3))  # 42 + 3 = 45
    
    div_120 = partial(div, 120)
    print(div_120(30))  # 120 // 30 = 4


    А каррирование - по сути, каррированная функция вместо выбрасывания ошибки "недостаточно аргументов" возвращает частично применённую функцию для себя и указанных аргументов. Вот очень упрощённая реализация для функции двух аргументов:
    def curry(func: typing.Callable[[int, int], int]) -> typing.Callable:
        def wrapper(*args):
            if len(args) == 2:
                return func(*args)
            elif len(args) == 1:
                return partial(func, args[0])
            else:
                raise Exception('Invalid arguments')
        return wrapper
    
    curried_add = curry(add)
    print(curried_add(32, 23))  # 55
    add_30 = curried_add(30)
    print(add_30(70))  # 30 + 70 = 100
    Ответ написан
    6 комментариев
  • Можно ли написать OS на Python?

    Vindicar
    @Vindicar
    RTFM!
    Нет.
    Ответ написан
    Комментировать