Pull to refresh

Comments 133

— Что, солдат? Ссымся?
— Так точно. Ссусь.
— Ну это, солдат, не беда. Такая сегодня экологическая обстановка. Все ссутся. Я ссусь. И даже главком пысается, бывает. Но по ситуации. Что ж нам из-за этого, последний долг Родине не отдавать? Твой позорный недуг мы в подвиг определим, пошлем в десантники. Там ты еще и сраться начнешь.

(с) ДМБ
«С другой же, проще даётся новикам, что обеспечивает приток новой крови в сообщество.»

звучит как «сообществу нужны инвалиды»
Не нравится то как из каждой щели рекламируют курсы от рандом-бокс, где обещают 300к/нано-сек. Не нравятся статьи в которых пишется: n-программа в n-строк (с импортом чуть ли не ядра ОС), без какой либо архитектуры или небольшой структуры, модульности, просто простынки кода (но зато в мало строк!111).
Типо данный ЯП сразу убирает требования к базовым ИТ-знаниям, Computer Science и т.п. Нет не убирает. ЯП как ЯП, все они инструменты, у Питона есть своя специализация и направленность, а оверхайп, попытка натягивания «совы на глобус» и реклама «вайтишности» языка никак его не красит, вернее она не красит тех кто об этом кричит.
И в итоге в статье почему-то три гребёнки. Мне не приходится по работе использовать Python, пересаживание на Python также не облегчит те задачи которые я решаю, для текущих моих пэт-проектов он также мало подходит, просто я не использую данный инструмент, мне и с текущими хорошо.
Пробелы в питоне рождают следующую проблему: если хочешь быстро скопировать себе какой-нибудь скрипт из интернета и запустить, с большой вероятностью все эти пробелы поплывут, и придётся сидеть и расставлять их руками.

Ещё одна проблема питона, которую не назвали — отсутствие обратной совместимости у версий 2 и 3.
1) а гит, пэйстбин для чего были созданы? Если скрипт с какого-то малоизвестного источника не запускается, тут стоит винить источник, а не ЯП.
2) зачем нужна эта обратная совместимость, если 2-й питон безнадёжно устарел? Кроме того, развитие питона так же предполагает эволюцию синтаксиса, так что…
1) На том же медиуме половина примеров кода на питоне нормально не отформатирована. Можно, конечно, обвинять этот «малоизвестный» источник, но примеры других ЯП (те же плюсы, которые упоминал автор поста), скомпилируются нормально даже с поплывшим форматированием.
2) Нужна затем, что огромное количество кода в интернете написано на втором питоне. Как минимум, чтобы этот код запустить, нужно иметь на компе две версии питона, а чтобы добавить этот код к своему, нужно переписывать. Язык, конечно, скорее всего выиграл от того, что не потащил за собой всё старьё из 2-й версии, но это доставляет определённые неудобства.
К слову, Python далеко не самый медленный язык по сравнению с конкурентами в «своей весовой категории», взять те же PHP

Ничего более смешного за последнее время я не читал. Сравнивать Python по скорости с современным PHP, который давно уже не «интерпретируемый», чья виртуальная машина по скорости уступает нативному коду максимум в 1.5 раза, в котором есть JIT-компиляция… Вы серьезно?
Режим интерпретации это php -a в консоли?
PHP и без JIT не интерпретируемый язык (правильнее, конечно, говорить не «язык», а «реализация языка»)

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

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

Иными словами, ненавидят не Python, а некоторую часть фанатиков Python, настаивающих на его использовании в качестве «золотого молотка» для решения любых задач.

Прошу прощения, если кого обидел. Python я сам использую в работе. Но только тогда, когда его применение оправдано.
UFO just landed and posted this here
Все познается в сравнении. Мне приходилось продуктивные(!) системы писать на COBOL и ассемблере IBM/370. Потом на сопровождение принял программный комплекс на Lisp. REXX после этого воспринимался, как дар божий, а Perl — как верх совершенства. Что уж тут говорить про Python?
После того, как пришлось покодировать за свою жизнь на десятке-другом языках (T-SQL, PL/SQL и PL/pgsql считаю разными языками, хоть они и похожи), толерантность резко повысилась и сложные в освоении языки больше не попадаются )
UFO just landed and posted this here
«Неприятно» — субъективное понятие. А если объективная реальность требует использования конкретного языка — это уже обязанность разработчика. Нет такой работы, где не приходилось бы заниматься «неприятными» (чаще — нудными и рутинными) вещами. Рекомендую даже не думать о том, насколько работа неприятна. Лучше в любой задаче находить что-то позитивное. И тогда все станет проще и легче.

Например, в свое время охреневал от DAX, потом от R. Ничего, зато освоил и обнаружил, что некоторые задачи на DAX решаются эффективней, чем на MDX, а на R — эффективней, чем на Python.
UFO just landed and posted this here

Если использовать PyCharm (не знаю, есть ли еще что-нибудь подобное) и, дополнительно, type hints и форматированные doc-strings, то жизнь сильно облегчается.

В VS Code достаточно неплохая поддержка автодополнения (с учётом типов, естессно), линтеров/форматтеров и прочих радостей жизни; однако последний раз когда смотрел, не было рефакторингов за исключением ренейма. PyCharm'ом не пользовался, но уверен, что там с этим лучше.

UFO just landed and posted this here

А можно конкретный пример? Хотя я и сам могу в пример matplotlib привести. Но тут возраст пакета почтенный, да он, небось, еще и совместимость с Python 2.X поддерживает.


Ну и кстати, что, в С/С++ не бывает такого:


func(float a, float b, ... float z)

P.S. На фортране можно писать на любом языке.

UFO just landed and posted this here

По поводу json'а — не понимаю проблемы. В описании пакета json есть ведь таблица конвертации?


В питоне, говорят, так тоже можно, но IDE от этого срывает голову.

Можно коротенький пример?


библиотека вместе с компилятором за меня сгенерит всю сериализацию-десериализацию,

А вам, часом, не pickle нужен? Он как раз за это отвечает.


Но если вы сравниваете питон с худшим случаем для плюсов,

Так и вы, возможно (пример?) не лучший случай для питона рассматриваете.

UFO just landed and posted this here
Нет. Если формат жсона зафиксирован, то бывает удобно определить под него какой-то конкретный тип данных, в который бы этот жсон бы парсился.

pydantic-docs.helpmanual.io

А с результатом json.loads() -> List[Any] это сработает?

Вдогонку — был неправ: Сигнатура json.loads из typeshed


def loads(
    s: Union[Text, bytes],
    encoding: Any = ...,
    cls: Optional[Type[JSONDecoder]] = ...,
    object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ...,
    parse_float: Optional[Callable[[str], Any]] = ...,
    parse_int: Optional[Callable[[str], Any]] = ...,
    parse_constant: Optional[Callable[[str], Any]] = ...,
    object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ...,
    **kwds: Any,
) -> Any: ...
То есть, вместо того, чтобы просто посмотреть на типы, где это вполне могло бы быть выражено, мне искать таблицы конвертации?

Что их искать — в официальной документации по питону прочитать про пакет json? Ну или пройдите по списку, который возвращает json.loads(), напечатайте типы элементов. Если тип не скалярный — рекурсивно для элемента. Или в режиме отладки посмотрите, что там функция вернула. Это если json'ы однотипные. Ну а как иначе, если функция, вообще говоря, читает произвольный валидный json-файл?


Сейчас уже не воспроизведу, к сожалению (особенно с гарантией глюков IDE — для этого надо как минимум будет поставить pycharm).

Ну, да, вот в коде ниже mypy ошибку видит, а последний Pycharm — нет (и он еще считает, что тип полей Any). Надо будет issue создать (если уже не создано). Но это совсем не "у IDE от этого срывает голову." False negative — все-таки лучше false positive. Ну и все равно надо периодически mypy использовать.


Pycharm - false negative
import json

def f(x: bool) -> None:
    print(isinstance(x, bool), type(x), x)

class Entity:

    def __init__(self, data: str):
        self._a: int
        self._b: bool
        self._a, self._b = json.loads(data)

    def ff(self) -> None:
        f(self._a)  # <- mypy error: main_mypy.py:16: error: Argument 1 to "f" has incompatible type "int"; expected "bool"

def main() -> None:

    e = Entity('[1, true]')
    e.ff()

if __name__ == '__main__':
    main()

Но можно и Pycharm уговорить, правда, за счет небольшого оверхеда в runtime:


Рабочий код
import json
from typing import cast

def f(x: bool) -> None:
    print(isinstance(x, bool))

class Entity:

    def __init__(self, data: str):
        self._a, self._b = json.loads(data)
        self._a = cast(int, self._a)
        self._b = cast(bool, self._b)

    def ff(self) -> None:
        f(self._a)

def main() -> None:

    e = Entity('[1, true]')
    e.ff()

if __name__ == '__main__':
    main()

Нo это в случае, если вы содержимому json доверяете. А так структуру валидировать надо в runtime.


А в каком примере отсутствие типов будет полезно?

Я, вроде, обратное предположил? когда сказал:


Так и вы, возможно (пример?) не лучший случай для питона рассматриваете.
UFO just landed and posted this here

Говоря про документацию, я имел ввиду вот это, или offline вариант, который ставится вместе с питоном. Ну, да, type hints сюда еще не завезли, как и много еще куда. Но хотя бы написано, что "If the data being deserialized is not a valid JSON document, a JSONDecodeError will be raised". Кстати — там и translation table есть. Т.е. тип результата loads Any можно заменить было бы на Union[int, float, str, bool, None, List, Dict]. А нет, можно и нестандартные типы на выходе иметь, см. пример. Таки Any.


Но есть вот такой продукт (его, кстати, тот же PyCharm для подсказок и проверки типов использует), куда завезли. Вот как там выглядит


сигнатура json.loads
def loads(
    s: Union[Text, bytes],
    encoding: Any = ...,
    cls: Optional[Type[JSONDecoder]] = ...,
    object_hook: Optional[Callable[[Dict[Any, Any]], Any]] = ...,
    parse_float: Optional[Callable[[str], Any]] = ...,
    parse_int: Optional[Callable[[str], Any]] = ...,
    parse_constant: Optional[Callable[[str], Any]] = ...,
    object_pairs_hook: Optional[Callable[[List[Tuple[Any, Any]]], Any]] = ...,
    **kwds: Any,
) -> Any: ...

Т.е. все правильно, Any. Т.е., если ожидаешь конкретную структуру и доверяешь поставщику данных — я пример привел, как превратить этот действительно произвольный (ну до определенной степени, конечно) результат в класс с типизированными полями или набор типизированных переменных. Если не доверяешь поставщику данных — придется проверить, что пришло. Вот так, например.


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

Это какой? А впрочем, не очень важно. Все равно ничего особо не понятно.


Загружаем модуль и узнаем тип функции decode:

Я правильно понял, в командной строке (интерпретатора)? Да ну, в Pycharm для этого надо консоль открывать. Проще "нормальный" help открыть.


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

В питоне — на входе или строка или байты. Вроде, и достаточно? Хотя, вот такое есть, например.


Что такое FromJSON?

[… ещё 100500 строк инстансов...]

Т.е., фактически, тот же Any.


То есть, даже если мы ничего не знаем о жсоне, то мы можем быть уверены, что мы можем его распарсить в A.Value, если это валидный жсон.

Все равно — проверка на валидность в runtime? Ладно, проверили, но дальше, все равно придется в runtime же разбираться, что там конкретно внутри древообразное живет? Что может быть в узлах у питона, см. ту же translation table. Плюс custom types (см.выше).


Режьте меня — не вижу (большой) разницы.


Я тут запутался, что у вас negative, а что positive. Negative — это когда ошибки на самом деле нет, но тайпчекер считает, что она есть?

Наоборот. Не генерирует ошибку там, где она есть.


P.S. Никто не утверждает, что питон — идеальный язык. Вполне приемлемый в большом (чтобы хватило на хлеб с маслом) числе случаем. И что PyCharm — идеальный IDE. Зайдите на issue tracker — дофига мелких ошибок и проблем. Но у каждого пользователя — свои.

UFO just landed and posted this here
Так вход мы вообще не обсуждаем, там всё проще.

Вы же написали ранее, что decode:


… может использоваться для того, чтобы распарсить любой тип, реализующий FromJSON

или это валидатор?


Any — это вызываемая функция выбирает, какой тип вернуть, и заворачивает его в Any

Это не тип, а type hint "на отвяжись", чтобы IDE не ругался на отсутствие типа. Т.е. функция может просто вернуть любой реальный тип.


Я могу явно написать decode myStr :: Maybe [Int], чтобы попытаться распарсить жсон как список интов, или decode myStr :: Maybe Person, чтобы функция decode пыталась распарсить жсон как какой-то мой тип Person.

Не могу не согласиться — удобно. В питоне придется воспользоваться внешним пакетом jsonscheme (см. также https://json-schema.org/) или чем-то подобным и написать свое расширение для json.loads().


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

Не понимаю, как ваш haskel работает. Из вашего последнего примера в предыдущем сообщении видно, что если в runtime на вход decode подать строку (из файла, несколько, разных), то она их будет каждый раз в runtime проверять и парсить.


Проблема в том, что эту translation table могу прочитать я как человек, но не может прочитать машина, поэтому для неё нужны какие-то отдельные тайпхинты или что-то такое (и которую не запилили).

Она как раз для человека нужна, чтобы, посмотрев на конкретный пример json-файла, написать парсер результата работы json.loads() в нужный формат. Типа выдернуть лишь часть полей? Раскидать по именованным атрибутам класса и т.д. и т.п.

UFO just landed and posted this here

Действительно, мало чего можно понять по описанию json.load. Мы не знаем ни про типы, которые он может вернуть, ни про исключентя, которые он может выбросить. Так что единственный нормальный способ, как по мне, это попробовать функцию в REPL. Можно посмотреть на поведение при разных входных данных. Тогда станет более менее понятно.
Тогда и стиль программирования отличается. Если в том же Haskell мы можем рассмотреть все возможные варианты и обработать все возможные ошибки, а в Python об ошибках мы будем узнавать уже во время разработки (т.е. забудем какую-то вещь обработать, но только через время о ней узнаем) и даже в продакшене (есть такая вещь, как sentry). Возможно, проблема в стиле. Вы привыкли программировать в одном стиле, и оказывается, что на Python так программировать будет тяжело.


Кстати, что там с количество библиотек под Haskell и как там с его популярностью? Я понимаю, что популярность не должна играть большую роль, но ведь от популярности в какой-то мере зависит и количество библиотек. Чем больше библилиотек, тем больший спектр задач можно решать на Haskell. Другой вопрос — а нужна ли такая гибкость?

UFO just landed and posted this here

Если взял в руки молоток, начинает казаться, что забить им можно буквально всё. И что все прочие инструменты не такие удобные ;)

UFO just landed and posted this here

Мне хорошо за сороковник, на разных писал и пишу в разное время. И сейчас понял, что кода именно на питоне последнее время стало встречаться намного больше. Стало обидно, что проходил мимо него столько времени. Накачал pdf-ok, когда валялся с модной болезнью, купил книжку, сейчас кайфую что понимаю о чем речь в кусках программ, хотя первых два дня ловил себя на мысли, что внутренне возмущался когда видел некоторые языковые конструкции питона и пыхтел, ведь в ХХХ и УУУ это же сделано совсем иначе :). Зато в копилочке у меня появилась возможность запускать и понимать внутреннюю кухню в проектах с интересными мне направлениями. Зачем сознательно сейчас лишать себя еще одного инструмента.

UFO just landed and posted this here

Бывают еще ситуации, когда, кроме питона и нет ничего больше. Я про embedded interpreter. Хочешь автоматизировать параметризованное построение геометрии и вычислительной сетки — вот тебе АPI в виде модуля, который с потрохами программы двунаправленно общается, и вперед. А у меня эта программа (версии, естественно, разные, недавно даже третий питон завезли. один из двух основных рабочих инструментов вот уже лет 15 наверное. Вторая — малоизвестный FEM solver. Я так и забросил C++. Сначала я на нем всякий постпроцессинг, в частности, писал, а потом попробовал на питоне. Код оказался раз в 10 короче. Спасибо пакетам numpy/scipy/matplotlib. А то, что разовая программа отрабатывает не за 10 секунд, а за пару минут, так и что?


Ну и питон есть у всех в округе. На ноутбуках, рабочих станциях, кластерах, виртуалках...

UFO just landed and posted this here
А на плюсах вы чем пользовались? Какой-нибудь там dlib или eigen?

Не помню я их в то время. BLAS, LAPACK… Опять же, на Linux-серверах они были, а собирать что-нибудь серьезное без административных прав — нафиг. Я помню, как матерился, собирая себе в таком режиме midnight соmmander.


Если она действительно разовая, то и нормально. Но программы ж не всегда разовые.

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

UFO just landed and posted this here
А если сутки удаётся свести до нескольких минут

Расчет, скажем, в Fluent?

UFO just landed and posted this here

Ну, это понятно, что совсем другая история.

К пробелам можно привыкнуть за пару дней, а взамен за моральные страдания

Один таб — один уровень вложенности. Логично же.


Как по мне, так это плюс. Это отучает людей писать код как на втором скриншоте с++, так и отсекает тех, кто хочет писать все в одну строчку.

Ну… в одну строчку-то как раз вроде можно, не? ;) Проблема с отступами от двух и выше…
Вот это тоже хорошо, ограничивает любителей накрутить вложенных условий и циклов.
ну по поводу форматирования, сейчас когда в ide можно выделить кусок неформатированного кода и нажать refactor… какоето натянутое «приемущество»

а вот динамическая типизация это реально боль… как только проект переваливает какойто размер (и это далеко не «огромный») сразу начинаются костылестроения по контролю типов
def get_city(city):

Добавим сахарку детишкам.


def get_city(city: str) -> str:

Не боготворю, но люблю питон за скорость отладки и обилие тулзовин. Возникла потребность проверить какую-нибудь математику или алгоритм, раз-два — и уже есть прототип, юнит-тесты с помощью pytest, и проверка типов от mypy, и всё это причёсывается yapf-ом.


Код на C++… и как его пишут дети

Вот вам смешно, а у нас так 80% проекта выглядит. Не совсем так, конечно, и C# вместо плюсов, и не выиграл, а проиграл, но очень похоже.

Забавно, что самому главному недостатку Python отведен маленький абзац в самом конце. "Ну нет типизации, никто не знает, где и когда оно рванет в продакшне, зато новичкам проще писать hello world"

забавно что фанаты питона реально не считают это недостатком

помнится на заре своего увлечения программированием я увлекался VB6… и у него главным недостатком считался тип Variant и довольно вольный контроль типов (без option explicit)… потом шла его сущность в виде полу-интерпретатора… типа фуу… это не язык а черти что
прошло 20 лет… и буквально все минусы VB6 я слышу от фанов питона как неоспоримые плюсы… вот уж времена меняются
В питоне вообще-то строгая типизация. Но динамическая. И это очень круто.
UFO just landed and posted this here

Опять же, зависит от задач. В jupyter notebook или простеньких скриптиках, или для обучения конечно неохота возиться с типами и ругаться с компилятором. Вот пусть python там и остается :-)


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

Вообще как раз сейчас (где-то 3.6+) с типизацией в питоне всё лучше и лучше. Есть аннотации типов и способы контроля (см. mypy), минимальный набор потребностей покрывает.


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

UFO just landed and posted this here
mypy активно развивается. там сейчас даже протоколы (аналог типажей из rust и scala) есть, корявые но есть. Но основная фишка которая в разработке это mypyc. вот неплохая статья habr.com/ru/company/exness/blog/542106
UFO just landed and posted this here
Первая и самая главная претензия к Python — постоянные и неизбежные проблемы с зависимостями. Проекты сложнее Hello World никогда не заводятся с первого раза. Попытайтесь, к примеру, запустить GPT-3 от Сбербанка на вашей домашней машине, и вы тоже начнёте не любить Python, потому что вам придётся упороть много часов, разбираясь, почему программа падает, когда вроде всё из requirements поставлено. Причём падает молча, тупо крэшем, даже без стектрейса… Хуже с зависимостями работает разве только C++.
Вторую претензию уже упоминали — использовать форматирование в качестве элемента синтаксиса видимо придумали специально чтобы затруднить копипасту так сильно, как только возможно. При копировании кода все эти Tab'ы с пробелами гарантированно поплывут.
Третье — совершенно кошмарная работа Python со строками. Стоит только во входных данных попасться «неправильному» символу, и всё повалится с километровым стектрейсом, увенчанным UnicodeDecodeError. Причём, конечно же, упадёт совсем не там и не тогда, где эта строка возникает, после чего нас ждут увлекательные часы отладки.
И это при том, что практически во всех данных, которые получаются из внешних источников, гарантированно будут «неправильные» символы, не соответствующие стандарту Unicode. А если кодировки гоняются туда-сюда (скажем, надо отдавать текст не в utf-8, а в cp1251), то всё становится совсем печально. Ни один другой язык не спотыкается таким кошмарным образом тупо на обработке символов. Оно ж от любого чиха валится…
А если такой символ попадёт в исходники (например, в комментарий), то вообще труба. Оно начнёт валиться в произвольных местах, и вы даже не сразу поймёте, в чём вообще проблема.

А как должна вести себя программа, словившая unicode error, но не оборудованная проверкой на ошибку? Всё равно упадёт, только немного позже. Что и произошло.

не скомпилироваться, например, ввиду отсутствия гарантии правильности данных поступающих на обработку

Ну, Питон это, все-таки, интерпретатор...

Программа на С++ не скомпилируется, если ей на вход подадут когда-нибудь не те данные? Круто, конечно :)

Если в программе (на любом языке) принимается допущение что любой сырой набор байтов — это валидная UTF-последовательность, то это ошибка в логике.


Язык С++ перекладывает заботу о валидации на программиста. Поэтому если программист "забыл" добавить валидацию, случается краш.


В языке Раст например, устроено так что "забыть" невозможно. Необходимо явно написать каким именно образом преобразовать сырые данные в utf8 — from_utf8 (и обрабатывать Result), from_utf8_lossy (который вставит плейсхолдер в места, которые сломаны) или как-то ещё

Есть два основных варианта поведения. Первый — это когда строка обрабатывается просто как набор байт по принципу «Garbage in — Garbage out». И если там на входе встречается неправильный символ, то и на выходе будет такой же, а остаток строки нормально обработается. Этот подход обычно используют C/C++ библиотеки.
Второй вариант — автоматически заменять битые символы плейсхолдером U+FFFD (REPLACEMENT_CHARACTER) — "�". При этом строка также успешно обработается, и если есть желание, то после обработки можно даже найти индексы неправильных символов.
А вот как эту задачу решить в Python? Вот есть строка. Вот мы точно знаем, что где-то в ней имеются битые символы. Как их найти и убрать, если при любой попытке это обработать программа сразу упадёт? Это не очень-то тривиальная задача, тогда как для большинства остальных языков это вообще стандартное поведение — обрабатывать строки «как есть».

Открывать файл с помощью codecs.open(), где можно определить политику обработки ошибок, или ручками — читать в бинарном виде, потом декодировать: bytes.decode().


Вдогонку, да обычный open это умеет…

"А вот как эту задачу решить в Python?"
Как и везде. Ловить и анализировать exception.


"для большинства остальных языков это вообще стандартное поведение — обрабатывать строки «как есть»."


Дык в python объект типа string (с unicode в нутре) немного сложнее устроен, чем char* :)

А если такой символ попадёт в исходники (например, в комментарий), то вообще труба. Оно начнёт валиться в произвольных местах, и вы даже не сразу поймёте, в чём вообще проблема.

Да даже если валидный: https://bugs.python.org/issue38755.

Python вполне хорош для своих задач. Например, как shell script. Или для ученых, которым нужны хорошие графики, анализ данных без особых затрат.


Плох он становится там, где им пытаются заткнуть задачи в неподходящих местах. Например, если "программист Python" уверен, что любая задача должна решаться через "pip3 install", и для простого сайта из 5 страничек заводит Django. А тот падает.


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


В общем, боль есть, но до ненависти ей далеко.

Современные инструменты, линтеры, форматтеры, конечно упрощают работу, но каждый раз, когда после Питона приходится писать на языках со строгой типизацией — это просто глоток свежего воздуха — собралось и работает, «а не вот это вот все». Про скорость особенно смешно слышать во всяких облачных штуках, где сетевой запрос на каждый чих нужен.

Не осилил питон прямо с синтаксиса и пробелов. Может пусть детишки и дальше пишут? И эти датасайентологи

Современный c++ по моему опыту весьма близок к питону по скорости разработки — auto, лямбды в помощь. "Проблема" с пробелами элементарно решается файлом .clang-format в репозитории (конечно, форматировать Легаси тот ещё ад для git)
Для пакетов — Conan


Раньше программировал больше на питоне, потом полностью перешёл на плюсы, и не жалею — спокойный сон за типы дороже

Соглашусь, 11 и 14 стандарты заметно облегчили жизнь
По моему опыту, скорость разработки на 95% определяется не синтаксическим сахаром или там сборкой мусора, а скоростью поиска и интеграции чужого кода. В конце концов, самый быстро разрабатываемый код — это тот, который уже кем-то написан.
И вот тут C++ в хлам проигрывает Python'у. Если в стандартной библиотеке Python есть практически всё, на что только у вас хватит фантазии (а чего нет — то находится в шаговой доступности в виде pip), то в C++ всё куда печальнее. Стандартная библиотека C++ на удивление куцая, там даже нормальной работы с сетью до сих пор нет (это в 2021 году, когда всё давно в облака ушло!).
Вот например, нужно просто скачать файл с какого-то URL для последующей обработки. В Python скачать файл можно в две строки, а в C++ вам придётся искать сторонние библиотеки и как-то их подключать/собирать. Это будет куда медленнее, и никакие лямбды не компенсируют потерю скорости.
Хотя, если вы пишете программы только под Windows, то тут всё неплохо — WINAPI могут буквально всё, и есть сразу «из коробки».
вы pip как панацею не превозносите.
каждую 'офигенную ' либу оттуда надо по возможности перепроверять и смотреть что пишут в репозитории, в issues и в комментах да и в код заглянуть желательно

Я уже натыкался несколько раз на проекты в которые приходил, когда 'ребяяят… крындец, django обновился до 3.12 и всё умерло'… а умерли такие универсальные либы у которых last commit на гитхабе 5 years ago несмотря на пару сотен звездочек
также бывает в коде либ такая страшная дичь написана что проще самому переписать с нуля чем бездумно их юзать.

"Стандартная библиотека C++ на удивление куцая"


На то она и стандартная. Для С++ есть boost, кстати.


"там даже нормальной работы с сетью до сих пор нет"


Учитывая, что работа с сетью — это огромный платформозависимый кусок кода — наверное оно и правильно.

так для этого придумали ноду и забыли про питон

со временем собирается личная копилка «fast-develop» рецептов, например класс-хелпер для cURL, для json тоже полно хидерных библиотек (https://github.com/nlohmann/json как наверное самая user-friendly)

пишу исключительно под Linux, работа c сетью, JSON и REST API (под капотом числодробилка, python не пойдет, разница 5мин vs 10 часов)

С питоном уже надоело возиться с импортом под разные версии (код часто запускается в разных окружениях, то python2.x, то python3.x) и несовместимостью 2vs3

Логика stdlib c++ такова уж, сеть это не std, хотя вот смотря на прогресс C++20 может скоро и появится (но зачем, если есть cURL?)
Как по мне, то Питон – супер язык программирования! Но только в своей области применения. Пока мне его более чем достаточно для задач одноразовой подготовки (обработки) данных. Для этих целей он просто идеален!

Для программирования других задач мне очень нравится C++ / WTL. Но как в С++, так и в Питоне, мне совершенно не нравиться стиль разметки кода, практикуемый большинством. Конкретно в Питоне, я всегда делаю отступ состоящий из двух пробелов. В качестве «закрывающего» тега использую комментарий, типа:

#==============================================================================
# exec(open('Html.py', encoding='utf-8').read())
# Html.py – Извлечение данных из html-страницы
#==============================================================================

#==============================================================================
# Глобальные переменные (только на чтение, при изменении используется модификатор 'global')
#==============================================================================

# Имя файла данных
_SrcName = '661830' # Слово из онлайнового словаря, с максимально объемным описанием

#...

#==============================================================================
# HtmlParsing2() — Очистить результаты предварительной обработки html-страницы от пустых строк и прочего «мусора»
#==============================================================================
def HtmlParsing2(OutFile, Html):
# Максимальная позиция строки в списке Html
MaxPos = len(Html) — 1
NewBlock = False

for i in range(MaxPos):
HtmlLine = Html[i].replace(' ', '').strip()

# Удалить ненужные символы из html-строки
HtmlLine = DeleteSpam(HtmlLine, NewBlock)

if(len(HtmlLine) > 0):
OutFile.write(HtmlLine)
NewBlock = True
# if(len(HtmlLine) > 0)
# for i in range(maxPos)

return
# HtmlParsing2()

#...

#==============================================================================
# Main() – Главная функция
#==============================================================================
def Main():
# Обработка данных
Processing()

# Завершение работы
return
# Main()

if __name__ == "__main__": Main()

#==============================================================================
#==============================================================================

Так что, любой опенсорсный код, используемый в проекте приходится переформатировать «под себя».

P.S. Отступы здесь теряются, при вставке кода.
те, кто Python боготворят;
те, кто делают вид, как будто его не существует, или о нём практически не слышали;
те, кто ненавидит Питон всем сердцем.

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

Наверное, каждый слышал, что Python медленный и уступает в скорости другим языкам по типу С++, С# и т.д.

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

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

Мне даже интересно, автор пробовал на ассемблере обойти по скорости современный Си? И много ли найдется в мире людей, которые смогут это сделать?

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

вы не берете те задачи в которых производительность упирается в питон
Ну так надо тогда указать, что в определенных задачах питон медленный, а не «он вообще медленный». Потому что есть множество задач, где такой вопрос даже не поднимается.
UFO just landed and posted this here

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

C тоже архитектурно зависим. Ну то есть он конечно позволяет писать кроссплатформенный код, однако вовсе не делает автоматически любой написанный на нём код кроссплатформенным. И для поддержания архитектурной независимости приходится прилагать очень значительные усилия (в разы большие, чем для написания мультиплатформенного кода на том же Python). А когда их изначально не прилагали, а потом внезапно грянул гром…
Достаточно вспомнить лишь, через какую боль пришлось пройти множеству программистов, когда осуществлялся переход с x86-32 на x86-64. Всего-то разрядность некоторых типов данных поменялась, а в итоге с адаптацией сишных программ была такая жесть, что до сих пор вспоминать страшно.

"Всего-то разрядность некоторых типов данных поменялась"


Ну, если в 100500 местах считалось, что sizeof(int) == sizeof(pointer), и pointer-pointer помещается в int, а потом вдруг оказывается, что это совсем не так… Конечно, все эти 100500 мест надо найти и исправить. Но теперь мы знаем, что так не надо делать, и не будем больше наступать на эти грабли? ;)

UFO just landed and posted this here
Если алгоритм достаточно мелкий, чтобы реализовать его на ассемблере в разумные сроки, то да, это делается легко, иногда с профитом в 3-10 раз.

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

Если у вас есть примеры такого профита, было бы интересно послушать. Но я уверен на 99%, что все такие примеры будут приведены от людей с бородой свисающей ниже свитера.
UFO just landed and posted this here
Я попытался ради интереса повторить ваш тест, но не уверен, что правильно оформил интринсиковый вариант:
gcc.godbolt.org/z/cbqGhYcas
так правильно или нет? В частности, тип idctRows.
Обычная версия кстати вполне успешно векторизуется:
gcc.godbolt.org/z/e4K3Ps5z3
только компилятор не умеет использовать горизонтальное сложение, и из-за этого долго тасует данные в регистрах, чтобы затем выдать красивую «простыню» из mulps/addps. Но сомневаюсь, что это даёт замедление аж в 5-7 раз, скорее вы сравнивали с невекторизованной версией.
UFO just landed and posted this here
Сравнил в том виде, в каком выкладывал в godbolt (Clang / gcc / интринсики, мс).
i3-3250 (IvyBridge), AVX: 69 / 45 / 44
i9-9900K (CoffeeLake), AVX: 52 / 38 / 40
i9-9900K (CoffeeLake), FMA: 44 / 38 / 40
Clang отстал на 10-60%, а gcc даже обогнал интринсики. В горизонтальные сложения он тоже не умеет, но зато сообразил перетасовать данные (матрицу 8*8?) ДО цикла.
gcc.godbolt.org/z/PWjar9qar
Что логично, я тоже об этом думал, глядя на попытки Clang-а, и в статьях по умножению матриц на Хабре что-то такое было. Похоже, gcc уже настолько крут, что читает Хабр :)
Если серьёзно, есть с gcc одна странность — если вызывать функцию idctAV в вашем примере 1 раз, то работает быстро, а если несколько раз в цикле для большей стабильности результата, то скорость сильно проседает (только с gcc, с clang такого нет).
Код
    const int cycles = 10;
    auto start = high_resolution_clock::now();

    for (size_t c = 0; c < cycles; ++c) 
      idctAV((float*)&arr[0], (float*)&output[0], (float*)&idctMat[0]);
	 
    auto end = high_resolution_clock::now();
    const auto result = std::accumulate(output.begin(), output.end(), 0.0);
    std::cout << result << std::endl;
    std::cout << duration_cast<milliseconds>((end - start) / cycles).count() << " ms" << std::endl;
Может быть я что-то напортачил с тайпкастами, я плохо знаю эти ваши плюсы. В моём примере проседания по скорости нет, там idctAV вызывается несколько раз, но как функция в DLL.
А ваш изначальный результат — это, как и следовало ожидать, невекторизованный код (простыня из vmovss/vmulss/vaddss).
gcc.godbolt.org/z/4jffcb89n
UFO just landed and posted this here
Опасается, что области памяти, с которыми работаем, могут пересекаться и векторизовать нельзя. Проанализировать код и понять, что нет — пока видимо ума не хватает.
__restrict как раз и говорит ему, что не пересекаются.
Статичные массивы вроде float arr[1024*1024*64] векторизует и так.
gcc.godbolt.org/z/5hP9vYanG

Кроме векторизации и аллокации регистров, где ещё человек может обойти компилятор?

UFO just landed and posted this here

Например, человек может понять, что за один проход цикла можно выполнить то, что делается в 2-х его проходах, и во 2-м проходе можно использовать другие регистры и выиграть до 50% на out-of-order-execution. Также транслятор пока не понимает, как можно ускориться, немного поменяв алгоритм, получив эквивалентное решение.

Я вот не слышал, что питон медленный, что я делаю не так?

Большинство тех, кто говорит что Python медленный из этих — «Слышал звон, да не знаю где он». Они просто где-то услышали что C++ быстрый, а Python медленный — и трезвонят на весь интернет об этом. При всем этом, они не знают, в каких случаях C++ может выиграть в производительности.
UFO just landed and posted this here
UFO just landed and posted this here

кстати, самый главный хейт забыли же — совместимость 2 и 3 версии :)

Наверное, каждый слышал, что Python медленный и уступает в скорости другим языкам по типу С++, С# и т.д.

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

На всё 100% уверен, что какой-нибудь убер-мастер питонист с 20-летним стажем может переписать и сделать всё по красоте, чтоб не тормозило. Однако, некоторые куски с питона были переписаны на C# далеко не сеньёрами буквально за неделю другую, и они работают по сей день без каких-либо проблем с памятью, скоростью, отвалами, наблюдаемостью. Никто туда не лезет, не ковыряет, не тюнит, не борется с GIL не подбирает фреймворк под задачи. Оно просто написано на дефолте, просто работает, и работает очень быстро.

Проблема питона не в том, что он медленный. А в обманчивых ожиданиях. Он идеален как скриптовой прикладной инструмент. Он часто плох как средство написание полноценных приложений.

Ещё немного в кассу

Давайте сравним, как я пишу код на С++:
И как его пишут дети:

Все подобные утверждения можно выкинуть на помойку. Если вы разрабатываете не в блокноте, любая IDE может отформатировать любой код в соответствие с заданными стандартами. Проверку форматтинга и авто-форматтинг можно настроить на любом уровне. Никаких преимуществ в навязанном способе форматирования исходников сегодня нет.

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

это выглядит как привычка работы с одним инструментом (я также могу сказать что на java можно только правильный и быстроработающий код писать и нигде более)


Я был как минимум на пяти крупных и нескольких буквально огромных проектов, написанных на питоне, и описанных вами проблем там не было, ни контейнеры не падали, ни интерфейс не тормозил (точнее то что там тормозило — тормозил в 95% случаев фронт сам по себе, а не бек)


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


я тыщу раз видел как даже топовые миддлы в джанговском орме на нагруженных проектах бездумно пишут prefetch на таблицах в миллионы записей и джойнят таблички ради одной записи… а потом все удивляются что контейнеры по памяти падают

При чём тут привычка? Мы в равной степени развиваем и сопровождаем проекты на Python и проекты на .NET. И у меня в такой ситуации есть довольно многогранная и полная картина, которая включает в себя:

  • производительность

  • стоимость владения тех. ресурсом

  • затраты на поддержку

  • затраты на техническое сопровождение (девопс, администрирование)

  • наблюдаемость

  • Т2М

  • уровень качества

И по всем этим пунктам проект на Python-е проигрывает.

Если вдаваться в детали, плюс историю, тут материала хватит на добрую книгу.

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

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

Всё есть из коробки. Буквально всё. И это всё работает сразу. Не нужно выбирать фреймворк. Он один, и он решает все задачи, от REST/API и генерации HTML страничек, до gRPC, WebSocket и т.д. И всё сразу асинхронно. Всё, по всей вертикали всех библиотек.

Разумеется я заангажирован в сторону .NET, не буду отрицать :) Но как тех. владелец продуктов и команды на Python, меня нисколько не радуют какие-либо проблемы в последнем. Я бы хотел, чтобы в нём было всё хорошо, быстро и стабильно. Но это пока к сожалению не так. Хотя успешные примеры я знаю, но всё же выгод от использования Python пока совсем не наблюдаю.

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

ИМХО конечно, не претендую на истину в последней инстанции :)

При чём тут привычка?

Разумеется я заангажирован в сторону .NET, не буду отрицать :)

я про это и говорю


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


это просто другой тип проектов, у меня тоже сначало очень сильно пекло когда я из мира java в питон переключился… и там есть жизнь и бизнес устраивает как это работает, потому что это быстрее выкатывается в прод, даже с такими косяками


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

Зачем хейтить 1С, если со своими задачами 1С великолепно справляется? :)
Делать микросервисы в здравом уме на 1С наверное никто не будет, а если вдруг начнёт и столкнётся с проблемами, сам виноват.

у них тольо несколько микросервисов были написаны на голанге и сях

Ну вот собственно и ответ. Теперь ради нескольких сервисов, в команде нужно держать ещё го/си разработчиков, да и ещё и интегрировать друг с другом совершенно разные миры.

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

Конечно, если есть проект на Python и команда, которая делает его быстро, качественно, оно при этом хорошо работает -- это просто замечательно и круто! Просто я такого не наблюдал в своей практике. Поэтому невольно сравниваю конечно. Вообще питон как ЯП люблю и уважаю. Но по мне как полноценный бекенд он используется не "благодаря", а "вопреки".

Ну вот собственно и ответ. Теперь ради нескольких сервисов, в команде нужно держать ещё го/си разработчиков, да и ещё и интегрировать друг с другом совершенно разные миры.

а это дешевле чем держать всю команду на голанге… также такие задачи можно на оутсорс отдавать


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

вот один из проектов где я был, его переписали сколько то лет назад с шарпа на питон, потому что спецы дешевле, доступнее и TTM у проекта быстрее...(про последнее у меня много матерных слов… это ЯП напрямую не касается… но повторюсь что для бизнеса это очень важный параметр)

У нас была задачка. В проекте на Python-е надо было принимать и отдавать очень много файлов, в пике тысячи транзакций, и десятки тысяч файлов в секунду. Такой трафик разрывал бекенд Python-а просто в клочья. Разнести по нескольким экземплярам -- это ещё плюс новая задача по синхронизации данных в транзакции. В общем месяц бились, мыкались. Безрезультатно. В итоге вынесли функцию и запилили сервис на .NET примерно за 3-4 дня. До сих пор работает, в одно рыло играючи обрабатывает трафик, полностью асинхронно, да ещё и полная наблюдаемость бонусом: метрики, трассировка, структурные логи, хелсчеки из коробки, работает в контейнере, масштабируется (но это не понадобилось). Никаких проблем за всё время работы не наблюдалось.

Вот вам и Т2М.

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

по этому такие узкоспециализированные сервисы пишут на других языках в питоновских проектах


у меня в одном из огромных проектов (которые я упоминал), тоже была задачка подгрузки и обработки файлов (xml), и для этого у нас был golang сервис который их лопатил и грузил в промежуточную базу… чтобы прддерживать адекватную производительность на прием данных… а вот уже обрабатывал подгруженные данные кластер из десятка питоновских микросервисов


тут правильно упоминали что корни этого растут из питонячего gil-а и проблем синхронизации


В итоге вынесли функцию и запилили сервис на .NET примерно за 3-4 дня

забавно было бы в команде где все питон разработчики запилить за 3-4 дня сервис на дотнете ;)
у нас на голанге его написали просто потому что один из сеньоров для саморазвития его учил… я потом этот сервис немного поддерживал плюясь от того что там все ноги себе поотстрелить себе можно из-за того что "та ерунда, горутины всех спасут, забъем на контроль повисших процессов волшебная гошечка всех спасет… только в яве этим морочатся" (а потом сервис падает когда 200гигабайт оперативки у сервера заканчивается)… тьфу блин… я единственный наверное был во всей конторе кто прочитал книжку по многопоточному программингу

по этому такие узкоспециализированные сервисы пишут на других языках в питоновских проектах

Я собственно об этом и вещаю. Чтоб пилить эффективные производительные приложения на бекенде, вам одного питона может быть недостаточно. А сравниваю с .NET-ом, так как это мой профиль, и ответственно заявляю, что одного .NET-а достаточно для того, чтобы писать производительный бекенд и писать его достаточно быстро, никакие костыли и вкрапления на каком-нибудь GoLang или на чем-либо ещё просто не нужны :)

В приложениях на .NET в качестве embedded-скриптов для написания логики на DSL легко встраиваются Lua, Python, JS (как DAG на AirFlow). По крайней мере такой опыт есть, вполне успешный.

забавно было бы в команде где все питон разработчики запилить за 3-4 дня сервис на дотнете ;)

Нет конечно, привлекли помощь из другой команды :)

тьфу блин… я единственный наверное был во всей конторе кто прочитал книжку по многопоточному программингу

Ну вообще, зачастую проблема не в ЯП, а в базовых знаниях. Писать плохо можно на чём угодно.

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

Бывают все же исключения. Для АСКУЭ пришлось, скрепя сердце, переписывать сервис с C# на C++. Логика там была такая, что сборщик мусора просто не успевал отрабатывать, а никакой возможности явно освободить занимаемую объектом память в C# нет. Можно было, конечно, свалиться на низкий уровень работы с памятью, отказавшись от объектно-ориентированного кода. Но с объектами все же кодировать проще.

Это наверное было давно. Современный C# умеет работать с массивами в стеке, есть динамические пулы памяти, каналы, пайпы, в общем всё хорошо щас с этим :)

Современный C# умеет работать с массивами в стеке

Так я это и написал:

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

Управлять памятью на низком уровне из C# Вы можете. Но как Вы к этому прикрутите уже имеющуюся иерархию классов, не считая даже множества пакетов, подключенных nuget? А в C++ у Вас всегда есть возможность вызвать деструктор и освободить память, занятую любым объектом.

P.S. Стек уж точно не выход для многопоточных конвееров.

Управлять памятью можно и нужно тогда, когда в этом действительно есть потребность. Есть множество великолепных примеров, например ASP.NET, gRPC, Yarp и т.д. Там где это действительно принесёт выгоды, можно перейти на более низкий уровень, задействовать специальные механизмы, при этом не слишком потеряв в удобстве.

Стек и пайпы, это выход для многопоточных конвееров. Например, мы перед продуктами, написанными на PHP и Python поставили программируемый прокси на .NET, чтобы компенсировать отсутствие нормального логирования и метрик, также дополнительный слой надёжности, лимитирование трафика, ретраи и CB. Прокси великолепно справляется с нагрузками в одного сразу для нескольких продуктов, при этом потребляя в среднем 30-40Мб вирт памяти. Да, у нас там кастомная логика на пути трафика, ООП все дела, никаких ограничений.

Работает изумительно.

Вы вообще о чем? Какое отношение имеет Ваш опус к утверждению, что из-за отсутствия понятия деструктора в C#, управлять памятью в нем можно только отказавшись от всей имеющейся иерархии классов?

Стек [...] это выход для многопоточных конвееров.

Вы вообще в курсе что такое стек, что он локален для процесса/нити и что управлять освобождением памяти в нем и повторно ее использовать штатными средствами невозможно? Или Вы собрались копировать петабайты в оперативке из стека одной нити в стек другой?

никаких ограничений.

Вы просто до них не дошли. Если у Вас действительно сложная логика в конвеере, при которой явно или не явно (например, увеличением длины строки) выделяется и помечается для освобождения память, то при повышении нагрузки в определенный момент точно так же сборщик мусора не будет успевать освобождать память и увидите катастрофический рост потребляемой памяти. После чего, в зависимости от корректности обработки исключения Out-of-Memory или его предсказания, весь сервис или навернется, или встанет колом на продолжительное время, пока GC не отработает.

То есть там, где сервис на C++ просто упрется в CPU и продолжит работу на максимуме своей производительности, сервис на C# наоборот, если не упадет, то покажет сильную деградацию производительности. Такова цена GC.

Можно сказать, что если у вас на бекенде .NET, то вам больше никто для бекенда не нужен.

Не утрируйте. Всему свое место. Например, поэтому DAG для Airflow всегда на Python, а кастомные классы для Confluent - на Java.

питон как ЯП люблю и уважаю

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

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

Не утрируйте. Всему свое место. Например, поэтому DAG для Airflow всегда на Python, а кастомные классы для Confluent - на Java.

Для аналитических задач Python просто идеален. Так мы его активно используем.

Я же говорил про разработку бекенд приложений, микросервисов. Зоопарк технологий там нафиг не нужен. Если у вас .NET, вам ничего не нужно. Более того, вы можете писать на других языках под тот же .NET, да хоть на PHP, если угодно :)

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

Типизация не самая большая проблема или достоинство, хотя именно про это почему-то часто говорят. В .NET можно писать с динамической типизацией. Можно писать под .NET на Python-е (IronPython), совмещая и статическую и динамическую типизацию.

Для аналитических задач Python просто идеален. Так мы его активно используем.

Опять, смотря каких. Он идеален до тех пор, пока не упираешься в GIL и печально наблюдаешь, как из 64 доступных ядер пашут, от силы, восемь.

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

Потому что при разработке она как раз не особо влияет на результат. А вот уже при поддержке в промышленной эксплуатации статическая типизация спасает от целого ряда проблем. Не зря же появился TS на замену JS и явно в него компилирующийся.

Если у вас .NET, вам ничего не нужно.

Опять утрируете. Будете что ли писать DAG для AirFlow на .Net? Или кастомный класс для Confluent на .Net? Или расширение/компилируемую функцию для PostgreSQL или ClickHouse? Не получится, так как архитектура уже накладывает ограничения.

Из .Net можно вызвать почти что угодно. Но если нужно подключить свою so/dll/jar и т.п. к уже имеющейся системе, извольте соответствовать её требованиям.

Я всё время говорил про написание отдельного приложения, сервиса, микросервиса. Это никак не противоречит использованию Python для DAG или хранимки на PL/SQL.

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

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

Например:

Я же говорил про разработку бекенд приложений

AirFlow, Kafka/Confluent, PostgreSQL и ClickHouse - все же компоненты именно бека.

Sign up to leave a comment.

Articles