Ответы пользователя по тегу Python
  • Существует ли поле ввода даты в tkinter python3?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    https://google.gik-team.com/?q=tkinter+date+widget

    Вам уже посоветовали в комментариях это
    Ответ написан
    2 комментария
  • Как сделать редирект со своего сайта на другой с сохранением данных?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Если разные сайты на разных доменах, то не получится. Если на разных субдоменах, то тоже не получится, если куки ставятся конкретно на домен.
    Читайте про OAuth.
    Это именно то, что вам нужно.
    Для всех существующих фреймворков можно найти код поддержки этого протокола.
    Ответ написан
    Комментировать
  • Python уведомление Windows?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вот например с помощью этой библиотеки:

    https://automated-testing.info/t/avtomatizacziya-w...
    Ответ написан
    Комментировать
  • Как вызвать из GUI методы?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Мне кажется вы взялись сразу за много задач и пытаетесь решить их одновременно.
    Хорошее решение было бы таким:
    1. Оформить основную бизнес-логику как отдельную библиотеку.
    2. Сделать CLI интерфейс для для вашей функциональности. Это будет отдельный скрипт. который с помощью argparse разбирает параметры командной строки, извлекает из них аргументы и запускает бизнес-логику. Возможно уже этого будет достаточно. особенно если можно вынести редко изменяемую конфигурацию в отдельный json или yaml файл и сделать на уровне операционной системы биндинг вашей утилиты в контекстное меню "Открыть с помощью". CLI утилита вполне способна сделать все необходимые преобразования, создать новый документ и открыть его экселем или что там привязано к xls.
    3. Если так уж нужна GUI, то я бы не советовал для вашей задачи делать нативное приложение с окошками и кнопочками. Можно сделать тривиальный веб-сервис на flask с одной единственной веб-формой, которая позволяет загрузить xls-файл с компа и потом скачать закэшированный результат. Также можно отобразить ошибки преобразования сверстав их в html.

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

    Ок. Давайте более по существу.
    1. Содержимое всех ваших модулей с бизнес-логикой (ParseExcelOMS.py, ParseExcelMIS.py и т.д.) выделите в отдельные функции, входными аргументами которых будут имена файлов.
    2. Импортируйте эти модули в модуле с GUI, и там, получив имена файлов, вызывайте нужные функции.

    Если не будет получаться - приходите с конкретными вопросами. А-то не понятно что именно вам не понятно. Вроде код у вас слишком сложный для непонимания автором концепции функций.
    Ответ написан
  • Почему парсер всех внутренних ссылок сайта на Python не хочет парсить некоторые сайты?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    На в каждом теге "a" есть `href`.
    from urllib.parse import urlparse
    from bs4 import BeautifulSoup
    import requests
    import lxml
    DOMAIN = 'apexair.ru'
    HOST = 'http://' + DOMAIN
    FORBIDDEN_PREFIXES = ['#', 'tel:', 'mailto:']
    links = set()  # множество всех ссылок
    headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
    response = requests.get(HOST, headers=headers)
    # print(response.content)
    
    def add_all_links_recursive(url, maxdepth=1):
        # print('{:>5}'.format(len(links)), url[len(HOST):])
    
        # глубина рекурсии не более `maxdepth`
    
        # список ссылок, от которых в конце мы рекурсивно запустимся
        links_to_handle_recursive = []
        # получаем html код страницы
        request = requests.get(url, headers=headers)
        # парсим его с помощью BeautifulSoup
        soup = BeautifulSoup(request.content, 'lxml')
        # рассматриваем все теги <a>
    
        for tag_a in soup.find_all('a', href=lambda v: v is not None):
            link = tag_a['href']
    
            # если ссылка не начинается с одного из запрещённых префиксов
            if all(not link.startswith(prefix) for prefix in FORBIDDEN_PREFIXES):
                # проверяем, является ли ссылка относительной
                # например, `/oplata` --- это относительная ссылка
                # `http://101-rosa.ru/oplata` --- это абсолютная ссылка
                if link.startswith('/') and not link.startswith('//'):
                    # преобразуем относительную ссылку в абсолютную
                    link = HOST + link
                # проверяем, что ссылка ведёт на нужный домен
                # и что мы ещё не обрабатывали такую ссылку
                if urlparse(link).netloc == DOMAIN and link not in links:
                    links.add(link)
                    links_to_handle_recursive.append(link)
    
        if maxdepth > 0:
            for link in links_to_handle_recursive:
                add_all_links_recursive(link, maxdepth=maxdepth - 1)
    
    
    def main():
        add_all_links_recursive(HOST + '/')
        for link in links:
            print(link)
    
    
    if __name__ == '__main__':
        main()
    Ответ написан
    5 комментариев
  • Как преобразовать строки Excel в datetime?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вытаскивайте данные из экселя в списки питона (чем вам там удобнее).
    Получается:
    data=[
        ['дата', '1', '2', '3', '4', '5', '6', '7', ...],
        ['Ноябрь 2019', '11', '22', '33', '44', '55', '66', '77', ...],
        ['Декабрь 2019', '11', '22', '33', '44', '55', '66', '77', ...],
        ...
    ]

    Потом собираете данные в нужный формат:
    import datetime
    import locale
    
    def replace_month(dt: str) -> str:
        dt = dt.replace('Январь', 'января')
        dt = dt.replace('Февраль', 'февраля')
        # ...
        return dt
    
    locale.setlocale(locale.LC_TIME, "ru_RU.utf8")
    head = data[0]
    data = data[1:]
    result_rows = []
    for row in data:
        for day, value in zip(head[1:], row[1:]):
            dt = replace_month(f'{day} {row[0]}')
            try:
                dt = datetime.datetime.strptime(dt, '%d %B %Y')
            except ValueError:
                pass  # тут у нас дата не сконвертнулась, например, 30 февраля. Пофиг.
            else:
                result_rows.append((dt, value))

    Код написал в браузере, не проверял, поэтому может где-то опечатался. Не обессутьте.
    Если форматы дат не постоянны, можно сделать несколько попыток преобразования по разным форматам и локалям.
    Закинуть как обратно в ексель - это тоже отдельная задача.
    Ответ написан
  • Как будет выглядеть этот код на Python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    def gcd(m: int, n: int) -> int:
        modulo = m % n    
        return n if modulo == 0 else gcd(n, modulo)
    
    n = int(input('Enter n:'))
    m = int(input('Enter m:'))
    divv = gcd(n, m)
    P = m // divv
    Q = n // divv
    
    print(P, Q)
    input('Press enter...')
    Ответ написан
    Комментировать
  • Как ускорить этот простой код?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Строго говоря этот код не делает ничего полезного. Только вычисляет степени и забывает их тут же. Это значит, что никаких побочных эффектов кроме задержки и нагрева процессора код не создаёт.
    Отсюда (да, звучит как занудство, но каков вопрос, таков и ответ!), логичные 4 варианта:
    1. Если нагрев процессора обязателен, то ускорить код можно уменьшив число 100000 в скобках.
    2. Если нагрев не нужен, то можно поставить time.sleep(3) и получить задержку нужной длительности.
    3. Если нам важна зависимость задержки от производительности компьютера, но код нужно немного ускорить, см Вариант 1..
    4. Если ни задержка, ни нагревание не нужно, то удалите ВЕСЬ цикл и вы получите минимально возможную задержку.

    Какого черта такие хреновые формулировки вопросов?!
    Ответ написан
    Комментировать
  • Как получить все классы в файле .py?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Слово "лежат" вообще непонятное в контексте вопроса.
    Но можно попробовать угадать чего хочет автор.
    Я бы предложил такой вариант:
    module = importlib.import_module('my_module_name')
    classes = [
        value 
        for value in (
            getattr(module, name) 
            for name in dir(module)
        )
        if isinstance(value, type)
        and getattr(value, '__module__', None) == module.__name__
    ]
    Ответ написан
    Комментировать
  • Что написать на Python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    1. Начните с утилит командной строки.
      • Освойте argparse, pathlib, yaml-конфиги, sqlite, концепцию пайпов, стандартные потоки ввода-вывода, цветной вывод в терминал.
      • Сделайте тулзу для автоматической разгрузки флешек от фотоаппарата. Пусть забирает все фотки с подключенной флешки, раскидывает по папкам с датами в каталоге хранилища, находит дубли, отделяет RAW'ы, правит EXIF, привязывает гео-метки по треку, индексирует в sqlite, находит похожие (opencv), находит и отделяет серии брекетинга для HDR, делает и восстанавливает бэкапы...
      • Сделайте CLI тулзу, которая качает спутниковые снимки региона и клеит для печати на фотообои или большой формат с рамкой, легендой и масштабной линеечкой.
    2. Попробуйте себя в бэкенде:
      • Освойте Flask.
      • Поиграйтесь с Django (сделайте себе уже сайт с вашими проектами, блогом, гостевой, галереей и админкой на готовых компонентах и дизайне).
      • Сделайте свой:
        • уменьшатель ссылок,
        • хостинг записок через QR-коды,
        • TODO-list,
        • анонимный интернет-чат на web-сокетах,
        • свою интернет-радиостанцию для семьи (с ротацией, новостными и погодными вставками, напоминалками из календаря семеных событий помощью TextToSpeech).
      • Попробуйте прикрутить к сайту донаты, принимать платежи.
      • Сделайте свой сайт, который присылает (можно за денежку) выбранную область карты в виде страниц атласа в масштабе и с легендой на основе рендера OSM и спутниковых снимков.
    3. Поиграйтесь с ML на классических примерах.
      • Научите вашу веб-камеру в ноуте вас узнавать, фотать незнакомые лица перед вашим компом.
      • Научите комп "видеть" вашего кота в комнате, понимать когда ему надо погулять.
      • Сделайте скрипт, который находит на записях видеорегистратора гос-знаки автомобилей и сохраняет в CSV вместе с таймингом по ролику.
    4. Поиграйтесь с MicroPython на NodeMCU (ESP8266).
      • Сделайте и закастомизируйте на нём интернет-wifi-радиоприёмник, или детский MP3-плеер для сказок с RFID-сканером и карточками.
      • Сделайте кормушку для котейки.
      • Робота-охранника или робота теле-присутствия для квартиры...
    5. Попробуйте себя в игрострое, если душа лежит. Я бы смотрел для начала в сторону веб-игр для соц-сетей. Да, придётся окунуться немного во фронтенд, но можно найти подельника, который учится фронту.
      • Можно замутить очередной http://www.milliondollarhomepage.com,
      • огромный скетч-холст для совместного рисования в стиле https://xkcd.com/1110/ на leaflet,
      • или свой граббер и просмотрщик тайлов этого комикса и похожих.
    6. Поделайте ботов для телеги - сейчас, похоже, все этим занимаются. Этот ресурс ломится от тупых вопросов по ним, присоединяйтесь.
      • Можно замутить своего бота для скачивания видоса с ютуба (и не только) по ссылке на основе YoutubeDL.
      • Сделайте бота для чата знакомств с гео-привязкой.
      • Бота, который мониторит RSS и репостит в чат.
      • Бота, который мониторит чат и репостит в RSS через сервер на Flask или статику.
      • Сделайте автоматическую качалку и публиковалку аудиокниг с рутрекера (принять ссылку или название, скачать торрент с нужными тегами, сгенерировать запись в RSS-фид, положить в публикуемый каталог, чтобы книги можно было качать и слушать как обычные подкасты, но еще и по команде из телеги).


    Ну сколько можно ныть и вопрошать "что делать"? Огромная куча всего еще не сделана или сделана через задницу. Сделайте тоже! Пусть получится хорошо или снова через задницу, но это будет ваш опыт!
    Публикуйте свои работы в opensource на github. Изучайте best practice, осваивайте CI/CD, Docker, TDD. Подпишитесь на технологические IT-подкасты. Заведите блокнот для базз-вордов и пишите туда всё что слышите незнакомое. Возьмите в привычку обзорно изучать новые вещи каждый день, каждую неделю.
    Со временем ваш профиль в гитхабе начнёт работать на вас. Крутые конторы постоянно мониторят открытые проекты и хантят разработчиков. Хороших программистов всегда не хватает!
    Дерзайте! Хватит ныть и колебаться! Идите делать!
    Ответ написан
    Комментировать
  • Ошибка "string indices must be integers" как решить?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Если data['custom_answer'] равно тому, что вы привели в качестве примера (хотя закрывающую фигурную скобку забыли), то код сработает верно и без ошибок.
    "string indices must be integers"

    Такая ошибка бывает, если кто-то пытается обратиться по текстовому индексу к строке:

    In [1]: 'qwerty'['xxx']                                                         
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-6-994fc1ca7c86> in <module>
    ----> 1 'qwerty'['xxx']
    TypeError: string indices must be integers

    Возможно несколько причин ситуации:
    1. Вы привели не тот код. который выдал вам ошибку.
    2. Вы запутались в данных, что не удивительно если почитать ваши формулировки:
      Вот такой массив передаю в 'custom_answer'

      Теперь мне нужно результат получить и "забрать".


    3. Вы не полностью привели пример данных и среди словарей в списке под ключом 'groups' у вас затесалась обычная строка к которой вы и обратились по текстовому индексу 'full_name'.

    Ответ написан
  • Ввод строки с добавлением в список?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    def task_v1(): 
        """
        Принимает на вход строки (признак конца ввода - пустая строка),
        сохраняет их в список без повторений.
        Печатает сохранённые в списке строки.
        """
        lst = []              # делаем пустой список
        s = input()           # вводим первую строку
        while s:              # пока введённая строка не пуста:
            if s not in lst:  # если строка не в списке:
                lst.append(s) # добавляем её
            s = input()       # принимаем следующую строку
            
        print('\n'.join(lst)) # объединяем все строки через абзац и печатаем
      
    
    def task_v2():
        """
        Также принимает на вход строки, но сохраняет их в Счётчик.
        Счётчик и порядок добавления запоминает и считает количество повторов.
        Печатает ключи счётчика.
        """
        from collections import Counter  # импортируем класс счётчика
        c = Counter()                    # создаём экземпляр Счётчика
        s = input()                      # вводим первую строку
        while s:                         # пока введённая строка не пуста:
            c[s] += 1                    # подсчитываем её счётчиком
            s = input()                  # принимаем следующую строку
            
        print('\n'.join(c))             # объединяем ключи счётчика через абзац и печатаем
          
    
    def task_v3():
        """
        То же, что и v2, но в функциональном стиле
        """
        from collections import Counter  # импортируем класс счётчика
        print(                        # функция печати, которой даём строку...
            '\n'.join(                # которую формируем объединяя через абзац элементы (строки) полученные...
                Counter(              # созданием экземпляра счётчика, которому в конструктор передаём...
                    iter(input, '')   # итератор, который будет вызывать функцию input пока она не вернёт '', 
                                      #   а результаты всех вызовов (кроме последнего) будет возвращать по мере
                                      #   запроса их конструктором Счётчика (для подсчёта)
                ).keys()              # и формированием списка уникальных ключей (строк) из счётчика.
                                      #   ктсати `.keys()` совершенно не нужен. Итаратор по счётчику возвращает ключи.
            )
        ) 
    
    
    def task_v3_1():    
        """В одну строку это выглядит не так ужасно:"""
        print('\n'.join(Counter(iter(input, ''))))
    
            
    def task_v4():
        """
        То же, что и v3, но расписано на этапы и сохранено в промежуточные переменные
        """
        from collections import Counter  # импортируем класс счётчика
        it = iter(input, '')   # создаём итератор, который по мере запроса у него
                               #   очередных значений будет вызывать функцию
                               #   input пока она не вернёт пустую строку
    
        c = Counter(it)        # создаём экземпляр Счётчика и в качестве аргумента
                               #   даём ему наш итератор. тем самым мы предлагаем
                               #   нашему новому счётчику запросить все значения, 
                               #   что отдаст итератор и посчитать количество
                               #   вхождений каждой уникальной строки
    
        unic = c.keys()        # получаем у счётчика его ключи, то есть все 
                               #   уникальные строки, которые он считал.
                               #   Приятный побочный эффект, доступный в современном
                               #   Питоне - это сохранение порядка ключей по мере ввода.
                               # Этот шаг не обязателен, поскольку счётчик итерируется по ключам.
    
        result_text = '\n'.join(unic)  # объединяем все уникальные строки через абзац. Вместо unic можно просто указать `c`.
        print(result_text)             # и печатаем их


    На баше можно совсем коротко, но порядок не сохраняется:
    $ py "set(iter(input,''))"
    $ cat<<""|py -l "set(l)"
    Чтобы сохранялся - подлиннее получится:
    $ cat<<""|py -l "collections.Counter(l)"
    py "collections.Counter(iter(input, ''))"
    Ответ написан
    Комментировать
  • Почему бот выдает ошибку No such file or directory: 'temp/?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    1. Вынесите строку `temp/` в отдельную переменную.
    2. Проверяйте при старте бота этот путь на существование.
    3. Если такого пути нет, можно его либо создать, либо выдать соответствующее сообщение об ошибке и завершить работу.

    Если путь без "/" вначале , то это относительный путь от текущего на момент запуска скрипта.
    Если бот лежит по пути: `/home/my_username/my_bot_folder/my_bot.py`
    И запускается так:
    `my_bot_folder/my_bot.py`
    То текущий каталог на момент запуска у вас домашний:
    `/home/my_username`
    И бот будет пытаться писать картинки по пути типа:
    `/home/my_username/temp/2345435666hashtralala.png`.
    Если у вас в домашнем каталоге нет папки temp, то будет эта ошибка.
    Нужно создать папку temp в нужном месте.
    Можно обработать эту ошибку и в ее обработчике написать `print('please make temp folder in:', os.getcwd())`
    Ответ написан
    Комментировать
  • В чём может быть ошибка в коде?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Метод .send_document() не принимает аргументов. А вы ему туда пихаете два лишних.
    Ответ написан
    Комментировать
  • Как сохранить неизвестное количество элементов из массива в неизвестное количество переменных?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Попробуйте для каждого значения из json, которое вы хотите поместить в отдельную ячейку, собрать ключ, состоящий из имён всех ключей родительских элементов. Для списков это может быть индекс.
    Я показывал такое вот в этом вопросе: Какой программой можно быстро сделать из json в csv?
    Ответ написан
    Комментировать
  • Куда двигаться(Python)?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Хватит "учить". Это не продуктивно. Просто делайте.
    Начните небольшой pet-project в той области, в какой лично вам интересно. Интерес нужен чисто для мотивации. Если вы супер-мотивированный человек, то и так можете делать всё что угодно.
    Вот какой-то тип рассуждает на ютубчике про то, чем заняться юным программистам. Специально не искал, просто промелькнуло на периферии и ваш вопрос напомнил. Он не про питон говорит, но это не важно.

    От себя могу порекомендовать следующее:
    1. Вести блокнотик для баззвордов. Всё, что слышите вокруг себя касательно предметной области, все непонятные слова и термины выписывайте в блокнотик и, на досуге, гуглите. Если тема и термин релевантны вашей области интересов и выбранному стеку технологий, то вникайте глубже, если не очень, то читайте поверхностно. Со временем новые слова в блокнотик станут попадать всё реже, а старые после нескольких попаданий запомнятся и тоже перестанут. Вы станете эрудированным в своей области.
    2. Читайте чужие исходники. Нет, не учите. Нет глубоко лезть не надо. Просто ищите на гитхабе для себя интересное и читайте как это сделали, думайте как сделали бы вы.
    3. освойте базовые вещи:
      • системы контроля версий в целом и git в частности;
      • концепцию TDD и какую-нибудь из стандартных библиотек для юнит-тестирования;
      • принципы unix-way; стандарты CLI; bash; концепцию пайпов (в linux и windiws);
      • освойте регулярные выражения, порешайте кроссворды.
      • соберите для себя шаблоны стандартных приложений для быстрого старта проектов: сайт с админкой и авторизацией; CLI-утилита; REST API сервис...
      • освойте концепцию docker контейнеризации;
      • освойте CI/CD...



    Где-то к середине этого списка ваш вопрос станет гарантировано не релевантен для вас.
    Ответ написан
    Комментировать
  • Как можно заменить способ выбора случайной величины с меньшим потреблением памяти, или есть ли альтернатива random.choises()?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Как минимум можно передавать аргументы в choices не в виде списков, а в виде генераторов.
    r=range(20, 2*10**7);
    print(choices(r, (1/x for x in r)))


    from guppy import hpy; from random import choices; h=hpy(); print(h.heap()); r=range(20, 2*10**7); print(choices(r, (1/x for x in r))); print(h.heap())                                             
    Partition of a set of 257681 objects. Total size = 30586285 bytes.
     Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
         0  77410  30  8264794  27   8264794  27 str
         1  69723  27  5198776  17  13463570  44 tuple
         2  28709  11  2133716   7  15597286  51 bytes
         3  14447   6  2089272   7  17686558  58 types.CodeType
         4  15188   6  2065568   7  19752126  65 function
         5   2013   1  1932488   6  21684614  71 type
         6   3316   1  1515992   5  23200606  76 dict (no owner)
         7    684   0   937144   3  24137750  79 dict of module
         8   2013   1   932560   3  25070310  82 dict of type
         9   1866   1   633536   2  25703846  84 set
    <863 more rows. Type e.g. '_.more' to view.>
    [9585326]
    Partition of a set of 257636 objects. Total size = 30579517 bytes.
     Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
         0  77406  30  8264562  27   8264562  27 str
         1  69724  27  5198832  17  13463394  44 tuple
         2  28709  11  2133716   7  15597110  51 bytes
         3  14447   6  2089272   7  17686382  58 types.CodeType
         4  15186   6  2065296   7  19751678  65 function
         5   2013   1  1932488   6  21684166  71 type
         6   3310   1  1514552   5  23198718  76 dict (no owner)
         7    684   0   937144   3  24135862  79 dict of module
         8   2013   1   932560   3  25068422  82 dict of type
         9   1866   1   633536   2  25701958  84 set
    <859 more rows. Type e.g. '_.more' to view.>

    Но что-то мне подсказывает, что это можно математически привести к операции, работающей за O(1) по времени.

    UPD

    Залез-таки в исходники и считаю важным отметить, что моё решение не полностью решает вашу проблему с памятью.
    Вот что (примерно) делается под капотом:
    def choices(self, population, weights=None, *, cum_weights=None, k=1):
            """Return a k sized list of population elements chosen with replacement.
    
            If the relative weights or cumulative weights are not specified,
            the selections are made with equal probability.
    
            """
            random = self.random
            if cum_weights is None:
                if weights is None:
                    _int = int
                    total = len(population)
                    return [population[_int(random() * total)] for i in range(k)]
                cum_weights = list(_itertools.accumulate(weights))
            elif weights is not None:
                raise TypeError('Cannot specify both weights and cumulative weights')
            if len(cum_weights) != len(population):
                raise ValueError('The number of weights does not match the population')
            bisect = _bisect.bisect
            total = cum_weights[-1]
            hi = len(cum_weights) - 1
            return [population[bisect(cum_weights, random() * total, 0, hi)]
                    for i in range(k)]

    Для нашего случая функцию можно упростить до:
    def choices(a=20, b=2*10**7, k=1):
        from random import Random
        import itertools
        from bisect import bisect
        random = Random().random
    
        n = b - a
        population = range(a, b)
        weights = (1/x for x in population)
        cum_weights = list(itertools.accumulate(weights))
        # get_weight = lambda idx: 1 / (a + idx)
        # get_cum_weight = lambda idx: ????
    
        total = cum_weights[-1]
        hi = len(cum_weights) - 1
        return [
            population[bisect(cum_weights, random() * total, 0, hi)]
            for i in range(k)
        ]

    И здесь видно, что происходит материализация генератора в список:
    cum_weights = list(itertools.accumulate(weights))
    Это уже не три огромных списка, а всего лишь один, но эту проблему тоже можно решить.

    Короче. Весь вопрос в том, как вычислить за O(1) следующую сумму ряда:
    С[n]=1/(a+0)+1/(a+1)+1/(a+2)+...+1/(a+n)
    Если это научиться вычислять за O(1), то bisect(cum_weights, random() * total, 0, hi) будет вычисляться за O(log2(n)). И такая же сложность будет у всей функции в целом.
    Однако это не предел. Думаю можно сразу вычислять индекс искомого числа за O(1) без двоичного поиска. Но это уже вы задайте как вопрос с тегом "математика".
    Ответ написан
    Комментировать
  • Ошибка CORS при использование aiohttp и Angular8 как правильно настроить?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Запустите рядом nginx (есть и портабл, и в докере можно стартануть) и пропишите ваши сервера как upstream через nginx в качестве реверс-прокси.
    Это повесит все ваши сервера на один порт и приблизит ваше девелоперское окружение к тому, что будет у вас в проде.
    Можно в hosts прописать для 127.0.0.1 какой-нибудь домен, чтобы всё ещё сильнее похоже было на прод.
    Проблема уйдёт, когда origin будет совпадать с адресами вызова api.
    Но, очевидно, можно и настройками cors побороть. Вопрос только зачем, если ваш апи предназначен для вашего сайта, а не для публикации для неограниченного круга сторонних сайтов.
    Ответ написан
    Комментировать
  • Как спарсить координаты городов?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Попробуйте вытащить данные из базы openstreetmap.
    Снапшот их базы доступен бесплатно.
    Вот есть штука для импорта в posgtres. Надо сказать, что кроме неё есть еще osm2pgsql, который делает примерно то же самое.
    На OSM Wiki можно найти теги, которыми промаркированы точки городов. А дальше вам, возможно, и ваш список названий не нужен будет, там они все (эти города) есть, причем на нескольких языках.

    Вот, кстати, был даже вопрос про фильтрацию на этом ресурсе.
    Ответ написан
    Комментировать
  • Как правильно спроектировать приложение по распознаванию лиц?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Проектируйте микросервисно. Получится как лего: опрятно и взаимозаменяемо.
    Тем более разные части можно делегировать подружкам по кафедре.

    Итак, микросервисы:
    • 1. Модуль захвата. Можно сделать на основе opencv. Присасывается к видео-потоку и ищет что-то похожее на лица, трекает их (opencv это хорошо умеет). Кадры с лицами гурппами кладёт в очередь (которая у вас отдельным микросервисом рядом крутится). Группы нужны, чтобы можно было улучшить распознавание за счет выбора наиболее однозначно распознаваемых ракурсов.
    • 2. Сервис распознавания. Вытаскивает таски с группами фоток из очереди и кидает в другую очередь на классификацию. После классификации всех вариантов группы выбирает самые надёжные варианты и пишет в БД события.
    • 3. Сервис классификации. Это воркер, он может масштабироваться (запускаться в нескольких экземплярах).
    • Достаёт таск (фоточку) из очереди, даёт своей нейроночке, а та выдаёт идентификатор класса и степень похожести.
    • 4. Вебсервис реализации дэш-борда - рендер и публикация текущей статисики и текущих событий.
    • 5. Сервис срочных уведомлений - выискивает из БД свежие тревожные события и рассылает СМС, дёргает сирену и активирует пулемётные турели.

    Читайте про SOLID. Это надо знать и уметь как "отче наш".
    Ответ написан
    2 комментария