Обновить
641.56

Python *

Высокоуровневый язык программирования

Сначала показывать
Порог рейтинга

Быстрая замена mypy на Rust'е: pyrefly

Еще одно видео про еще один новый тайпчекер для питона на расте! Много их нынче стало.

В видео:

  • Обсуждаем первую версию: pyre-check, обсудили taint analysis

  • Сравниваем pyrefly с ty и mypy

  • Смотрим на внутреннее устройство

  • Применяем на реальном проекте

Ключевые ссылки из выпуска:

Вывод: пока очень сырой, много багов, но быстрый. Ключевой вывод: отлично, что есть конкуренция.

Теги:
Всего голосов 7: ↑7 и ↓0+8
Комментарии1

Осваиваем азы компьютерного зрения с библиотекой Pillow на одноплатном компьютере Lichee Pi 4A

Наш первый шаг — загрузить изображение, определить его цветовую модель и получить информацию о размере и границах.

from PIL import Image
from PIL import ImageFilter
img = Image.open(“flower.jpg”)
print(img.size, img.format, img.mode)

Эта базовая информация пригодится для дальнейшей работы с изображением.

Меняем цвет пикселя

К отдельным пикселям можно обращаться с помощью метода load() из библиотеки Pillow. Так мы сможем изменять цветовые значения точечно, а это основа для различных операций по обработке изображений.

Открываем white.jpg с помощью Pillow:

from PIL import Image
img = Image.open("white.jpg")
obj = img.load()

Выбираем пиксель с координатами (25, 45) и меняем его цвет:

obj[25, 45] = (0, 0, 0)  # Новый цвет: черный (RGB: 0, 0, 0)

Сохраняем отредактированное изображение:

img.save("image3.jpg")

Визуально проверяем, что цвет пикселя изменился. 

Метод load() позволяет напрямую работать с массивом пикселей изображения: читать, модифицировать и анализировать отдельные элементы, не копируя данные в отдельные структуры. Это особенно важно для задач, которые требуют высокую производительность при обработке больших изображений.

Почему был выбран Lichee Pi 4A, как создать виртуальное окружение Python, установить подходящую среду разработки и научиться базовым приемам работы с изображениями — читайте в подробном туториале.

Теги:
Всего голосов 6: ↑6 и ↓0+7
Комментарии1

Привет, меня зовут Александр, я аналитик в Альфа-Банке. Однажды я устал, что на Feature Store, на платформе для дата-инженеров (DE) и дата-саентистов (DS), невозможно ничего найти.

Поиск по контексту отсутствует. Приходится руками шерстить огромное количество ETL-проектов в поисках той самой полезной информации, полагаясь сначала на удачу, а после — на опыт и помощь коллег. 

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

И я сделал MVP с GPT-2: весит около ~400 МБ и, самое главное, не требует регистрации. В статье пошагово описал, как всё прикрутить. Заходите почитать.

Примечание. Для прома MVP, конечно, не прокатит, но после показа решения начали реализовывать решение на OpenSearch.

Теги:
Всего голосов 3: ↑3 и ↓0+3
Комментарии1

IMPulse - менеджмент инцидентов. Интеграция с Google Calendar, вложенные цепочки эскалации.

Предыдущие публикации:
https://habr.com/ru/articles/865208/
https://habr.com/ru/posts/889768/

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

Помимо интеграции с Google Calendar, мы реализовали вложенные цепочки эскалации. Теперь в chain можно добавить другой chain (nested), благодаря чему размер конфигурационного файла уменьшится.

Мы хотим создать достаточно гибкую, но не перегруженную систему цепочек эскалации, чтобы на проектах разной величины вы могли использовать IMPulse так как вам удобно. Для этого в комментариях расскажите, какой самый сложный кейс уведомлений / эскалации вам необходимо было реализовать. Например: во вторник нужно дёргать Антона, через 5 минут Олега, а по средам - только дёргать Геннадия, в остальное время, если severity == 'critical', звонить Грише.
Будем рады почитать самые сложные варианты и предложить наше универсальное решение для них.

Остаёмся на связи в нашем Telegram канале - там можно общаться / задавать вопросы.

Теги:
Всего голосов 1: ↑1 и ↓0+2
Комментарии0

Всем привет!

Представляю вам мой новый проект: Terpinal.

Также я называл его "терпи нал".

Это терминальная операционная система для Raspberry Pi Pico. Который выводит на SSD1306.

Вот ссылка:

https://github.com/SystemSoftware2/Terpinal

Прочитайте README.md и узнайте что и как подключить.

Также я называю операционку как PicoOS Firmware (не знаю почему так).

Теги:
Всего голосов 1: ↑0 и ↓1-1
Комментарии3

Инженерной боли пост. С надеждой на дельные советы

Все началось с pet-проекта, который использовал polars(сорцы) и должен был крутиться в Docker на моем домашнем NAS, в следующей конфигурации:

Спойлер: принципиальное решение проблемы - найдено. Купил маленькую коробочку на "мейнстримной" архитектуре, на которой все цветет и пахнет.. кроме моего внутреннего(ну и внешнего, че уж там) инженера) Так что решение выкинуть железку - можно не предлагать

Так вот, пока я писал код, и готовил сборочные скрипты ничто не предвещало беды - я спокойно потестил код локально, написал Dockerfile для сборки на poetry. Настало время развернуть это все на NAS - казалось бы ARM уже давно мейнстрим, но тут понеслось

  1. python как всегда лишь удобный биндинг к куче платформозависимого кода) подавляющее большинство python-зависимостей под arm/v7 приходится компилировать

  2. готовых бинарников polars под arm/v7 - тоже нет

  3. Никаких блокеров к тому, чтобы собрать polars под arm/v7 я не нашел. Но скомпилить его нативно на 4Гб ОЗУ - не получится, даже с минимальными оптимизациями. Нужна кросс-компиляция. Благо с rust и maturin(которым собирается polars) - это несложно, target armv7-unknown-linux-gnueabihf в хорошем tier-е поддержки

  4. забегая чуть вперед указываем окружение для сборки аллокатора jemalloc(по умолчанию в polars) под 32k страницу

Итак, усложняем сборку Docker(см. repro) - используем кросс-компиляцию, энв-переменные, QEMU, охапку дров и теперь у нас есть приложка, которая успешно стартует в докере на целевой железке. Вот только за рамками самых примитивных тестов - OOM-ится, причем память точно есть, никакой OOM-киллер процесс не убивает(на всякий случай смотрим лимиты cgoup) - оно "шамо":

memory allocation of 1345920 bytes failed

(подробные логи можно посмотреть по ссылкам в конце поста)

Что же делать?

  1. пробуем mimalloc - он использует для конфигурации рантайм(getconf), эффект - тот же

  2. пробуем env-крутилки, в частности arena_reserve может стоит просто меньше резервировать - но нет, просто больше попыток, но по факту все равно OOM

  3. помимо jemalloc и mimalloc не работают также: стандартный аллокатор rust(чем бы он ни был), libc-аллокатор и версия mimalloc, установленного как системная библиотека

И вот на этом месте я застрял. Я не большой спец по системному программированию - не понимаю куда копать

  • Общение с поддержкой QNAP свелось к

    Справедливости ради они еще дали советов что попробовать, но это я уже попробовал до них
    Справедливости ради они еще дали советов что попробовать, но это я уже попробовал до них
  • Пытался отлаживать приложение в gdb - никаких аномальных трейсбэков во время OOM не увидел: rust честно пытается аллоцировать большой raw_vec(трейс есть в вопросе на stackoverflow)

  • Как-то глубоко копать переменные не получается, т.к. дебаг-символы для бинарника polars получаются слишком большими

    BFD: error: /app/.venv/lib/python3.12/site-packages/polars/polars.abi3.so(.debug_str) is too large (0x498a9fd1 bytes)

  • Я сделал небольшое repro на голом расте - там эта проблема не воспроизводится, значит базово бинарная совместимость - в порядке

  • Есть несколько гипотез, но я не знаю как их проверить

    • возможно, кривая вся адресация, но ее проверить я тоже не могу

    • возможно, стоит чего-нибудь половить в ядре bpf-ом, но что..

    • кастомное ядро 4.2.8 кастомный дистриб(QTS) не богат средствами отладки - как я понял там запускается busybox набор утилит

В итоге я завел

Но активности там не очень много(

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

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

Теги:
Всего голосов 1: ↑1 и ↓0+1
Комментарии2

unraisable exceptions в питоне

Мы все с вами привыкли, что в питоне можно "зарайзить" исключение в любой момент: raise Exception
Но, что если в какой-то момент времени мы не можем вызывать исключение?

Простейший пример: что произойдет при запуске такого скрипта?

# ex.py
class BrokenDel:
    def __del__(self):
        raise ValueError('del is broken')

obj = BrokenDel()
del obj
print('done!')  # будет ли выведено?

Тут может быть два варианта:

  1. Или del вызовет ValueError и программа завершится

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

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

» python ex.py
Exception ignored while calling deallocator :
Traceback (most recent call last):  File "/Users/sobolev/Desktop/cpython/ex.py", line 3, in __del__    raise ValueError('del is broken')
ValueError: del is broken
done!

Знакомьтесь – unraisable exceptions 🤝

Как оно работает?

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

static void
list_dealloc(PyListObject *op)
{
    Py_ssize_t i;
    PyObject_GC_UnTrack(op);  // убираем объект из отслеживания gc
    if (op->ob_item != NULL) {
        i = Py_SIZE(op);
        while (--i >= 0) {
            // уменьшаем счетчик ссылок каждого объекта в списке
            Py_XDECREF(op->ob_item[i]);  
        }
        op->ob_item = NULL;
    }
    PyObject_GC_Del(op);
}

А, как вы можете знать, чтобы в C коде вызвать ошибку, нужно сделать две вещи:

  • Взывать специальное АПИ вроде PyErr_SetString(PyExc_ValueError, "some text")

  • И вернуть NULL как PyObject * из соответствующих АПИ, показывая, что у нас ошибка. Если вернуть NULL нельзя, то мы не можем поставить ошибку в текущий стейт интерпертатора. А тут у нас void и вернуть вообще ничего нельзя. Потому приходится использовать вот такой подход с unraisable exception

Ошибку мы "вызываем" через специальные АПИ:

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

В питоне оно используется где-то 150 раз. То есть – прям часто. Примеры:

  • Ошибки при завершении интерпретатора, попробуйте сами:

import atexit
def foo():
    raise Exception('foo')
atexit.register(foo)
  • Ошибки внутри sys.excepthook

  • Ошибки внутри gc

  • Ошибки внутри логики установки ошибок (вдруг память кончилась, например) 🌚️️️️

  • И многое другое

Пользовательское АПИ

Ну и конечно же, есть специальный хук для обработки таких ошибок: sys.unraisablehook

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

Например, pytest использует кастомный хук, чтобы валить тесты при возникновении такой ситуации. Что логично.

Нравится контент про технику и устройство технологий? Присоединяйся к каналу @opensource_findings в телеге; там много такого.

Обсуждение: знали ли вы про такую особенность? Приходилось ли где-то в мониторинге особо настраивать?

Теги:
Всего голосов 9: ↑8 и ↓1+10
Комментарии1

Я сделал своего первого Telegram-бота — WebCheck. Мониторинг сайтов прямо в Telegram⁠⁠

Привет!

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

Знакомьтесь: WebCheck — бот, который следит за доступностью сайтов, SSL-сертификатами и доменами.

🧠 Что умеет бот

  • Проверяет, доступен ли сайт (HTTP-код);

  • Показывает, сколько дней осталось до окончания SSL-сертификата;

  • Проверяет, когда истекает регистрация домена;

  • Присылает уведомление, если:

    • сайт стал недоступен;

    • до окончания SSL-сертификата осталось 14 дней или меньше;

    • до окончания регистрации домена осталось 14 дней или меньше;

  • Позволяет экспортировать логи и список сайтов в CSV;

  • Есть админ-интерфейс для контроля всех добавленных сайтов.

⚙️ Как пользоваться

  1. Открываете бота 👉 @ITSync_WebCheckBot

  2. Жмёте «Start» или пишете /start

  3. Просто отправляете ссылку на сайт (например: example.comozon.ru или https://wildberries.ru)

  4. Получаете оповещения, если с ресурсом что-то не так

Бот абсолютно бесплатный, ничего не требует — просто добавил сайт, и бот сам всё контролирует.

👨‍💻 Технически

Бот написан на Python с использованием:

  • aiogram v3

  • PostgreSQL

  • APScheduler

  • Shell-команд (whois, curl, openssl) для большей точности

Контейнеризирован в Docker, база хранится вне контейнера, а вся логика максимально простая и прозрачная.

🔐 А ещё я сделал бот для дешифровки VNC

Если вдруг работаете с .vnc файлами или UltraVNC — может пригодиться мой мини-инструмент:
@DecryptVNC_bot — он расшифровывает VNC-пароли прямо в Telegram.

🙏 Буду рад, если протестируете

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

Спасибо, что прочитали.
Бот тут 👉 @ITSync_WebCheckBot
И ещё один на всякий 👉 @DecryptVNC_bot

Теги:
Рейтинг0
Комментарии0

Новый тайпчекер для Python от авторов ruff и uv, написанный на Rust

Вышло видео про новый тайпчекер и lsp: ty (старое название red-knot) от авторов ruff и uv. Пока по первым впечатлениям – бомба! Не смотря на версию 0.0.0a8 🌚

Из плюсов:

  • Быстрый

  • На расте

  • Куча новых фичей для типов

  • Полная спецификация

  • Интеграция с ruff и IDEшками

Из минусов:

  • Пока есть баги (но их поправят, конечно же)

  • Нет плагинов (и скорее всего никогда не будет)

  • Софт от молодой и маленькой компании

  • Как сделать поддержку ty и mypy вместе? А если использовались ty_extensions?

Обсуждение: а как вам проект? Успели попробовать?

Теги:
Всего голосов 8: ↑8 и ↓0+10
Комментарии1

Представлен бесплатный гайд по изучению языка программирования Python за 100 дней от истории создания языка и его работы на уровне процессора и памяти до мощнейших фреймворков и комплексных алгоритмов. Задачи равномерно распределены. Каждый урок объёмный и разжеван досконально — поймет даже полный нуль в кодинге. Любое объяснение подкрепили примерами кода.После разделов есть сборники задач разного уровня сложности, чтобы железно зафиксировать знания.

Теги:
Всего голосов 2: ↑1 и ↓1+2
Комментарии4

PEP 750: t-строки в 3.14

Недавно ревьюил один интересный PR в CPython: в питон добавили еще один способ форматировать строки. Теперь – со специальным АПИ для внешних интеграций. Расскажу: как и зачем.

Основная причина: использовать f строки удобно, но нет никакого АПИ для перехвата момента "вставки" или интерполяции значений. Например, при форматировании html или sql – требуется специальным образом делать escape для значений. И раньше код вида f"{template}" представлял собой дыру в безопасности и потенциальное место для XSS.

string.templatelib.Template

Новый префикс t не будет создавать объект str, он будет создавать объект класса string.templatelib.Template:

>>> user = 'sobolevn'
>>> template = t"Hi, {user}"
>>> template
Template(strings=('Hi, ', ''), interpolations=(Interpolation('sobolevn', 'user', None, ''),))

>>> from string.templatelib import Template
>>> isinstance(template, Template)
True

Обратите внимание, что при создании template – у нас не произошло форматирование сразу. Мы создали объект, у которого есть свойства strings и interpolations, из которых можно собрать финальную отформатированную строку.

Давайте посмотрим на примере. Допустим, мы хотим формировать URL из наших данных:

>>> domain = 'example.com'
>>> query = 'python string formatting is too complex'
>>> template = t'https://{domain}?q={query}'

И сам код логики форматирования, где мы будем вставлять значения разным способом. Если у нас шаблон query, то мы будем использовать quote_plus для его форматирования. Остальные значения – будем вставлять как есть:

>>> from string.templatelib import Template, Interpolation
>>> from urllib.parse import quote_plus

>>> def format_url(template: Template) -> str:
...     parts = []
...     for part in template:
...         match part:
...             case str() as s:  # regular string
...                 parts.append(s)
...             case Interpolation(value, expression='query'):
...                 parts.append(quote_plus(value))
...             case Interpolation(value):
...                 parts.append(value)
...     return ''.join(parts)

И вот результат:

>>> format_url(template)
'https://example.com?q=python+string+formatting+is+too+complex'

Только теперь наш Template был отформатирован. Нами. Ручками.
У нас есть полный контроль за процессом форматирования. Вот в чем суть данного ПЕПа.

Фичи одной строкой

  • Работает = как обычно в f строках: t'{user=}'

  • Есть привычные определители формата: !r, !s, .2f, тд

  • t строки можно конкатенировать: t'Hello' + t' , world!' и t'Hello, ' + 'world'

  • Поддерживается режим raw строк: rt"Hi \n!"

Как устроено внутри?

Интересные места имплементации:

>>> import dis
>>> user = 'sobolevn'
>>> dis.dis('t"Hi, {user}"')
  0           RESUME                   0

  1           LOAD_CONST               2 (('Hi, ', ''))
              LOAD_NAME                0 (user)
              LOAD_CONST               1 ('user')
              BUILD_INTERPOLATION      2
              BUILD_TUPLE              1
              BUILD_TEMPLATE
              RETURN_VALUE

Обсуждение: как вам еще один способ форматирования строк?

Если понравилось – заходи в тг, где я рассказываю, как я делаю CPython.

Теги:
Всего голосов 10: ↑10 и ↓0+13
Комментарии7

Я доделал компилятор C на Python.

Баги всё ещё есть но их намного меньше

Его я назвал pycc.

Если хотите попробовать, вот гитхаб: https://github.com/SystemSoftware2/pycc

Всё остальное смотрите там.

[UPD]: А за что минусуете?

Теги:
Всего голосов 7: ↑6 и ↓1+6
Комментарии2

Всем привет.

Как вы знаете я пишу компилятор C на Python.

Сегодня я исправил баг с типизацией, который случайно нашёл когда делал ошибки.

Вот этот отрывок: void main() { int x = "h"; } обрабатывался как правильный синтатикс. Теперь нет.

И я добавил цикл do-while. Правда в нём есть проблема: в конце если выражения = false то он ещё раз выполняет и потом останавливает цикл do-while. Ну, пока что так.

Пример цикла do-while:

void main() {
  int a = 10;
  do {
    a = a + 1;
  } while (a > 2);
}

Только вывод не то что "a" это 1 а 0. Правда, сил нету добавлять ненужные части кода для исправления.

Ну. Хотя бы работает как то. А то когда в первый раз делал этот цикл то вообще нечего не работало.

Всем пока.

Теги:
Всего голосов 4: ↑3 и ↓1+3
Комментарии0

Ближайшие события

Снова всем привет. В прошлом посту я писал о том что пишу компилятор C (на Python).

Вчера я добавил функции, вот пример программы вычисления факториала с функциями:

void fac(n) {
  int f = 1;
  while (n > 1) {
    f = f * n;
    n = n - 1;
  }
}

void main() {
  fac(5);
}

Что можно заметить нового и чего нету:

  • Функция main стала обязательной

  • Не обрабатывается тип данных у аргументов (не везде)

  • Все переменные и параметры - глобальные

  • Оператора return не существует

  • Функции объявляются только с помощью void

Вот как компилятор создаёт функции:

  1. Добавляет в словарь self.funcs данные о функции

  2. Когда видит вызов функции то компилирует код функции но перед компиляцией создаёт переменные со значениями аргументов

Получается мы не заставляем виртуальную машину работать с функциями ВООБЩЕ.

Но и в этом есть свой минус: return сделать будет невозможно.

Самым сложным это сделать нормальный парсер для этого чуда.

Из-за этого я испортил код парсера. Главное работает 😅.

Всем пока.

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0

От картотеки Лумана к современным графам: учим языки программирования с методом Цеттелькастен

В середине XX века социолог Никлас Луман разработал метод организации информации Цеттелькастен (Zettelkasten). Он создавал множество заметок и, чтобы не терять знания, начал вести картотеку. Система нумерации и ссылок помогала ориентироваться в карточках. У каждой заметки был уникальный номер, отражающий тему и дополнения.

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

Все заметки Дмитрия в виде графа
Все заметки Дмитрия в виде графа

Веб-разработчик в YADRO Дмитрий сохраняет заметки в сервисе Obsidian. Дмитрий услышал о ПО от инженера и блогера Николая Тузова и понял, что система, похожая на картотеку, ему близка.

Программа оказалась понятной, легко адаптируемой под разные задачи. Когда Дмитрий перенес данные из Notion в Obsidian, образовалось несколько графов: по Go, хешированию и базам данных. В этой базе знаний все концепции в Go пересеклись в двух точках — интерфейсе и горутинах. Есть еще слайсы, но в основном все «лучи» сходятся именно в эти две точки. 

Как Дмитрию удалось упорядочить большие объемы знаний и кому он рекомендует Цеттелькастен, читайте в статье →

Теги:
Всего голосов 4: ↑3 и ↓1+3
Комментарии2

Всем привет.

Сегодня на данный момент я пишу компилятор C в байткод.

Вы скажете: но C же в машинный код компилируется? В моём случае нет. Лишь в байткод.

Вот правила которые мой C поддерживает:

  • цикл do-while, цикл while, условие if-else, цикл for (возможно)

  • Из операций: +, -, /, *, ==, !=, <, >

  • Декларация переменных только с инициализацией (не int x;) а (int x = 5;)

  • Присваивание (типо a = a + 1;) можно при созданной переменной

  • Из типов данных только два: int, char

  • Функции не обещаю но возможно будут

А то что уже есть:

  • if-else, while

  • Декларация переменных

  • Присваивание переменных

  • Все типы данных

  • Все операции

Сделать факториал уже можно. Вот пример факториала 5:

int n = 5;
int f = 1;
while (n > 1) {
  f = f * n;
  n = n - 1;
}

Вывод:

Execution finished
n: 0
f: 120

Вот как он работает:

  • С помощью регулярок лексер получает нужный токен и тег

  • Парсер строит AST

  • Компилятор делает байткод

  • Виртуальная машина выполняет его

Вот так всё работает.

Все инструкции байткода (на данный момент):

FETCH переменная - положить на стек значение переменной
PUSH число - положить на стек число
POP - я не помню зачем это ведь это не нужно будет нам
ADD, SUB, MUL, DIV - бинарные операции
NOTEQ, EQ, LT, GT - реляционные операции
JMP адрес - перейти по адресу
JNZ адрес - перейти по адресу если на вершине стека не 0
JZ адрес - перейти по адресу если на вершине стека 0
PASS - игнорировать
STORE имя - сделать переменную если она есть и её тип данных
      соответствует типу данных значения
TSTORE имя - декларация переменной
HALT - конец программы

Вот так. На данный момент в проекте где-то 400 строчек кода но это с комментариями и всеми пустыми строками.

Конец. Всем пока.

Теги:
Всего голосов 3: ↑3 и ↓0+4
Комментарии1

Опубликовано исследование о том что индексирование сайтов поисковиком (Google) не зависит от того, SPA ли это или же он SSR. Также пару лет назад делал аналогичное расследование и пришел к тому же выводу.

Вообще, мы пришли к идеалу достаточно давно - когда сервер занимается своими делами, а клиент статический, минифицирован, и раздается из CDN для быстроты и без траты ресурсов сервера.

https://vercel.com/blog/how-google-handles-javascript-throughout-the-indexing-process

Теги:
Всего голосов 2: ↑2 и ↓0+2
Комментарии9

Программирование на квантовом компьютере. Урок 1

В данной статье мы рассмотрим только как запустить программный код на симуляторе квантового компьютера (локально на вашем компьютере).

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

Теги:
Всего голосов 5: ↑1 и ↓4-3
Комментарии0

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

Не очень было понятно, как можно извлечь эту информацию из самого Питона, не заглядывая в готовые таблицы соответствия (это было бы скучно). Тем более, что на самом деле Питон много чего оптимизирует, и на самом деле при сложении двух сущностей обычно не будет вызван метод __add__, а в байткоде сгенерируется вызов BINARY_ADD, в чём можно легко убедиться с помощью модуля dis (если речь не о самописном классе с перегруженным методом __add__, а о каких-то стандартных объектах Питона). Например, сложим два списка через + и через __add__ и посмотрим, какой байткод будет сгенерирован.

import dis

dis.dis("first_list = [1, 2]; second_list = [3, 4]; final_list = first_list + second_list")
# Только самое существенное в выводе:
#             16 LOAD_NAME                0 (first_list)
#             18 LOAD_NAME                1 (second_list)
#             20 BINARY_ADD

dis.dis("first_list = [1, 2]; second_list = [3, 4]; final_list = first_list.__add__(second_list)")
# Опять же самая суть:
#             16 LOAD_NAME                0 (first_list)
#             18 LOAD_METHOD              2 (__add__)
#             20 LOAD_NAME                1 (second_list)
#             22 CALL_METHOD              1

И тут я вдруг вспомнил про стандартный модуль operator, в который зашиты все возможные операторы Питона именно в виде именованных методов как с двойным подчёркиванием, так и без оного. После небольшого исследования оказалось, что в нём каждый такой метод имеет строку документации, в которой таки написано что-то типа "Same as a + b." ("Тоже самое, что a+b.")

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

# Модуль operator содержит методы, аналогичные встроенным методам Питона и методам классов Питона
import operator
import re

# Будем искать в докстрингах методов фразу "Same as" ("То же, что и")
rx = re.compile('Same as (.*)')

# Перебираем имена модуля operator
for name in dir(operator):
    
    # Нас интересуют только имеющие двойное подчёркивание в названии
    if '__' in name:
        
        # Берём аттрибут модуля operator с таким именем
        attr = getattr(operator, name)
        
        # Читаем его docstring и ищем там фразу (см. выше)
        descr = rx.findall(attr.__doc__)
        
        # Если фраза нашлась, то она там одна и заканчивается она точкой, которая нам не нужна
        if descr:
            print(f'{descr[0][:-1]} -> {name}')

Получилось такое соответствие.

abs(a) -> __abs__
a + b -> __add__
a & b -> __and__
a + b, for a and b sequences -> __concat__
b in a (note reversed operands) -> __contains__
del a[b] -> __delitem__
a == b -> __eq__
a // b -> __floordiv__
a >= b -> __ge__
a[b] -> __getitem__
a > b -> __gt__
a += b -> __iadd__
a &= b -> __iand__
a += b, for a and b sequences -> __iconcat__
a //= b -> __ifloordiv__
a <<= b -> __ilshift__
a @= b -> __imatmul__
a %= b -> __imod__
a *= b -> __imul__
a.__index__( -> __index__
~a -> __inv__
~a -> __invert__
a |= b -> __ior__
a **= b -> __ipow__
a >>= b -> __irshift__
a -= b -> __isub__
a /= b -> __itruediv__
a ^= b -> __ixor__
a <= b -> __le__
a << b -> __lshift__
a < b -> __lt__
a @ b -> __matmul__
a % b -> __mod__
a * b -> __mul__
a != b -> __ne__
-a -> __neg__
not a -> __not__
a | b -> __or__
+a -> __pos__
a ** b -> __pow__
a >> b -> __rshift__
a[b] = c -> __setitem__
a - b -> __sub__
a / b -> __truediv__
a ^ b -> __xor__

К чему это всё? Да просто люблю исследовать Питон. Благо он позволяет легко извлекать из себя и обрабатывать такие штуки, которые из других языков бывает довольно непросто вытащить даже с применением каких-то специальных библиотек. А в Питоне всё это стандартными методами и встроенными библиотеками делается буквально в несколько строк кода.

Спасибо за чтение.

Теги:
Всего голосов 5: ↑5 и ↓0+5
Комментарии0

Напоминаем, что в Академии Selectel можно пройти бесплатный курс «Изучаем Python: теория, практика, настройка инструментов».

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

Что будем делать:

✅ настроим инструменты разработчика — уделим внимание связке IDE и Python;

✅ поработаем с базами данных и брокерами сообщений — будем писать запросы SQL;

✅ создадим приложения с графическим интерфейсом — нарисуем виджеты, выведем диалоговые окна;

✅ научимся автоматизировать получение данных — попрактикуемся и с Request, и с Selenium.

Без задач для практики тоже не останетесь!

Но и это не все! Поделимся записями докладов Python Meetup. Дадим подборку для дальнейшего изучения.

Все материалы бесплатные. Не требуется даже регистрация.

Изучить курс в Академии Selectel

Теги:
Всего голосов 1: ↑1 и ↓0+2
Комментарии0

Вклад авторов