• Как декодировать текст?

    @deliro
    import base64
    
    text = 'eyJzaWQiOiJmYVVGVjBpTVo2OTRpY3BTVnhsMGJNbzBaUEJGTmcyWiIsImFpZCI6bnVsbCwiZXhwIjoxNjY3MTQ4NTQyfQ'
    print(base64.b64decode(text + "=="))


    Пожалуйста
    Ответ написан
    1 комментарий
  • Как составить число n из элементов списка?

    @deliro
    Ответ написан
    Комментировать
  • Sqllite ерунда в ответе на запрос (дата/время)?

    @deliro
    Как минимум, даты не хранят в таком формате, потому что в таком формате они не сравниваются лексикографически. Правильный формат - "2022-10-28 01:19". От большего к меньшему. Год, месяц, день. Размерность обязательна, нельзя написать 2022-2-15 и сказать, что это 15е февраля, только 2022-02-15, иначе у тебя все даты февраля станут позже месяцев с двузначными числами: октябрь, ноябрь, декабрь ("10", "11", "12" меньше "2" лексикографически). Только так между двумя датами в виде строк можно поставить знак «больше» или «меньше». Ну или хранить как timestamp тоже вполне вариант, меньше места займёт, но менее человекочитаемо
    Ответ написан
    Комментировать
  • Почему кв.матрица — nxn?

    @deliro
    Это троллинг такой? У квадрата все стороны равны, верно? Вот и у квадратной матрицы количество столбцов равно количеству строк. А причём тут индекс — я могу только догадываться. Почему трёхэтажный дом по 3 квартиры на каждом этаже называют девятиквартирным, если у каждой квартиры есть свой номер?
    Ответ написан
    2 комментария
  • Что будет при увеличении вместимости канала?

    @deliro
    1. Нет, либо нет в 99.9999% случаев
    2. Да, чтобы ограничить то, на скольких OS тредах может расположиться рантайм. Это прямо влияет на CPU-bound задачи и почти не влияет на IO-bound. Например, у тебя есть функция, которая перемножает матрицы. В канал поступают матрицы, есть 10 горутин, которые читают оттуда и умножают матрицы. Очевидно, что если GOMAXPROCS будет == 1, то все эти горутины будут жить на одном треде и будут "мешать" друг другу, задействуя не более одного ядра процессора. Если GOMAXPROCS будет 10, то каждая горутина может расположиться в отдельном ОС треде и считать себе там матрицы на "собственном" ядре.
    3. Увеличится канал (sic!). Канал — это очередь. Канал без буфера — это "очередь", в которую можно добавить элемент только если с другой стороны этот канал кто-то пытается прочитать. Если такого нет — горутина будет ждать, пока этот канал кто-то захочет прочитать и наоборот, если кто-то читает канал, а с другого конца никто туда не пишет, то горутина будет ждать до тех пор, пока в канал кто-то не захочет записать. Если в канале есть буфер, то это уже становится полноценной очередью. Есть N слотов, если кто-то пришёл записать в канал, канал никем не слушается и там есть хотя бы один свободный слот — этот "кто-то" запишет в канал и пойдёт по своим делам и только если в буфере нет свободных слотов, то этот "кто-то" будет ждать, пока слот освободится. И наоборот, если кто-то слушает канал и в буфере канала уже что-то есть, то он сразу забирает первый на очереди элемент и уходит. Обычно это делают, чтобы сгладить нагрузку. Например, у тебя есть парсеры, которые что-то парсят, чтобы потом записать на диск. Но диск — штука непредсказуемая, может записать за 1мс, а может тупить 20мс. Довольно странно, если парсер будет ждать диск эти 20мс, хотя у него есть работа, которую он может выполнять прямо сейчас. Для этого можно создать буфер, куда парсер будет кидать данные СРАЗУ, а горутина, которая пишет на диск, заберёт их "когда-нибудь потом", когда диск перестанет тупить.
    Ответ написан
    4 комментария
  • Как запараллелить выполнение ф-ций в асинхронном парсере?

    @deliro
    1. Создать очередь (asyncio.Queue)
    2. Парсер пишет в очередь, писарь csv читает очередь и пишет в неё.
    3. Парсер и писарь должны запускаться одновременно, то есть, типа такого

    q = asyncio.Queue()  # с maxsize можно поиграться, в данном случае отставание писаря от парсера может быть не более чем на один элемент
    await asyncio.gather(get_pages_data(q), csv_writer(q))

    4. Парсеров, кажется, надо сделать больше одного. То есть, появляется второй asyncio.Queue (назовём его work_queue), куда падают lines из файла, эту очередь слушают N воркеров (скажем, 5 штук), получают элемент, работают с ним, затем пишут в result_queue, который слушает писарь csv и записывает результат в файлик

    Псевдокод будет выглядеть так:

    async def file_reader(work_q, n_parsers):
        with open('all_links_1.txt', 'r') as f:
            lines = [line.strip() for line in f.readlines()]
        for line in lines:
            await work_q.put(line)
        for _ in range(n_parsers):  # говорим парсерам, что работы больше нет
            await work_q.put(None)
    
    async def parser(work_q, results_q):
        while True:
            line = await work_q.get()
            if line is None:
                return
            result = ... магия с походом в http ...
            await results_q.put(result)
    
    async def writer(results_q):
        with open('companys.csv', 'w', newline='') as file:  # возможно, открывать файл имеет смысл при каждом получении элемента и закрывать после записи, так файл всегда будет "целым", но процесс записи будет дольше
            writer = csv.writer(file, delimiter=',')
            while True:
                result = await results_q.get()
                if result is None:
                    return
                writer.writerow([result['name'], result['phone'], result['edrpou']])
    
    
    async def main():
        work_queue = asyncio.Queue()
        results_queue = asyncio.Queue(10)  # парсер не должен ждать, пока писарь запишет в файл (хард может быть занят), поэтому небольшой буфер
        n_parsers = 5
        tasks = []
        parsers = []
        reader_task = asyncio.create_task(file_reader(work_queue, n_parsers))
        tasks.append(tasks)
        for _ in range(n_parsers):
            parser_task = asyncio.create_task(parser(work_queue, results_queue))
            tasks.append(parser_task)
            parsers.append(parser_task)
        tasks.append(asyncio.create_task(writer(results_queue)))
        await asyncio.gather(*parsers)  # ждём все парсеры
        await results_queue.put(None)  # говорим писарю, что больше ничего не будет
        await asyncio.gather(*tasks)  # дожидаемся все остальные таски (вернее, будет только одна — writer)


    Однако нужно понимать, что порядок результатов при таком подходе не будет гарантированным или хоть сколько-то стабильным. Поэтому, если порядок важен, стоит писать в файл какую-то промежуточную структуру (пусть тот же csv, но с доп столбцом link) и под конец всех работ вычитывать её, сортировать и складывать уже в нужном порядке
    Ответ написан
  • Можно ли избавиться от избыточных типов (struct) в Golang?

    @deliro
    Либо делать несколько типов, либо один супер-тип, который будет содержать все возможные поля, часть из которых будет nil'ами, если не пришла из апи. У го очень тупорылая система типов, ни о каких ADT речи нет
    Ответ написан
    4 комментария
  • Насколько безопасно передавать всю модель в контексте, если некоторые её поля надо скрыть?

    @deliro
    Ты хоть чуть-чуть разбирался, как происходит вся цепочка запрос-ответ? Как можно извлечь из отрендеренного HTML то, что ты туда не вывел?
    Ответ написан
    4 комментария
  • Объясните, как проще и на сколько это сложно будет новичку?

    @deliro
    Разбираясь, не имея опыта ни в чем, вполне можно на это потратить и 4 месяца и больше. Если тебя это пугает — откажись от программирования. Но в целом это довольно простое клиент-серверное взаимодействие. Самый примитивный вариант можно накидать за час. Условно, у тебя есть два урла, на один идут команды, на другом сервер отвечает изменениями. Изменения запрашиваются с некоторой частотой (смотря как тебе нужно): раз в секунду, раз в минуту, 10 раз в секунду, смотря насколько быстро надо реагировать. Вместо урла с изменениями можно сделать очередь сообщений, вебсокет и что еще угодно, до чего додумается фантазия и требования. Ну и получив изменения, ты на них как-то реагируешь
    Ответ написан
    5 комментариев
  • Надежный способ достать созданный пост в тесте формы django?

    @deliro
    1. В ответе на создание поста где-то отдавать ид созданного: урл редиректа вида /posts/1234/, в жисоне, а если ответ этого не подразумевает, то можно в заголовке или ставить в сессию (вариант с заголовком лучше)
    2. При создании поста сохранять какой-нибудь last_post_id юзера (тоже подвержен состояниям гонки, как и фильтрация по дате/ид)
    3. Ставить уровень изолированности транзакций выше read committed (repeatable read или serializable)
    Ответ написан
    Комментировать
  • Какой ноутбук купить: MacOS или PC?

    @deliro
    8гб памяти никому уже не хватает для разработки (если ты не вимер). Это однозначно всё начинает свопаться и лагать. 16 минимум

    M1 хорош, даже очень. Поменял месяц назад macbook pro 13 с i5 на macbook pro 14 с m1. Всё работает заметно быстрее (по ощущениям от интерфейсов, раза в 2-4, по цифрам: сборка JS на esbuild, например, ускорилась с 240мс до 45мс), а вентилятор не включался, кажется, ещё ни разу с моими задачами (обычно это докер + браузер + мессенджеры + PyCharm + Goland). Постоянно холодный и надолго хватает батареи.

    Но нужно понимать, что под M1 есть не всё запускается нативно (хотя большая часть уже есть). Например, я не очень в курсе, что там у С++ с кросс-компиляцией. Go кросс-компилируется довольно быстро, но Go в целом компилируется очень быстро. Возможно, тебе придётся устраивать танцы с бубном. Не то чтобы это было преградой, просто потенциальные неудобства, о которых стоит знать заранее.

    По удобству пользования, имхо, ничего не сравнится с маком. Трекпад, клавиатура, экран и сборка — лучшие. Именно как мобильное устройство, макбук — однозначный топ.
    Ответ написан
    2 комментария
  • Как ограничить ресурсы бота (ОЗУ) в discord на python?

    @deliro
    Лимиты теоретически ограничить можно, но практически - не нужно. 1.5 гб для ботика - это овердофига (если только он не обрабатывает десятки тысяч пользователей одновременно). Особенно если он асинхронный (запущен в одном процессе). Правильно - лечить проблему, а не её симптомы. Профилируй, почему у тебя бот столько жрёт. Вероятно, где-то что-то течёт. Плюс в питоне вагон способов уменьшить нагрузку на память от элементарного __slots__ до генераторов и Сишных библиотек

    Ну и как сказал mayton2019, после оптимизации, если это не спасает, нужно начинать горизонтально масштабировать нагрузку.

    Тупо ограничить память - это просто шанс того, что придёт OOM Killer (или его аналог) и прибьёт твоё приложение, когда оно этого не ожидает. Да, есть инструменты, например, в golang, чтобы ограничить потребление памяти, но все они делают ровно одну вещь: управляют параметрами запуска сборщика __мусора__ (то есть, памяти, которая НЕ НУЖНА). На секундочку, протёкшая память не определяется как мусор, ровно как и не является мусором НУЖНАЯ память. Её никакие оптимизаторы не сожмут никакой магией.

    Есть также техника, которая позволяет "костыльно", но быстро и иногда даже эффективно избавляться от утечек памяти, не решая саму причину утечек. Тупо перезапускать воркер после X обработанных запросов, то есть, стартовать новый процесс, перекидывать трафик на него, а старый убивать вместе со всей утёкшей памятью.
    Ответ написан
    2 комментария
  • Как ускорить работу Python в разы?

    @deliro
    Ну ага мы сейчас такие раз и рецепт тебе сказали, который работает для всех случаев. Если бы он был, его бы логично было запихать прям в интерпретатор, не так ли?

    Может быть, asyncio тебе поможет, может быть threading, может быть, там CPU-bound у тебя что-то и надо multiprocessing, а может и вообще на PyPy заменить интерпретатор или часть кода переписать на Cython

    А может вообще сервер стоит подвинуть ближе к серверу API чтобы пинг уменьшить. Или лимиты как-то повысить, используя прокси, несколько аккаунтов или заплатив за API.

    Ну или просто код говно:)

    Нам откуда знать профиль твоей нагрузки? Вариантов тысячи.
    Ответ написан
    1 комментарий
  • Как при помощи pydantic распарсить json?

    @deliro
    Как насчёт почитать документацию? https://pydantic-docs.helpmanual.io/usage/models/
    Ответ написан
    Комментировать
  • Как реализовать класс-обёртку, используя Python generics?

    @deliro
    https://github.com/rustedpy/result

    p.s. непонятно, зачем в твоём варианте ты хочешь смешивать мух с котлетами. Валидным возвращаемым значением вполне может быть объект подтипа Exception, в том числе, ошибкой не обязательно должен быть Exception.Часто гораздо удобней ошибкой делать Enum. (Чувствуешь, как значение и ошибка поменялись местами и твоя проверка not isinstance(result, ServiceException) только что зафейлилась?)
    Ответ написан
    Комментировать
  • Стоит ли переписать gulp на webpack?

    @deliro
    webpack - это помойка. Медленная, грязная и монструозная. Попробуй лучше https://vitejs.dev/ или https://parceljs.org/

    Ну или можно остаться на gulp, только тормознутый babel заменить на esbuild или swc, а sass компилировать dart-sass
    Ответ написан
    Комментировать
  • Для чего нужна черепашья графика?

    @deliro
    Наглядно увидеть, что твой код что-то делает. Никакой практической ценности это не несёт
    Ответ написан
    Комментировать
  • Как вычислить среднюю оценку если есть непроголосовавшие люди?

    @deliro
    Ну раздели на долю проголосовавших, чего тут выводить-то и причём тут теовер?

    5 человек оценили по 5 баллов. 2 человека воздержались (по 0 баллов). Сумма 25, среднее 25/7 = 3.5714. Доля проголосовавших 5/7 = 0.714

    3.5714 / 0.714 = 5 средний балл тех, кто голосовал

    Ну или, раз ты знаешь, сколько человек не проголосовало, сразу вычти их из подсчёта (25 / (7 - 2)) = 5
    Ответ написан
    3 комментария
  • Micropython uasyncio почему одна функция тормозит другую?

    @deliro
    Во-первых, urequests.get у тебя блокирующая (с micropython не знаком, но await там у тебя нет и не похоже, что возвращается future)
    Во-вторых, ровно каждые 50мс выполняться оно не будет. sleep ставит в хип таску с приоритетом «текущее время» + время сна. Этот хип разбирается на каждом шаге event loop, но никто не гарантирует, что шаг отработает, допустим, не за 500мс, тогда твоя таска исполнится только через полсекунды. Ну и блокирующий вызов urequests это лишний раз подтверждает

    В общем, sleep - это «усни минимум на x времени», а блокирующий вызов http надо заменить на асинхронный
    Ответ написан
    Комментировать