Ответы пользователя по тегу Python
  • Как ловить статус и от этого выводить результат?

    Vindicar
    @Vindicar
    RTFM!
    Вместо строки возвращай кортеж или словарь. Короче, структуру данных.
    from typing import NamedTuple
    
    class Result(NamedTuple):
        text: str  # текст запроса
        success: bool  # успешен ли запрос
        status: str  # статус
    
    async def check_text(text: str) -> Result:
        url = f'https://сайт.com/?query={text}'
    
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                if response.status != 200:
                    return Result(text=text, success=False, status='Не удалось определить результат')
                html = await response.text()
                soup = BeautifulSoup(html, 'html.parser')
                status_element = soup.find('div', class_='table-block')
                if not status_element:
                    return Result(text=text, success=False, status='Не удалось определить результат')
                status_text = status_element.get_text().strip()
                # тебе нужно будет решить, когда запрос был успешен (True), а когда нет (False)
                if "ok" in status_text:
                    return Result(text=text, success=True, status='Можно')
                elif "no" in status_text:
                    return Result(text=text, success=False, status='Данный вариант недоступен')
                elif "no1" in status_text:
                    return Result(text=text, success=True, status='Можно под заказ')
                else:
                    return Result(text=text, success=False, status='Неизвестно')

    Тогда можно будет анализировать результат просто:
    result = await check_text(text)
    if result.success:
        ...  # реагируем на успешный запрос
        logger.info('%s: %s', result.text, result.status)
    else:
        ...  # реагируем на неудачный запрос
        logger.info('%s: %s', result.text, result.status)
    Ответ написан
  • Почему происходит «Сайт XXX выполнил переадресацию слишком много раз» и как исправить ошибку «the STRING opcode argument must be quote»?

    Vindicar
    @Vindicar
    RTFM!
    ganstar565, внезапно, зависит от браузера. Например, гугл "firefox cookie storage format" даёт такой ответ:
    Cookies in Firefox are stored in an SQLite format database found in the file cookies.sqlite in the currently-active user profile directory (exact path is system-dependent).

    Иными словами, смотришь папку %APPDATA%\Mozilla\Firefox\Profiles, в ней каждый подкаталог - профиль браузера, часто один, но может быть несколько. Внутри подкаталога лежит файл cookies.sqlite.
    Путь можно сконструировать с помощью os.path.expandvars() (и модуля os.path в целом), файл открыть стандартным модулем sqlite3, а дальше смотри что внутри таблицы moz_cookies.
    Для остальных браузеров по аналогии - гугл, потом эксперименты.
    Ответ написан
    9 комментариев
  • Как исправить ошибку чтения аргумента?

    Vindicar
    @Vindicar
    RTFM!
    __getattribute__() вызывается ДО проверки содержимого __dict__. В большинстве случаев нужен __getattr__().
    А вообще, что ты пытаешься сделать?
    Ответ написан
    3 комментария
  • Можно ли оптимизировать этот код?

    Vindicar
    @Vindicar
    RTFM!
    Можно, если сделать допущение, что текст кодируется посимвольно, а не группами из N символов.
    open_text = 'текст'  # открытый текст
    
    # letters - именно строка, одна позиция - один символ
    letters = ''.join(['а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф',
           'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я'])
    key = 5  # ключ к шифру - величина сдвига. Может быть >0 или <0
    # генерируем таблицы подстановки
    encrypt_table = str.maketrans(letters, letters[key:]+letters[:key])  # для шифрования
    decrypt_table = str.maketrans(letters, letters[-key:]+letters[:-key])  # для дешифрования
    
    cypher_text = open_text.translate(encrypt_table)
    restored_text = cypher_text.translate(decrypt_table)
    
    print(open_text)
    print(cypher_text)
    print(restored_text)
    Ответ написан
    Комментировать
  • Как получить url страницы и какие есть способы изменять html код через python?

    Vindicar
    @Vindicar
    RTFM!
    Ты упускаешь из виду, что современные страницы часто набиты скриптами, да и банальную необходимость авторизации на сайте. Иными словами, если ты через requests запросишь тот же URL, далеко не факт что ты получишь ту же самую страницу. Тут нужно само содержимое страницы вытаскивать. А оно может быть большое, так что лучше уж выбранный текст.
    Это проще всего сделать через браузерное расширение. Альтернатива - добавить окошко/иконку на панель задач/в трей, куда можно будет перетащить выделенный текст.
    Ответ написан
    Комментировать
  • Правильная и красивая замена if?

    Vindicar
    @Vindicar
    RTFM!
    В комментариях уже написали простое решение, а я его чуток разовью.

    import typing as tp
    
    Func = tp.Callable[[], None]  # функция без апарметров, возвращает None
    
    class FuncMap:
      def __init__(self):
        self.map: tp.Dict[str, Func] = dict()
    
      def register(self, key: str) -> tp.Callable[[Func], Func]:
        def decorate(f: Func) -> Func:
          self.map[key] = f
          return f
        return decorate
      
      def get(self, key: str) -> Func:
        return self.map[key]
      
      def run(self, key: str):
        return self.map[key]()
    
    # а вот так этот класс используется
    fmap = FuncMap()
    
    @fmap.register('11')
    def test():
      print('This is test()')
    
    fmap.run('11')
    Ответ написан
    2 комментария
  • Возможно ли закрыть файл.ini на python?

    Vindicar
    @Vindicar
    RTFM!
    Откуда у тебя приходит переменная config? Где она ещё используется?
    read() будет дочитывать данные в текущее состояние конфига, не сбрасывая его в ноль перед чтением.
    Не экономь, создавай отдельный экземпляр парсера на каждый файл.

    Ну и да, база данных в ini? Лучше не надо. sqlite не настолько сложен.
    Ответ написан
    Комментировать
  • Почему он выдает interrupt exception, который не ловится?

    Vindicar
    @Vindicar
    RTFM!
    Потому что вызов thread.start() который внутри start_listen() - не блокирующий. Главный поток продолжит работу, выйдет из try-except и завершится, так что на момент возникновения KeyboardInterrupt он уже будет завершён. Твой поток не помечен как daemon, поэтому интерпретатор продолжит работу (был бы помечен - программа бы завершилась тут же).
    Если ты делаешь join() - то пока запущенный поток не закончится, главный не продолжит работу.

    Собственно, в текущем виде тебе поток вообще не нужен, у тебя главный поток ничего не делает и так, и так.
    Что ты пытаешься сделать?
    Ответ написан
    Комментировать
  • Как получить какой-нибудь хеш от значения переменной (dict)?

    Vindicar
    @Vindicar
    RTFM!
    Очевидно, надо в каждом словаре найти значение, которое уникально идентифицирует соединение.
    Я бы сказал, это пара IP:порт удаленного узла (с которым установлено соединение).
    Не уверен, будет ли эта информация в словаре, так как ты не озаботился привести пример, и как это будет работать с UDP (где формальных соединений нет), но попытаться можно.
    Ответ написан
  • При команде `!mine` алмазы 0, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    Рекомендую выучить язык, прежде чем писать ботов.
    Посмотри на свой код (выделено мной):

    elif user_data[5] == '<:939223290105454632:1164940159050059786>':
    ...
    elif user_data[5] == '<:939195860317773856:1164153649296048148>':
    ...
    elif user_data[5] == '<:939223290105454632:1164940159050059786>': # Добавлено условие для железной кирки
    ...

    У тебя уже есть условие для железной кирки. Оно отработает первым, и в дальнейшие ветки elif управление просто не перейдёт. Более простой пример, иллюстрирующий твою ошибку:
    x = 1
    
    if x == 0:
      print('Ноль!')
    elif x == 1:
      print('Один!')
    elif x == 2:
      print('Два!')
    elif x == 1:
      print('Раз!')

    Код выведет "Один!" а не "Раз!".
    Единственный способ добиться нужного поведения - исправить уже существующую ветку.
    x = 1
    
    if x == 0:
      print('Ноль!')
    elif x == 1:
      print('Раз!')
    elif x == 2:
      print('Два!')


    В коде вообще много спорных решений, но про них лучше отдельно поговорить.
    Ответ написан
    1 комментарий
  • Постоянно вылазит ошибка NoneType:None в чём дело?

    Vindicar
    @Vindicar
    RTFM!
    А что, по твоему, ты пытаешься сделать?
    Эта функция выводит информацию о текущем обрабатываемом исключении. А у тебя в коде исключения не выбрасываются.
    По факту, эту функцию имеет смысл использовать только когда обрабатываешь исключение, т.е. внутри блока except.
    Ответ написан
    Комментировать
  • Как описать функцию python в одном файле, а выполнить в другой?

    Vindicar
    @Vindicar
    RTFM!
    Импортируй файл MAIN до f().

    Вообще, если я верно понял ситуацию, у тебя циклическая зависимость.
    Это надо разруливать иначе.
    Например, пусть f() получает ссылку на f_from_main_file как параметр.
    Или, возможно, у тебя вообще неправильно распределены обязанности, и часть f_rom_main_file() на самом деле должна быть там же, где f().
    Ответ написан
  • Как мониторить изменение файла?

    Vindicar
    @Vindicar
    RTFM!
    Читаем документацию:
    schedule(event_handler, path, recursive=False)
    Schedules watching a path and calls appropriate methods specified in the given event handler in response to file system events.
    Parameters:
    event_handler (watchdog.events.FileSystemEventHandler or a subclass) – An event handler instance that has appropriate event handling methods which will be called by the observer in response to file system events.
    path (str) – Directory path that will be monitored.
    recursive (bool) – True if events will be emitted for sub-directories traversed recursively; False otherwise.

    Returns:
    An ObservedWatch object instance representing a watch.

    Прямо говорится что должен быть путь к каталогу.
    Просто проверяй каталог файла, указав recursive=False, а в обработчике фильтруй по имени. Только имей ввиду, что имя может иметь другой вид. Например, если я мониторю "." (текущий каталог), то имя мне приходит вида ".\test.txt". Так что pathlib в помощь, чтобы вытащть из имени нужную часть.
    Ответ написан
  • Как исправить ошибку с file.tell()?

    Vindicar
    @Vindicar
    RTFM!
    Ну раз проблема в цикле for, то вместо for line in data: делай цикл вручную, например так:
    while True:
        line = data.readline()
        if not line:
            break
        ...  # тут выполняем дальнейшие операции

    Этот код полагается на тот факт, что чтение в конце файла вернёт пустую строку (а "пустая" строка в середине файла всё равно будет иметь хотя бы один символ - символ перевода строки).
    Ответ написан
    Комментировать
  • Как параметр в лямбде соотносится с параметром в функции?

    Vindicar
    @Vindicar
    RTFM!
    Программа доходит до строки print(mydoubler(11)). Чтобы напечать результат выполнения функции mydoubler, программа вызывает эту функцию с аргументом 11, для этого программа идёт к строке mydoubler = myfunc(2).

    Ну вот тут ты уже неправ. Программа не идёт назад по коду.

    Сначала отрабатывает оператор def, определяющий функцию myfunc. После этого в текущей области видимости программы появляется переменная myfunc, хранящая ссылку на объект-функцию.
    Затем отрабатывает строка mydoubler = myfunc(2). Происходит вызов функции myfunc, при этом ей передаётся объект-число 2 как параметр. Внутри локальной области видимости myfunc теперь есть имя a, ссылающееся на объект-число 2. В ходе выполнения создаётся лямбда-функция, которая ссылается на этот параметр.
    Лямбда функция возвращается из myfunc, myfunc завершает выполнение. Поскольку лямбда-функция продолжает существовать (мы её вернули), а она ссылается на объект-число 2, то этот объект тоже продолжает существовать.
    Возвращённая функция присваивается имени mydoubler в текущей области видимости. Это позволяет её продолжать существовать (её не собирает сборщик мусора), ну и позволяет её вызвать по этому имени.

    Если бы ты сделал ещё один вызов, скажем, mytripler = myfunc(3), это бы создало новую, отдельную лямбда-функцию, совершенно независимую от mydoubler, и ссылающуюся на объект-число 3.
    Ответ написан
    1 комментарий
  • В чем может быть ошибка?

    Vindicar
    @Vindicar
    RTFM!
    Указанная тобой библиотека использует другой плейсхолдер для указания значений параметров - не ? а %s.
    Смотри пример в документации.
    Ответ написан
    Комментировать
  • Как запустить скрипт на Python с использованием сторонних библиотек?

    Vindicar
    @Vindicar
    RTFM!
    Запускай, используя python.exe из виртуального окружения.
    Ответ написан
  • Как заставить питон преобразовать значения столбца к формату?

    Vindicar
    @Vindicar
    RTFM!
    Ну т.е. у тебя два формата, по сути. Первый A-B/C/DE, где A - одна цифра, B - 4 цифры, C - 2 или 3 цифры, D - от 0 до 2 цифр, E - 2 цифры. Тебе нужно извлечь две части: A-B/C и E, и использовать их как ключ. В виде регулярки это будет что-то типа (\d-\d{4}/\d{2,3}/)\d{0,2}(\d{2}). Пример:
    import re
    r = re.compile(r'(\d-\d{4}/\d{2,3}/)\d{0,2}(\d{2})')
    m = r.match("1-2345/678/0099")
    print(m.groups())  # выведет ('1-2345/678/', '99')

    Для второго формата всё ещё проще, там будет 9 цифр подряд: (\d{9})
    import re
    r = re.compile(r'(\d{9})')
    m = r.match("123456789")
    print(m.groups())  # выведет ('123456789', )

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

    Vindicar
    @Vindicar
    RTFM!
    Советую не пытаться удалять гланды через противоположный конец тела. А именно:
    Вместо того, чтобы пытаться вызвать обработчик команды, и биться об стенку, пытаясь имитировать всё необходимое окружение, следует просто вынести непосредственно операцию поиска в ОТДЕЛЬНУЮ функцию.
    Собственно, в твоём случае было бы норм и просто вызвать
    search_results = googlesearch.search(query, num_results=3)
    внутри ask(), и обработать полученные результаты - невелико повторение. Я бы сделал именно так.

    Если прям очень хочется сделать общий код для двух команд, вынеси в отдельную функцию и вывод:
    # Messageable - это что-то, чему можно послать текстовое сообщение. Это может быть канал, пользователь, контекст команды...
    async def search_and_reply(query: str, ctx: discord.abc.Messageable) -> None:
        try:
            search_results = googlesearch.search(query, num_results=3) 
            if search_results:
                await ctx.send("Результаты поиска в Google:")
                for result in search_results:
                    await ctx.send(result)
            else:
                await ctx.send("Ничего не найдено.")
        except Exception as e:
            await ctx.send(f"Произошла ошибка при выполнении поиска: {str(e)}")

    И тогда у тебя будет всё проще: search() будет состоять из одного вызова await search_and_reply(query, ctx), но будет брать на себя регистрацию как обработчика команды, проверку ролей и кулдаунов, и прочую мишуру, которой не место внутри search_and_reply(). Тогда ask() может просто сделать аналогичный вызов await search_and_reply(query, channel) в нужный момент, не беспокоясь о специфике дискорд-обработчика, так как search_and_reply() таковым не является.
    Ответ написан
    Комментировать