Ответы пользователя по тегу Python
  • При попытке проверки переменной выдаёт ошибку, что делать?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вам же белым по черному в тексте ошибки написано, что переменная country используется до объявления. То есть в программе вы еще ни разу в нее ничего не присвоили, а уже пытаетесь проверять ее значение. КОнечно тут ошибка.
    Там даже показано в какой именно строке. Что делать? Исправлять.
    Ответ написан
    Комментировать
  • Где ошибка в коде?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    замените
    c = Canvas(window, width=WIDTH, height=HEIGHT, bg="darkblue").pack()

    на
    c = Canvas(window, width=WIDTH, height=HEIGHT, bg="darkblue")
    с.pack()

    Иначе в переменную c попадает результат выполнения метода .pack(), который None, а не ожидаемый вами экземпляр канваса
    Ответ написан
    Комментировать
  • Почему поверхностная копия не изменяет значение?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    всё как и долно быть.
    В С-подобных языках программирования переменная - это, как бы, ящичек с именем. Вы в ящичек можете положить значение, а при присвоении в ящик кладётся другое значение, а старое значение уже с этим ящиком не будет ассоциировано. Один ящик - одно значение.

    В Питоне переменная - это как ярлычок с именем. При присвоении вы, как бы, вешаете ярлычок на объект:
    x = [1,2,3]
    y=x
    И у вас теперь есть два ярлычка: x и y. Оба привязаны к одному и тому же объекту.
    Если вы этот объект измените (отредактируете элемент), то не важно как вы к нему будете обращаться, по какому из имён.

    Нужно различать что вы меняете: вы либо перевешиваете ярлычок с именем на друго объект, либо меняете что-то внутри объекта, к которому привязан ярлычок. Чувствуете разницу?

    Представьте, что в вашем объекте (Заявка) два атрибута: Имя_клиента и Адрес_квартиры.
    Вы копируете заявку поверхностно. Меняете имя в одной из копий, а во второй всё осталось как было. Делаете ремонт в квартире по указанному адресу. Само собой алрес в обеих копиях заявки один итот же и вы его не меняели. Вы меняели объект по этому адресу.

    Теперь вы берете заявку и делаете её глубокое копирование:
    Тут начинается проблема у аналогии, но это нам не помешает.
    Вы меняете имя в копии и тут всё работает как в прошлом примере.
    Но при создании глубокой копии создалась новая абсолютно такая же квартира но с новым адресом. В копии заявки адрес уже другой. Если вы сделаете ремонт в квартире по новому или старому адресу, то на другой квартире это не отразится.
    Ответ написан
    Комментировать
  • Как перехватить ошибку ConnectionRefusedError: [WinError 10061]?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    try:
        # ... код, порождающий ошибку
    except ConnectionRefusedError as e:
        # код обработки ошибки
    Ответ написан
    Комментировать
  • В чём разница между list() и []?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Там всё просто.
    Считайте, что list - это функция, которая принимает перечисляемый объект и возвращает список с извлеченными из этого объекта элементами.
    [], [1,2,3] - это "синтаксический сахар" для удобной записи готовых списков в коде. Первый из этих двух примеров пустой, а второй содержит три элемента. Эта запись подразумевает, что элементами будут выражения, записанные в квадратных скобках через запятую.

    Так что list() и [] действительно вернут одинаковый результат, но если речь не о пустых списках, то функция извлечет элементы из своего аргумента, а [1,2,3] примет в качестве элементов то, что внутри через запяту.

    Прочитайте лучше систематически в книжке того же Лутца. Иначе вы своими догадками ни язык нормально не освоите, ни время не сэкономите.
    Ответ написан
    3 комментария
  • Как найти и удалить плагин SQLScout в Pycharm?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Так я и не понял, решили вы проблему для себя или нет?

    Нужно найти каталоги вида:
    %HOMEPATH%\\.<product><version>\config\plugins
    Показать здесь их содержимое.
    Указать версию всех продуктов JetBrains, установленных в системе.
    Удалить все следы проблемного плагина.
    Ответ написан
    1 комментарий
  • [Python] Как сделать передвижение строки?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Могу предложить для ясности вот такое решение:
    import sys 
    from time import sleep 
    
    def cut_frame(s: str, start_pos: int = 0, frame_size: int = None) -> str: 
        frame_size = frame_size or len(s)
        left_space = ' ' * min(start_pos, frame_size) 
        if start_pos < 0: 
            s = s[-start_pos:] 
        return f'{(left_space + s)[:frame_size]:{frame_size}}' 
    
    
    def scroll(s: str, frame_size: int = None, timeout: float = 0.1, template: str = '[{}]', file=sys.stdout): 
        frame_size = frame_size or min(len(s), 80) 
        for i in range(-len(s), frame_size + 1)[::-1]: 
            substring = template.format(cut_frame(s, i, frame_size)) 
            print(substring, end='\033[0G', flush=True, file=file) 
            sleep(timeout)

    В виндовом терминале не пробовал, но если ANSI-последовательности поддерживаются, то должно скроллиться как положено.
    Ответ написан
  • Изучение Python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    https://otus.ru/
    На любой вкус вообще.
    Ответ написан
    Комментировать
  • Python как перебрать значение по ключу в список?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вот так, например.

    from itertools import groupby
    
    [
        dict(
            name=name, 
            id=id, 
            pos=[subitem['pos'] for subitem in subitems]
        ) 
        for (name, id), subitems in 
        groupby(
            dic, 
            lambda item: (item['name'], item['id'])
        )
    ]

    Только у вас там, похоже, ошибка в примере для случаев с одиночными вхождениями. Не хватает двойного вложенного списка.
    Если нужно именно так, то нужно будет добавить "раздевание" одноэлементных списков.

    Не забудьте предварительную сортировку, если группируемые элементы могут быть не рядом.
    Ответ написан
    Комментировать
  • Как получить человекопонятные символы в кодировке UTF-8?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Продам участок - 35

    это выглядит, будто вы смотрите на utf-8 через неправильно настроенный просмотрщик, который пытается читать текст, будто он в 1251 кодировке.

    Давайте объясню. Unicode - это не кодировка, это просто номенклатура большого количества самых разных символов. Этих символов сильно больше чем 256, а именно столько (256) значений может быть записано одним байтом.
    Напомню. что у нас в компьютерах всё хранится в виде байтов и их последовательностей. Но один байт - это слишком мало для вычислений, поэтому их объединияли в "слова". Короче сперва регистры в процессоре были 2 байта (16 бит), потом 4 байта (32 бит), сейчас повсеместно завоёвывает позиции 64-битная архитектура. Грубо говоря это значит, что одной операцией процессор обрабатывает вот эти вот 4 или 8 байт. Но в каком порядке идут эти байты в такой группе? Вот тут тоже есть разница на разных платформах и там вообще мрак. Но как-то с этим живем.

    Итак, нужно байтами записывать символы, которых очень много. Надо, чтобы эти байты можно было передать по сети другому компьютеру, возможно с другой архитектурой и другим порядком байт в "слове". Многим не нужны вообще все символы. Кому-то хватает только английских букв/цифр и некоторых знаков -- такой набор не превышает числом 128 символов (ASCII кодировка).
    Что такое кодировка? Это способ задать одним или несколькими байтами конкретный символ. У кодировок разные наборы этих символов. Текст - это последовательность символов. В конкретной кодировке он задаётся последовательностью байт. Чтобы прочитать текст, нужно знать в какой он кодировке, брать байты (зная кодировку мы понимаем какие символы им соответствуют) и рисовать символы.

    Исторически сложилось, что в windows в русской локали используется сразу две разных однобайтовых кодировки: cp1251 и cp866. Первая половина из 256 символов в них одинаковая, как в ASCII, а во второй русские буквы на совершенно разных местах стоят. Текст из одной кодировки в другую перевести можно однозначно, но нужно менять номера по специальной таблице.

    А потом люди захотели очень разных символов, всякие иероглифы и пиктограммы. Это всё не поместится в байт и появились много байтовые кодировки. ASCII-символы там кодируются одним байтом, часто употребимые двумя, тремя, редкие, могут потребовать и больше байт. Есть сложный алгоритм, который говорит как превратить Юникод-символ с номером таким-то в набор байтов. Для каждой кодировки этот алгоритм свой. Для однобайтовых кодировок он сильно проще.

    Регулярно чередующиеся символы в вашей строке примера - это те самые вторые байты символов. Заметьте, что ascii-символы представлены однобайтово. Это utf-8, на которую смотрят как на 1251 или какую-то другую однобайтовую кодировку.
    То есть пытаются представить каждый байт в виде отдельного символа.

    В итоге.
    У вас есть файл в UTF-8. Открывайте его правильным редактором с правильными настройками и будет у вас всё видно правильно. Либо кодируйте в cp1251 файл при записи, тогда таким образом он у вас откроется читабельно.
    Ответ написан
  • Как сделать, чтобы при записи в csv файл числа были числовыми, а не датами?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вы самое главное упустили. В виде дат эти строки выглядят в экселе, а CSV тут ни при чем. Это простой текстовый формат и в нем нельзя указать тип данных ячейки.
    Вам в соседнем ответе уже порекомендовали настроить тип данных ячеек в экселе. Это именно его, экселевская, проблема. Слишком "умный".

    Однако есть и своеобразный лайфхак. Чтобы десятичные дробные числа не воспринимались экселем как даты, можно сделать их на даты непохожими. Сделать это можно дописав справа в дробной части нули. Можно даже потоковый конвертер сделать, который будет все дробные числа форматировать нулями до, скажем, шести знаков после запятой. Это незначащие нули и на числовые данные они не повлияют, зато эксель не будет их датой показывать.

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

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Нифига. Никак тут не продолжить снаружи. Итальянец писал код - не иначе. Спагетти явно с сыром.
    Но у вас есть возможность форкнуть и отрефакторить этот парсер, хотя лучше бы взяли просто другой хороший, пусть не из стандартной библиотеки.

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

    О, ну и ещё одна идея на грани фола. Попробуйте _strict перекрыть свойством, а на геттер инициировать ворнинг. Правда вы так не узнаете на каком именно дубле проблема. А ещё, чтобы не путаться на случай нерелевантных обращений _strinct, можно включать режим ворнингов и выключать до и после перекрытого метода. Такой себе грязный хак основанный на побочных эффектах.

    Можно пофиксить _strict параметр и ошибка не будет инициироваться, но вы останетесь без ворнинга.
    Ответ написан
    5 комментариев
  • Как сделать, чтобы при выводе в консоль новой строки, она моментально записывалась в csv?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Это можно (и правильнее) делать снаружи:
    ./my_script.py | tee the.csv
    Так вы получите весь выхлоп и в терминал и в файл.

    Но можно и по-другому. например сделать свой кастомный print:
    with open('the.csv', 'w') as f:
        def my_print(s):
            print(s)
            print(s, file=f)
            f.flush()
        
        for i in range(1000):
            my_print(i)
            time.sleep(12)

    Можно сделать свой класс, поддерживающий протокол записи (write) и в конструктор получающий набор потоков ввода/вывода, в которые будет писать.
    class IOFork:
        def __init__(self, *streams, flush=True):
            self.streams = streams
            self._flush = flush
    
        def write(self, s: str):
            for stream in self.streams:
                stream.write(s)
                if self._flush:
                    stream.flush()
    # ...
    import sys 
    import time 
    with open('the.csv', 'w') as f:
         io = IOFork(f, sys.stderr) 
         for i in range(100): 
             print(i, file=io) 
             time.sleep(1)

    Вы можете убедиться, что всё пишется вовремя, если в соседнем терминале будете подслушивать выходной файл:
    tail -F the.csv
    Ответ написан
  • Как игнорировать пользователя?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    По приходу сообщения проверяйте не замучен ли пользователь. Если-таки да, то пусть бот не обращает на него внимания.
    Или в чем вопрос? Вы его как-то невнятно описали.
    Ответ написан
  • Как реализовать копирование файлов с одинаковыми именами под разными именами, а не перезаписывать созданный файл при нахождении одноимённого файла?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Есть несколько простых правил:

    0. Следите за отступами и форматируйте код правильно.
    Для питона это самое главное правило. Вы некорректно наставили тегов для оборачивания кода, я вам лишние убрал, но ваши отступы в коде поломаны. К этому нужно относиться внимательно.
    Помните, что помимо пробелов бывают табуляции. Табуляция - это один широкий символ, но его ширина нигде не регламентирована, а питон по количеству пустых символов вначале строки понимает её вложенность в коде. Само собой смешение табуляций и пробелов в питоновском коде ведёт к страшной неразберихе и гарантированным ошибкам. Холивару "пробелы против табов" не одна сотня человеко-лет, но есть общее правило, зафиксированное в PEP: используйте 4 пробела в качестве одного отступа. Всегда. Без исключений.

    1. Не используйте скобки там, где они не нужны:
    disk = ('C:\\')
    filen1 = (f'{root}' + str('\\') + f'{name}')

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

    1. Не конкатенируйте пути вручную, как вы это делаете здесь:
    f'{root}' + str('\\') + f'{name}'
    Приведение строки к строке бессмысленно. Могли бы просто написать так: f'{root}\\{name}', но и это плохая идея, потому что нельзя конкатенировать пути вручную. В разных операционных системах используются разные символы-разделители в путях. В питоне для работы с путями есть модули: os.path (древний как навоз мамонта) и pathlib (новый, объектный, очень удобный).

    2. Используйте pathlib для работы с путями.
    Изучите эту библиотеку. Вы откроете для себя массу полезных вещей.

    3. Используйте оператор with при работе с закрываемыми ресурсами.
    Ваш код:
    file1 = open(filen1, 'rb')
    file2 = open(filen2, 'wb')
    file2.write(file1.read())
    file1.close()
    file2.close()

    Станет таким:
    with open(filen1, 'rb') as file1, open(filen2, 'wb') as file2:
        file2.write(file1.read())

    А с использованием pathlib ещё лаконичнее:
    directory = Path('path/to/my/dir')
    fn1 = directory / 'file1.jpg'
    fn2 = directory / 'file2.jpg'
    file2.write_bytes(file1.read_bytes())

    Слеши расставятся в правильную сторону сами, как это нужно системе, вам никогда больше об этом не придётся задумываться. Не придётся думать об экранировании слешей, как это сделано у вас в путях. В библиотеке перекрыт оператор деления, через него удобно собирать путь.
    А ещё там полно всяких удобностей вроде проверки наличия файла, создания каталогов, удаления...

    4. Не смешивайте работу с каталогами и с файлами:
    if name in dirs or name in files:
    В каких-то случаях, возможно, и есть сходства, ведь в файловой системе каталог - это тоже файл. Но вы не сможете его ни прочитать, как таковой ни записать. По логике вашей программы получается, что, если есть каталог с таким именем и расширением, то вы его будете тоже пытаться читать. на этом ваш код и упадёт.
    В pathlib, кстати, есть отличный метод rglob, который рекурсивно итерируется по всем путям, соответствующим маске. Сделать это можно относительно любого каталога:
    files = Path('c:').rglob('*.jpg')
    найдёт все jpeg-картинки на вашем диске c:.
    При этом вы получите объект, по которому можно итерироваться циклом или превратить его в список. Элементы такой последовательности будут тоже типа pathlib.Path.

    5. Для решения любой задачи разбейте ее на элементарные части и решайте их по отдельности.
    В данном случае логично написать отдельную функцию безопасного копирования одного файла. Эта функция должна проверить есть ли целевое имя файла (если нет, то копирует), какого размера там файл (если такого-же до байта, то нужно проверить хеш и отказаться от копирования при совпадении, если другого, то нужно менять целевое имя или путь). С помощью pathlib можно подставлять расширение и быстро получить все файлы по маске в каталоге. Это позволит, например, быстро понять какой самый последний файл с именем вида 'file_name_00023.jpg' по маске 'file_name_*****.jpg', достать его цифровой хвостик, превратить в целое число, прибавить единицу и снова подставить в имя: Path('file_name_{last_index+1:05}.jpg').

    6. Подозреваю вы хотите написать безопасную дедупликацию картинок.
    • Прочитайте про хеш-функции и как они могут помочь сказать наверняка одинаковы ли два файла.
    • Прочитайте про символические ссылки. Это как ярлыки, но на уровне файловой системы и с файлами можно работать точно так же как с оригиналами. Такие ссылки позволят не копировать и не дублировать данные, когда требуется лишь как-то альтернативно сгруппировать их по каталогам.
    • Прочитайте про жесткие ссылки. Это выглядит как несколько имён одного файла в произвольных каталогах. Если хоть одно имя останется не удалённым, то и файл на диске будет. Данные хранятся один раз, а лежит файл как бы сразу в нескольких местах и нет никакого приоритета между ними.
    • Подумайте о журналировании. Иногда правильнее вместо реальных операций с файловой системой написать подробный журнал того, что вы хотите сделать в ней, а затем, по окончании опасного длительного процесса сборки этого журнала, можно утвердить и согласовать действия с пользователем, проанализировать список предстоящих операций и выполнить уже их спокойно или отказаться от них.
    Ответ написан
    1 комментарий
  • Как пользоваться методами в vk_api на python-e?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    А я не понимаю что вы не понимаете. И вашим коротким текстом вы не объяснили сути вопроса. Но даже не понимая сути вопроса и никогда не пользовавшись этим API я вот иду и пишу в гугле "vk-api python" и самой первой ссылкой получаю репозиторий на гитхабе.
    На главной странице проекта в ридми ссылка с примерами. Ну невозможно не увидеть.

    Я не понимаю, что вам не понятно. Где в моих действиях было что-то не очевидное? Как вообще отвечать на ваш вопрос?!
    Ответ написан
    4 комментария
  • В каком направлении двигаться для написания не сверх сложных ботов?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Судя по вопросу вам надо сперва хотя бы основы программирования освоить. на чем угодно, это не важно. И в совокупности это будет в разы сложнее и дороже по человекочасам, чем заплатить фрилансеру.
    Ответ написан
    9 комментариев
  • Реально ли работать на питоне не понимая сути декораторов?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    В общем пытаюсь учить питон и не могу никак понять суть декораторов.

    Всё зависит от того, насколько давно вы уже пытаетесь их понять и всё никак.
    Если покумекав пару минут уже отчаялись, то наверно программирование - не ваша стезя.
    Если прочитав пару статей не смогли разобраться, то, может быть, следует сделать еще одну попытку. Или вы считаете, что это прям рокет сайнс и раз уж с первого подхода не осилили, то это уж на всю жизнь теперь "работать без декораторов". Судьба.

    Вообще меня удивляет такой фатализм. Ну не понял ты что-то, так разбирайся, а не беги выяснять можно ли без этого прожить всю жизнь. Декораторы - это очень простая концепция.
    Если ты не способен её понять, то программировать профессионально не сможешь - это факт.

    И нет, на декораторах свет клином не сошелся. Нужно понимать что в питоне функция - это объект первого рода и что это значит.
    Нужно понимать, что такое "замыкание" в контексте функционального программирования.
    Более того, нужно понимать что такое дескрипторы, как работают мета-классы и много-много всего такого.

    Нет, с этими знаниями не рождаются, их нужно осваивать.

    Декораторы - это очень простая концепция.
    Декоратор - это функция, которая принимает в качестве единственного аргумента какую-то функцию. Декоратор что-то делает с этой функцией (где-то регистрирует ее, документирует, оборачивает её вызов в другую функию) и возвращает её изменённую или другую функцию-обёртку.

    Что конкретно вам не понятно?

    Надо заметить, что Декоратор как паттерн проектирования имеет боле еширокий смысл. Декорировать можно объекты, классы, функции, даже модули (постольку, поскольку это тоже объекты). Учиться вам надо, сударь, и не ожидать, что всё прошьётся в мозг мгновенно. Быть программистом - это всегда учиться. Не останавливаясь.

    Примеров декораторов огромное множество: самые простые и понятные - это:
    - замер времени выполнения функции
    - кэширование результата
    - подстановка части аргументов (partial)
    Ответ написан
    4 комментария
  • Как обрезать фото человека с определнной точки(я хочу взять глаз человека и вокруг него обрезать), что читать?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Думаю надо использовать искуственный интелект да?

    Сначала нужно использовать естественный.
    Потом погуглить 2 минутки и вуаля
    Ответ написан
    Комментировать
  • Как в pandas посчитать только новые данные, а не всю таблицу?

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

    Второй вариант - это реализовать свою оконную функцию, грубо говоря это будет объект с состоянием, куда построчно заталкиваются и соответственно извлекаются данные. Объект внутри хранит оконный буфер, но считает всё сам, без панды и выщёлкивает из буфера ненужные строки.
    Ответ написан