• Как работать с общим списком в многопользовательском приложении?

    @antares4045
    Точка входа в приложение (запускаемый python-скрипт) должна быть одна: при входе или запуске пользователь вводит свой id (или он генерируется на основании неких косвенных признаков). Для хранения данных необходимо использовать базу данных. причём, учитывая что вы сразу захотели многопользовательское приложение, необходимо поднять полноценный сервер базы данных (простенький sqlite не прокатит).
    Если вы не знакомы с sql, рекомендую начать с знакомства с mongodb и способа взаимодействия с ним через python. Если всёже знакомы, то лучше будет поднять инстанс mysql/postgress/или что вы там знаете, вооружиться библиотекой pyodbc и начать постигать мир полноценного промышленного программирования.

    UPD: ответив решил исследовать, нельзя ли стандартный sqlite3 запустить в мультипроцесном режиме -- оказалось костыль есть.

    Подключение к базе блокирует другие подключения и они ждут, пока файл освоботится с задержкой timeout. так что если соединения постоянно открывать-зарывать, то сразу несколько процессов могут работать с одной базой (теоретически её можно коннект в picke положить, но это злая идея).
    Вот такой код по идее должен справляется с парой десятков пользователей (а главное: никакого сервера):
    import sqlite3
    import os
    import sys
    import random
    import time
    from datetime import datetime
    
    TIMEOUT_DELAY=10
    
    CURRENT_DIRECTORY = os.path.normpath(
        os.path.relpath(
            os.path.dirname(__file__),
            os.getcwd())
        )
    DB_PATH = os.path.normpath(os.path.join(CURRENT_DIRECTORY, './db/lists.db'))
    
    
    
    def initBase():
        with sqlite3.connect(DB_PATH) as connect:
            cursor = connect.cursor()
            cursor.execute("""
    CREATE TABLE lists(
        userid INTEGER primary key,
        value INTEGER
    )
    """)
            connect.commit()
    
    
    
    if not os.path.exists(DB_PATH):
        os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
        initBase()
    
    
    ID = None
    if len(sys.argv) > 1:
        ID = int(sys.argv[1])
    else:
        ID = int(datetime.now().timestamp() * 1000) % 10000 + 10000
        print(f'ID не передан. сгенерирован идентефикатор {ID}')
    
    
    while True:
        with sqlite3.connect(DB_PATH, timeout=TIMEOUT_DELAY) as connect:
            cursor = connect.cursor()
            cursor.execute("""SELECT userid, value FROM lists""")
            print(cursor.fetchall())
            x = random.randint(100, 999)
            cursor.execute("""
    INSERT INTO lists(value, userid)
    VALUES (?, ?)
    ON CONFLICT(userid) DO UPDATE SET
    value=?
    WHERE userid=?
    """, [x, ID]*2)
            connect.commit()
        time.sleep(1)


    открыл 3 консоли и запустил
    python3 __main__.py
    python3 __main__.py 1
    python3 __main__.py 2
    вроде работает):
    616e00f12619c652105096.png

    Но лучше всеравно так не делать, а использовать всёже нормальный сервер бд
    Ответ написан
    1 комментарий
  • Программы/сайты которые рассчитывают количество повторений какого-то слова в проекте и отображают список всех слов с указанием количества повторений?

    @antares4045
    на большинстве высокоуровневых языков это вопрос десятка строк.
    Смеха ради набросал реализации на двух языках, которые были под рукой:
    python:
    import os
    import re
    from collections import Counter
    
    PROJECT_DIRECTORY = '.'
    ignoreName=set(['__pycache__', '.git', '.gitignore', 'README.md'])
    ignoreExt=set(['wav', 'jpg', 'png'])
    
    CURRENT_DIRECTORY = os.path.dirname(__file__)
    
    splitToLiteralsReg = re.compile(r"[^a-zA-Zа-яА-Я0-9\_]+")
    
    target_path = os.path.normpath(os.path.relpath(os.path.join(CURRENT_DIRECTORY, PROJECT_DIRECTORY), os.getcwd()))
    
    def shouldIgnore(root, name):
        if name in ignoreName:
            return True
        if name.split('.')[-1] in ignoreExt:
            return True
        return False
    
    counter = Counter()
    
    for root, dirs, files in os.walk(target_path):
        dirs[:] = [
            foldername for foldername in dirs
            if not shouldIgnore(root, foldername)            
        ]
        for filename in files:
            if not shouldIgnore(root, filename) :
                fullpath = os.path.join(root, filename)
                print('чтение', fullpath)
                with open(fullpath) as file:
                    for line in file:
                        #counter.update(line.split(' '))
                        counter.update(filter(lambda literal: literal, splitToLiteralsReg.split(line)))
    
    index = 0
    for literal, count in counter.most_common():
        index+=1
        print(f'{index}. "{literal}" {count} повторений')

    node js:
    const fs = require('fs')
    const path = require('path')
    
    const PROJECT_DIRECTORY = '.'
    const ignoreName=new Set(['__pycache__', '.git', '.gitignore', 'README.md'])
    const ignoreExt=new Set(['wav', 'jpg', 'png'])
    
    const CURRENT_DIRECTORY = __dirname
    
    const splitToLiteralsReg = /[^a-zA-Zа-яА-Я0-9\_]+/gim
    
    const target_path = path.join(CURRENT_DIRECTORY, PROJECT_DIRECTORY)
    
    function shouldIgnore(root, name){
        if(ignoreName.has(name))
            return true
        if(ignoreExt.has(name.split('.').slice(-1)[0]))
            return true
        return false
    }
    function Counter(){
        this.literals = {}
    }
    Counter.prototype.learnLiteral = function learnLiteral(literal){
        this.literals[literal] = 1 + (this.literals[literal] || 0)
    }
    Counter.prototype.update = function update(iterable){
        for(let curr of iterable)
            this.learnLiteral(curr)
    }
    Counter.prototype.most_common = function most_common(){
        return Object.entries(this.literals).sort((a,b) => b[1] - a[1])
    }
    const counter = new Counter()
    
    function walk(root, callback){
        const content = fs.readdirSync(root).reduce(([dirs, files], name) => {
            (fs.lstatSync(path.join(root,name)).isDirectory() ? dirs : files).push(name)
            return [dirs, files]
        }, [[], []]);
    
        callback(root, ...content) 
            
        for(const dirname of content[0]){
            walk(path.join(root, dirname), callback)
        }
    }
    
    walk(target_path, (root, dirs, files) =>{
        const filtratedDirs = dirs.filter(name => !shouldIgnore(root, name))
        dirs.splice(0)
        dirs.push(...filtratedDirs)
        for(const filename of files){
            if(!shouldIgnore(root, filename)){
                const fullName=path.join(root, filename)
                console.log('чтение' ,fullName)
                const text = fs.readFileSync(fullName, {encoding :'utf-8'})
                
                counter.update(text.split(splitToLiteralsReg))
            }
        }
    })
    
    let index = 0
    for(const [literal, count] of counter.most_common()){
        index++;
        console.log(`${index}. "${literal}" ${count} повторений`)
    }


    Первым писал скрипт на питоне, а на js просто повторил архитектуру питоновского скрипта: получилось странно, но вполне работоспособно
    Ответ написан
    1 комментарий
  • Как в VSCode сделать вывод кириллицы в консоли при работе на питоне?

    @antares4045
    Судя по интерфейсу, вы давно не обновояли vs code: начните с этого.
    Если не поможет посмотите в настройках расширения python, какая консоль является средой выполнения.
    Ответ написан
  • Как запустить react native приложение на ios эмуляторе?

    @antares4045
    Ходят слухи, что проще купить старенький бу айфон, чем заставить корректно работать эмуляторы. Хотя, пока я это печатал, меня посетила идея: можно попробовать развернуть виртуальную машину под macos (при помощи например докера) и запустить эмулятор из под неё, но это в формате теоретической идеи.
    Ответ написан
    1 комментарий
  • Существует ли способ написать мобильное приложение за месяц-два?

    @antares4045
    Ну технически ваше начальство право и подобный подход имел некоторое распространение лет пять назад (точных названий вам не назову, но я уверен гулгл вам в этом поможет мгновенно). -- там насколько я помню довольно широкий выбор инструментария, и если сайт, который вам надо засунуть в телефон у вас уже есть, то вопрос разработки приложения можно уложить и в неделю человеку совершенно не знакомому ни со swift ни android.

    Но также отмечу, что на сегодняшний день стремительно набирают популярность фреймворки ReactNative и Flatter, которые позволяют разрабатывать нативные приложения для мобилок всех платформ пользуясь, абсолютно привычным любому сегодняшнему веб разработчику, jsx синтаксисом. Если у вас есть опыт работы в React, настоятельно рекомендую подумать о таком подходе.
    Ответ написан
    5 комментариев
  • Как вычислить высоту блока перед рендерингом в react?

    @antares4045
    ну jquery с bootstrap как то справляются (они именно вхардкоживают высоту контента, ещё ни разу не отрендерив), но там какая-то чёрная магия.

    Автору могу предложить сделать overflow: hidden контейнер, в который вложен контент: при этом контент будет рендериться, но видно его не будет.
    Плюс навесьте обработчик на изменение размера окна: открываешь аккордион на какой-то одной ширине окна, затем делаешь поуже и ваш код делает вот так:6151807f5540e931269470.png

    UPD: чтобы отвлечься от затыка в работе проверил, достаточно ли того подхода, что я описал: работает

    Если вам влом клонить и билдить также закинул билд на pages

    Хотя некоторая задержка, после которой начинается увеличение высоты контента при сужении страницы меня смущает. но мне, честно говоря влом искать причину.
    Ответ написан
    Комментировать
  • Как сделать разные состояния у объектов useContext?

    @antares4045
    Возможно я вас не так понял, но по всей видимости тут дело не в setState, и useContext тут ничем не поможет: вы пытаетесь в булевой переменнной (которая просто содержит либо "да", либо "нет") данные о том, на какой элемент навёл курсор пользователь.

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

    UPD: набросал код, отвечающий на изначальный вопрос, только контекст в нём реально лишний: достатоно было бы реализовать редюсер в корне и пробрасывать обёртки вокруг него пропсами.
    Ответ написан
  • Как найти ближайшую дату?

    @antares4045
    Если я правильно понял формулировку вопрса, то его можно свести к "найти наименьшую дату из списка, исключая те, что были раньше, чем опорная дата"
    const closestTo = (dateToCompare, datesArray) => {
      const buff = datesArray.filter(date => date >=dateToCompare).sort()
      return buff.length ? buff[0] : undefined
    }
    Ответ написан
    Комментировать
  • Как запланировать действие в python?

    @antares4045
    Вопрос из заголовка: библиотека shedule
    Вопрос из текста вопроса: библиотека Threading+sleep
    По факту, сделайте лучше формулу, которая вычисляет исходя из текущей даты, даты когла вычислялась формула последний раз и значения этой формулы при прошлом расчёте. Сохраняйте дату и прошлое значение и обновляйте, когда поьзователь интересуется. Такой подход сбережет вам куууучу вычислительных ресурсрв
    Ответ написан
    2 комментария
  • Задача на Python. Как найти число?

    @antares4045
    Ваша задача называется бинарный поиск
    def binsearch(min, max, check):
        support = (min + max) // 2
        result = check(support)
        if result == 'меньше':
            return binsearch(support+1, max, check)
        if result == 'больше':
            return binsearch(min, support-1, check)
        return support
    
    def guess(num):
        print('загадано', num)
        def check(req):
            result = 'равно' if req == num else 'меньше' if req < num else 'больше'
            print(f'это {req}?', '-', 'Да' if result=='равно' else f'Нет, твоё число {result}')
            return result
        return check
    
    
    binsearch(0, 100, guess(10))
    print('='*30)
    binsearch(0, 100, guess(27))
    print('='*30)
    binsearch(0, 100, guess(50))
    print('='*30)
    binsearch(0, 100, guess(100))


    загадано 10
    это 50? - Нет, твоё число больше
    это 24? - Нет, твоё число больше
    это 11? - Нет, твоё число больше
    это 5? - Нет, твоё число меньше
    это 8? - Нет, твоё число меньше
    это 9? - Нет, твоё число меньше
    это 10? - Да
    ==============================
    загадано 27
    это 50? - Нет, твоё число больше
    это 24? - Нет, твоё число меньше
    это 37? - Нет, твоё число больше
    это 30? - Нет, твоё число больше
    это 27? - Да
    ==============================
    загадано 50
    это 50? - Да
    ==============================
    загадано 100
    это 50? - Нет, твоё число меньше
    это 75? - Нет, твоё число меньше
    это 88? - Нет, твоё число меньше
    это 94? - Нет, твоё число меньше
    это 97? - Нет, твоё число меньше
    это 99? - Нет, твоё число меньше
    это 100? - Да
    Ответ написан
  • Стоит ли грузить голову алгоритмами и структурами данных?

    @antares4045
    Всё сильно зависит от того, в какой области программирования вы себя видите: фронтендеру врядли всё это понадобится, как и вероятно архитектору БД. В большинстве случаев в современном IT знание о том, как можно реализовать сортировку больше мешает (руки чешутся написать самому, причём почти наверняка выйдет хуже реализации из стандартной библиотеки). И почти всем я отвечаю, что алгоритмы скорее полезно не знать, но их необходимо понимать. И именно из второй половины лично для вас у меня выросло большое "но": не знаю, что именно вы там читали, но из полусотни страниц текста общей тематики профиля, совпадающего с вашим образованием вы поняли, по вашим словам, "ничерта"... это как то пугает, знаете ли.
    Настоятельно рекомендую первым делом сменить автора: малоли на какого фрукта вы напололись. Алоритмы и структуры, помимо просто исторически сложившейся практики, изучают, чтобы просто настроить разум обучающегося на нужный лад: что-бы вы не делали в IT ваша работа сводися к тому, что вы вербализируете свои мысли в строгие и однозначные формулировки -- если чтение признаных авторов (простите вы не назвали свое направление так что конкретных имён не будет) не вызовет ни просветления ни мыслей в ключе "всё и так ясно -- зачем об этом писать?", то... не то что бы у вас не получится, но путь будет полон страданий как ваших так и ваших коллег.

    И настоятельно рекомендую не скатываться в эзотерику по типу SICP и фундаменталистику вроде Кнута: они все по своему прекрасны, но чтобы изучать нужны авторы укладывающиеся в сотни страниц а не тысячи.
    Ответ написан
  • Есть асинхронный модуль для отправки писем на email?

    @antares4045
    Вообще то стандартная питоновская либа просто реализует протокол подключения к POP серверу, так что она способна работать с любой почтой.

    Скорее всего вы просто отправляли письма с неблагонодёжного сервера (или аккаунта).

    по поводу синхронности: существует модуль threading (ну или asyncio (который, не смотря на свою хайповость, ̶р̶а̶б̶о̶т̶а̶е̶т̶ ̶т̶а̶к̶ ̶с̶е̶б̶е̶ мне не нравится))

    настоятельно рекомендую изучить примеры использования threading.Thread для решения вашей проблемы
    Ответ написан
    8 комментариев
  • Как спарсить сайт?

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

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

    Можно также попытаться притвориться гуловским сканирующим ботом (но это в формате идеи).

    А бесплатные анонимизирующие https прокси сервера которые работают а не редиректят тебя на страницу с приглашением купить подписку вообще сродни единорогам по редкости.
    Ответ написан
    Комментировать
  • Почему функция вызывается сама по себе?

    @antares4045
    Функция сама по себе точно не вызывается: вероятно файл, с скриптом подключён и перевызывается на всех страницах проекта.

    Если найти место не получается, можно изменить условие вызова deleteDots на

    slider && dotsSlider
    Ответ написан
  • Как сделать вертикальный липкий слайдер?

    @antares4045
    а телефон это какое разрешение?
    просто я посмотрел: на всех стандартных разрешениях выглядит слегка стремновато, но работоспособно.

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

    @antares4045
    Обычно преобразуют в одномерный список (честно или при помощи абстракции), перемешивают, и восстанавливают размеры.

    Набросал такой перемешиватель:

    import random
    class Shuffler:
        def __init__(self, lst, depth=2):
            self.lst = lst
            self.depth = depth
            random.shuffle(self)
            
        def __getlevel(self, index, depth):
            curr = self.lst
            curr_depth = depth
            while curr_depth > 0:
                curr_depth -= 1
                curr_size = len(curr)
                curr = curr[index % curr_size]
                index //= curr_size
            return curr, index
        
        
        def __getitem__(self, index):
            value, index = self.__getlevel(index, self.depth)
            if index > 0:
                raise IndexError('list index out of range')
            return value
        
        def __setitem__(self, index, value):
            last_line, line_index = self.__getlevel(index, self.depth - 1)
            last_line[line_index] = value
            return value
        
        def __len__(self):
            acc = 1
            curr = self.lst
            curr_depth = self.depth
            while curr_depth > 0:
                curr_depth -= 1
                acc *= len(curr)
                if acc:
                    curr = curr[0]
            return acc
    
    lst = [[i * 10 + j for j in range(10)] for i in range(10)]
    Shuffler(lst, 2)
    print(*lst, sep='\n')

    вывод:

    [45, 50, 74, 1, 3, 29, 43, 2, 93, 68]
    [41, 10, 51, 99, 85, 20, 95, 54, 59, 8]
    [46, 64, 24, 12, 26, 15, 6, 76, 39, 5]
    [58, 13, 44, 60, 36, 70, 63, 79, 42, 18]
    [9, 69, 25, 66, 67, 65, 35, 47, 23, 87]
    [78, 80, 22, 73, 97, 31, 91, 75, 82, 90]
    [57, 38, 49, 11, 84, 17, 62, 7, 89, 71]
    [40, 30, 86, 94, 21, 53, 14, 19, 0, 32]
    [33, 37, 61, 92, 81, 88, 56, 83, 98, 34]
    [96, 16, 52, 4, 27, 55, 48, 72, 77, 28]
    Ответ написан
    Комментировать
  • Как отобразить на карте яндекса нужные организации?

    @antares4045
    Пример:
    https://yandex.ru/dev/maps/jsbox/2.1/
    Полная документация на русском(для вашей задачи (если хитро проксировать) получать api-key не нужно):
    https://yandex.ru/dev/maps/jsapi/doc/2.1/quick-sta...

    p.s. на самом деле, если бы вы вбили в яндекс ваш вопрос, то с высокой вероятностью получили бы ответ
    Ответ написан
    Комментировать
  • Как работает данный код?

    @antares4045
    ну вообще, писавший этот код, вероятно не очень здоров
    для начала предлагаю разобраться с деструктуризацией

    если вы напишите
    a,b = 2,3
    то в переменной a окажется значение 2
    а в переменной b -- значение 3

    это же можно использовать в циклах:
    words = [(0,'What'),(1,'the'),(2,'heck?')]
    for key,word in words:
        print('key:', key)
        print('word:', word)
        print()

    вывод:
    key: 0
    word: What

    key: 1
    word: the

    key: 2
    word: heck?


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

    words = [(0,'What'),(1,'the'),(2,'heck?')]
    
    for _,word in words:
        print(word)


    Но автор вашего примера решил сделать нечто странное:
    {} -- создание пустого dict
    [()] -- присвоение в него по ключу "пустой кортеж" значения

    учитывая, что исходный dict никуда не сохраняется, это можно считать отчисткой, только вот зачем?
    a = {}
    a[()] = 5
    print(a)


    {(): 5}
    Ответ написан
    Комментировать
  • Как сделать так, чтобы бот с кнопками при перезагрузке реагировал на прошлые сообщения?

    @antares4045
    Соглашусь, с ораторами, рекомендующими сменить хостинг, но можно прикрутить бд (ну или просто файл) и сохранять контекст в неё (при помощи например pickle) и при заргрузке соответственно проверять на наличие сохранённого контекста. С ботскими api у меня такой необходимости, признаться, ни разу не возникало -- возможно вылезет какая-нибудь специфика, но при доработке напильником оно точно обязано взлететь.
    Ответ написан
    Комментировать