• Пишем веб сервис на Python с помощью FastAPI
    +1

    Автор FastAPI уже этим занимается. :)
    Остается пожелать ему удачи и терпения.

  • Хранение изображений с помощью Django/Django REST
    0
    позволяет использовать функцию для определения пути

    Тут тоже есть свои неудобства, которые описаны в упоминаемой вами документации.


    instance — In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.

    То есть, на момент вызова функции переданной в upload_to, instance еще не будет сохранен в базу, а значит, id у него будет равен None.


    На SO есть несколько решений этой проблемы особенности, надеюсь, другие джангисты поделятся популярным самым решением.

  • Как проверить навыки программирования на Python? Задачи от Яндекса
    0
    Кодирование длин серий
    Были участники, которые решили задачу с помощью регулярных выражений.

    И правильно сделали, как мне кажется.


    Сильно уж они все упрощают
    import re
    
    def decoded_rle_value_len(value):
        pairs = re.findall(r'(?P<letter>[A-Z])(?P<count>\d*)', value)
        return sum(int(pair[1]) if pair[1] else 1 for pair in pairs)
    
    result = decoded_rle_value_len('A15BA5')
    print(result)

    С другой стороны, решение в статье более прямолинейное и его, возможно, проще осмыслить.

  • Как проверить навыки программирования на Python? Задачи от Яндекса
    0

    Вот это решает проблему:


    from collections import Counter
    from operator import itemgetter
    
    a = [0, 0, 10, 10]
    counter = Counter(a)
    result = max(counter.items(), key=itemgetter(1, 0))[0]
    print(result)

    Но оказалось, что решение в посте работает прилично быстрее.

  • Конфигурационные файлы в Python
    +3

    Пользуюсь dynaconf
    Умеет в большинство популярных форматов, есть интеграции с Джангой и Флаской, умеет в Vault.

  • Быстрее, чем C++; медленнее, чем PHP
    0

    Подобные "упрощения" не очень то и упрощают чтение кода. :)

  • Быстрее, чем C++; медленнее, чем PHP
    +2

    Круто, что даже без использования numpy при помощи numba можно прилично ускорить работу программы.


    Например, если на код автора просто навесить декоратор @jit — программа отработает за 2.528 на моем железе.


    Если убрать isinstance — уже будет 1.7.


    Что не может не радовать. :)


    Все-таки, если уже считаем в Питоне, то берем для этого инструменты, которые для него придумали.

  • Пишу на C#, чтобы фронтендерам было полегче
    +2

    Если бы проблема была и для Windows — было бы куда больше шума, мне кажется.
    Попробовал у себя: Windows 7, Pycharm 2019.3, русская раскладка. Хоткеи из тикета работают точно так же, как и на английской раскладке.

  • Сложность простоты
    +3

    Перенес C# реализацию автора на Python 3.7+:


    from __future__ import annotations
    
    import asyncio
    from dataclasses import dataclass, field
    from typing import Generic, Sequence, TypeVar
    
    from aiohttp import ClientSession
    
    T = TypeVar("T")
    
    @dataclass
    class Comment:
        id: int
        title: str
    
        def __repr__(self):
            return f"{self.id} - {self.title}"
    
    @dataclass
    class Tree(Generic[T]):
        value: T
        children: Sequence[Tree] = field(default_factory=list)
    
        def print(self, indentation: str = "") -> None:
            print(f"{indentation}{self.value}")
    
            for child in self.children:
                child.print(indentation + "\t")
    
    async def get_comment(client: ClientSession, id: int) -> Comment:
        async with client.get(f"https://jsonplaceholder.typicode.com/todos/{id}") as resp:
            raw_comment = await resp.json()
            return Comment(id=raw_comment["id"], title=raw_comment["title"])
    
    async def get_comments_tree(client: ClientSession, tree: Tree[int]):
        children = [get_comments_tree(client, child) for child in tree.children]
        value = await get_comment(client, tree.value)
        chilren_results = await asyncio.gather(*children)
        return Tree[Comment](value, chilren_results)
    
    async def main():
        async with ClientSession() as client:
            tree = Tree(1, children=[Tree(2), Tree(3, children=[Tree(4), Tree(5)])])
            tree.print()
    
            comment_tree = await get_comments_tree(client, tree)
            comment_tree.print()
    
    if __name__ == "__main__":
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())

    pyright даже умеет за дженериками следить. А вот mypy и PyCharm почему-то не смогли меня наругать, когда при создании дерева я попытался одной из нод передать в качестве children НЕ Sequence[Tree].


    Если кто знает как обучить другие тайпчекеры понимать дженерики — поделитесь, пожалуйста. :)
    Попробовать можно на этом:


    tree = Tree(1, children=[Tree(2), Tree(3, children=[Tree(4), Tree(5, children='i am not a sequence of trees')])])
  • Python-скрипт на 20 строк, который каждый день желает родителям доброго утра через WhatsApp
    0

    Из приятностей еще можно отметить, что если вам понадобится удалить приложение — не придется ходить по каждому сервису и чистить все руками.


    chalice delete и все что оно породило — само и удалит.

  • Python-скрипт на 20 строк, который каждый день желает родителям доброго утра через WhatsApp
    0

    Весь третий шаг можно опустить, если воспользоваться официальной библиотекой под названием Chalice.


    Всё приложение можно уместить в 20 строк кода (у меня не Twilio, но суть та же):


    from os import environ
    
    from chalice import Chalice, Cron
    from httpx import Client
    from httpx.exceptions import HTTPError
    
    app = Chalice(app_name="app")
    http = Client()
    
    @app.schedule(Cron(30, 1, "*", "*", "?", "*"))
    def send_greetings_periodic(event):
        try:
            http.post(
                environ["DISCORD_WEBHOOK"], json={"content": "Hello!"}
            ).raise_for_status()
        except HTTPError as ex:
            app.log(ex)
    

    А сборкой приложения, настройкой AWS и отправкой туда всего нужного займется CLI, который идет в комплекте.


    Зависимости складываем в <app_root>/requirements.txt.


    Самое главное — добавить креды AWS в ~/.aws, добавить токен Twilio (в моем случае) URL для Discord, куда будет отправляться приветствие, в environment_variables из файла <app_root>/.chalice/config.json:


    {
      ...
      "environment_variables": {
        "DISCORD_WEBHOOK": "definitely_secret"
      },
      ...
    }

    И сделать chalice deploy.


    Если всё сделали правильно — вы восхитительны. :)


    (venv) D:\Projects\Python\discord-auto-greeter>chalice deploy
    Creating deployment package.
    Updating policy for IAM role: discord-auto-greeter-dev
    Updating lambda function: discord-auto-greeter-dev-send_greetings_periodic
    Resources deployed:
      - Lambda ARN: arn:aws:lambda:probably_not_secret:discord-auto-greeter-dev-send_greetings_periodic

    Невероятно много времени экономит.

  • Мелкая питонячая радость #5: Dynaconf — управление настройками в проекте
    +1
    Давно уже пользуюсь, очень удобная штука.

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

    Рекомендую попробовать.
  • Что не так с Яндекс.Музыкой? UX/UI разбор
    +8
    Это, наверное, сильно зависит от количества «налайканных» треков. Я вот месяца два пользуюсь YouTube Music, не на постоянной основе, но как минимум час в день музыка играет. Треки лайкаю. И знаете что? В рекомендациях все те же 10 исполнителей. С теми же песнями. От них уже просто тошнит. Я не смог понять как мне получать новую музыку в YouTube Music.

    C Яндекс.Музыкой же всё наоборот. Импортировал свой плейлист из 2 000 песен, много лайкал и ежедневный плейлист очень радует.

    Слушаю предпочтительно рок, иногда подмешивая разное.
  • Изучаем Python: модуль argparse
    0

    Судя по документации, можно сделать либо с ограниченным количеством аргументов (в данном случае — 3 аргумента; определит из длины кортежа type):


    import click
    
    @click.command()
    @click.option('--userdata', type=(str, str, int), help='User data represented as "FirstName LastName Age"')
    def greet(userdata):
        print('Hello, user {} {}. You are {} y.o.'.format(*userdata))
    
    if __name__ == '__main__':
        greet()

    Что можно использовать как:
    python app.py --userdata Vasiliy Petrenko 42


    Если нужно передавать несколько одинаковых параметров — можно делать так:


    import click
    
    @click.command()
    @click.option('--name', type=str, help='A name to greet', multiple=True)
    def greet(name):
        for n in name:
            print(f'Hello, {n}')
    
    if __name__ == '__main__':
        greet()

    И использовать как:
    python app.py --name Vasya --name Petya


    Указывать неограниченное количество аргументов для Option (например, python app.py --names Vasya Petya Tolya) — нельзя.

  • Изучаем Python: модуль argparse
    0
    Тоже очень нравится click. Особенно приятно работать с путями. Сразу при указании типа аргумента можно провести его валидацию, например:
    import click
    
    
    @click.command()
    @click.option(
        "--count",
        default=1,
        type=click.IntRange(min=1, max=100),
        help="Number of files to generate.",
    )
    @click.option(
        "--output",
        type=click.Path(exists=True, file_okay=False, writable=True),
        help="Output directory script will write files to.",
    )
    def file_generator(count, output):
        for i in range(count):
            with open(f"{i}.txt", "w") as f:
                f.write(f"Dummy data {i}")
    
    
    if __name__ == "__main__":
        file_generator()
    


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

    P. S. Да, во время генерации самих файлов проверки все еще нужны, но это уже другая история. :)

    P. P. S. Форматировался код при помощи black
  • UTF-8 кодировка в названиях и паролях Wi-Fi (Emoji)
    +1
    Netis WF2411E, родная прошивка, через веб-интерфейс позволил установить SSID в виде emoji без каких-либо проблем. С телефона посмотрел, emoji видно. Выглядит забавно. :)

    Установить пароль в виде emoji не позволил, сработала валидация.
  • Tornado vs Aiohttp: путешествие в дебри асинхронных фреймворков
    +2
    Vibora сейчас трогать — грешно. Автор обещает большие изменения, будем надеяться и ждать, но на данный момент, последний коммит — 18 июля. Проблем куча. В продакшн такое не потащишь.

    Вот uvicorn / starlette и их друзья — интересные кандидаты. На их основе множество фреймворков наплодилось уже.
  • Tornado vs Aiohttp: путешествие в дебри асинхронных фреймворков
    0
    В ответ на комментарий blind_oracle:

    Не согласен.

    Без углублений, которые делал автор, всё можно свести к aiohttp + uvloop и async/await синтаксису. Работается с этим крайне просто. :)

    Go, конечно, хорош. Мне в первую очередь было интересно: «А как бы показал себя Go в задачах автора?», но когда всё налажено для Питона — переезжать не хочется.
  • Бессерверный REST API «на коленке за 5 минут»
    +2

    Для создания простых API в Lambda на Питоне пользуюсь Chalice, очень упрощает жизнь и избавляет от рутины. Напоминает обычное приложение на Фласке. :)

  • Если вы подумываете начать писать на Go, то вот что вам следует знать
    +1

    mypy поможет уже начиная с момента, когда мы попытаемся передать times: str аргуметом в range(...), который ожидает int.


    Но если говорить про момент с условием — mypy сообщит, что тут что-то не так:


    app.py:19: error: Incompatible types in assignment (expression has type "Callable[[str, int], Any]", variable has type "Callable[[str, str], Any]")

    Похоже, тут mypy видит, что одной и той же переменной передаются Callable с разными типами и он сразу же об этом сообщает.


    Так же, насколько я понял, mypy делает предположение (так как он не может знать заранее что будет лежать в newInterface), что условие выполнится и в secret будет лежать функция greet_times2, которая на вход принимает str, str и не поднимает дополнительную тревога .


    Если же присвоение функций в условии поменять местами (при выполнении условия в secret присвоится greet_times, который str, int), mypy даст знать, что мы еще и типами ошиблись:


    app.py:22: error: Argument 2 has incompatible type "str"; expected "int"

    В общем, штука мощная и прикольная. Неожиданно приятно, что малыми усилиями можно защитить себя от выстрелов в ногу даже в Питоне.

  • Если вы подумываете начать писать на Go, то вот что вам следует знать
    0
    Поймут.

    Вот пример, если я правильно понял ваш вопрос:
    # app.py
    name = "John"
    times = "1"
    
    
    def greet_times(name: str, times: int = 1):
        for _ in range(times):
            print(f"Greetings, {name}!")
    
    
    greet_times(name, times)
    
    secret = greet_times
    secret(name, times)


    mypy app.py найдет и сообщит мне о двух ошибках: как для оригинальной функции, так и для делегированной:
    app.py:10: error: Argument 2 to "greet_times" has incompatible type "str"; expected "int"
    app.py:13: error: Argument 2 has incompatible type "str"; expected "int"
    

    На самом деле, они мощные и умеют сильно больше, чем пример выше.
    Даже если немного начать типизировать код — это помогает. Это еще называют gradual typing.
  • Если вы подумываете начать писать на Go, то вот что вам следует знать
    0
    Можно обрабатывать, но не обязательно. Этим занимается сторонний тайп-чекер (вроде mypy, который к слову, разрабатывается создателем Python).

    Может показаться, что «для этого нужно стороннее решение», но это не так важно, так как mypy — самый используемый тайпчекер, стандарт дефакто и поставляется с любым плагином для среды разработки по Питону (VSCode тот же). В PyCharm есть свой. То есть, проверка типов встраивается очень приятно и без лишних телодвижений.
  • Если вы подумываете начать писать на Go, то вот что вам следует знать
    +6
    Часто читаю отзывы, что питонистам нравится Go и все не могу понять — почему?
    Чем он вас цепляет после Питона?
    Я хоть владею Питоном не профессионально, но даже учить Go и его особенности неприятно. Мне куда ближе тот же Kotlin.
  • Введение в аннотации типов Python
    0
    Говорят, PEP по типизации располагает к созданию инструментов, которые бы использовали эти самые аннотации в целях улучшения производительности. Вот вдруг JIT нам прикрутят? :)
  • Топ книг по фреймворку Django
    +3
    У неё есть пара недостатков:
    … полное игнорирование второй версии Python… Последнее понятно и простительно...

    Очень интересный "недостаток" в книге по Django 2.1, учитывая это:


    Django 2.1 supports Python 3.5, 3.6, and 3.7. Django 2.0 is the last version to support Python 3.4. We highly recommend and only officially support the latest release of each series.

    Django 2.1 release notes


    The Django 1.11.x series is the last to support Python 2.7.

    Django 2.0 release notes

  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    0
    Функция, видать, свежая. :)

    Сейчас «Семейная подписка» работает.
  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    0
    Для этого нужна подписка.
  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    +2
    Так Яндекс «зашивает» (еще не факт) свои сервисы в смартфон под своим брендом. А вот Google делает это со всеми. Не очень справедливое сравнение. :)
  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    0
    Согласитесь, выключать полезную функцию, когда нужно поделиться файлом со знакомым или по работе из-за того, что кто-то использует её не по назначению — не очень круто.

    Для ваших целей есть специальные файловые хостинги с документированными лимитами. :)
  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    +1

    Если человек покупает Яндекс.Смарфтон, то очень странно от него ожидать, что он захочет удалить Яндекс.Браузер. Ты уже или весь в этой экосистеме или непонятно зачем покупал.

  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    +1

    А оно есть.
    Возможно, лимиты больше.


    Интересно, а какое ограничение допустимо для шаринга файлов?
    Или вы решили Яндекс.Диском раздавать файлы сотням / тысячам людей? Не для этого же функция создавалась.

  • На сайте «М.Видео» случайно открыли информацию по смартфону от «Яндекса» за несколько дней до презентации
    +2
    Яндекс Музыку, которая рядом не стоит с более дешевыми Apple Music и YouTube Music?

    Это очень интересное и спорное утверждение.
    Вы когда ей пользовались последний раз? 2 года назад?

  • Автор Python больше не руководит разработкой. Сделает это язык лучше или хуже?
    0
    docs.python.org/3/library/string.html#format-string-syntax
    The precision is a decimal number indicating how many digits should be displayed after the decimal point for a floating point value formatted with 'f' and 'F', or before and after the decimal point for a floating point value formatted with 'g' or 'G'.


    Если в код из примера после {precision} добавить f — получим 4 знака после запятой:
    >>> f"result: {value:{width}.{precision}f}"
    'result:    12.3457'
    

  • 10 веб-фреймворков Python, с которыми стоит работать в 2018 году
    0
    Абсолютно поддерживаю. Для API — отличный выбор. Действительно минималистичен и среди синхронных фреймворков является крайне быстрым (частично на Cython).

    Еще сейчас активно разрабатывается Vibora — асинхронный веб-фреймворк, внутренности которого написаны на Cython, из-за чего он получился невероятно быстрым (на странице проекта есть относительно свежие бенчмарки). До production-ready ему далеко, но «звездочку» им поставил, однозначно стоит следить. :)
  • Управление окружением Python c Pipenv
    0
    А что делать, если я хочу потестировать новый пакет, но пинить мне не надо?

    pipenv install <package> --skip-lock


    он должен сделать это явно

    Тут явно делается обратное. Вы всегда хотите запинить версии. А если нет — пожалуйста, вот флаг.

  • Управление окружением Python c Pipenv
    –1
    окружение все равно надо явно активировать через pipenv shell, поэтому не понимаю, чем pipenv shell отличается от. venv/bin/activate к примеру

    Для установки пакетов НЕ нужно активировать окружение самому. Даже для запуска скриптов можно НЕ активировать окружение самому, а воспользоваться pipenv run <command>, чтобы исполнить что-нибудь из нужного окружения.


    Я лишь предложил pyenv в качестве альтернативы

    Начнем с того, что это разные инструменты

    Так и запишем!


    Еще раз. pipenv при желании расширяется возможностями pyenv. Зачем себя ограничивать pyenv, а остальные вещи делать руками или другими способами — непонятно.


    pyenv же активирует окружение при входе в директорию проекта

    На любой "платформе"? bash / zsh / cmd / powershell?
    Автоматическую активацию окружения уже давно можно сделать и просто в pip, подключив нужный плагин в том же zsh. Такие же штуки есть и для pipenv.


    Как использование хешей для файлов может оповестить о наличии или отсутствии уязвимостей в коде?

    Никак, сори, я неправильно прочитал ваш комментарий. Я держал у себя в голове информацию об этом.


    Просто непонятно тогда, что значит "Strongly encourage the use of the latest versions of dependencies"

    Нет Pipfile.lock — всегда ставит последние версии пакетов, если не указано иначе.


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

    Не совсем понимаю, как тут будет мешать pipenv. Есть проект на Python, в нем есть свой .env, pipenv его подтянул. Никто не мешает использовать остальные тулзы.


    pipenv позиционируется разработчиками именно как менеджер среды dev окружения "Python Dev Workflow for Humans"

    Ну, это очевидно. Вы превращаете свой неудобный процесс разработки в удобный. :)


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

    Ничего не теряется. Даже если вы будете собирать свое приложение в Докере — вам так или иначе нужны конкретные версии пакетов, которые будут лежать в Pipfile.lock. А его уже разработчик будет создавать при помощи pipenv с великим удовольствием.

  • Управление окружением Python c Pipenv
    0
    Ответил вам ниже, не туда отправил :(
  • Управление окружением Python c Pipenv
    –1
    Это реально проблема для разработчика?

    Конечно, это невероятно упрощает работу. Раньше нужно было делать несколько вещей и следить за ними самому (где создавался venv, активировал ли я его), а тут всё сделали за меня.


    поставьте pyenv, он решает эту проблему, да еще и добавляет возможность ставить любую версию питона и на базе него создавать окружения

    Поставить инструмент хуже, чем инструмент лучше? Странное предложение. Тем более, что pipenv умеет использовать pyenv, поэтому минусов никаких на выходе не получаем.


    Но это решается и без pipenv. Может и не так элегантно) Но ставить только для этого отдельную тулзу как-то избыточно, что ли.

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


    От установки изначально неправильного или подмененного пакета это никак не защищает.

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


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

    Они "пинят", в Pipfile.lock. А коли же вы его потеряли — из Pipfile установятся последние версии пакетов, если вы не укажете другое сами. Это уже в ответ на:


    лучше это делать явно, руками и поднимать версии на нужные, а не на самые последние

    включать в тулзу, которая управляет пакетами, функционал чтения и активации файлов

    Тут я и согласен, и нет. С одной стороны — вы правы, с другой — а зачем мне использовать какой-то дополнительный пакет, если это сделает pipenv? Он просто сделает внутри окружения доступным всё что есть в .env как переменные окружения. Это даже логично звучит. Pipenv все-таки и окружением управляет. Я скорее рад этому, чем нет.




    Я допускаю, что не весь функционал Pipenv может быть нужен всем разработчикам, многие спокойно себе живут используя другие инструменты, но в мире Питона не было удобного способа делать свою разработку удобной, как это уже давно сделано в других "мирах" (PHP, JS, Ruby, ...). Использовать его или нет исключительно ваше право, но многие разработчики очень довольны, просто дайте ему шанс. Возможно, удасться насладиться тем, что за вас все сделали и вы можете просто заняться разработкой, а не играми с окружением и зависимостями! :)

  • Управление окружением Python c Pipenv
    0

    Эту "штуку" Pipenv вполне себе поддерживает.
    А еще много других, крутых фишек. Все в одном пакете, с удобным CLI.
    Советую более детально ознакомиться на официальном сайте проекта.


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


    Присматриваюсь к poetry, попутно используя старый добрый pip + venv.

  • Управление окружением Python c Pipenv
    +1
    А почему pipenv показан не так?

    Удобство. Обо всем по порядку.


    pip install pipenv

    Вы единожды ставите пакет в систему и больше его не трогаете. Поэтому нет смысла указывать этот шаг при сравнении двух этих инструментов.


    $ pipenv shell
    $ pip install Flask gunicorn

    А это не альтернатива.
    shell используют, если вам нужно проделывать много манипуляций из-под этого virtualenv. Если вам нужно установить пакеты или запустить скрипт — зачем?


    Для установки же пакетов очень удобно использовать $ pipenv install <package>, который автоматически посмотрит, есть ли в данной папке Pipfile, создано ли окружение, если нет — создаст, установит в это окружение пакеты и "запинит" зависимости.
    pip install <package> же этого всего не сделает, даже если запускать его внутри shell. Да, он установит пакет в virtualenv, но "пинить" зависимости вам придется самим.