Получи случайную криптовалюту за регистрацию!

Python Заметки

Логотип телеграм канала @pythonotes — Python Заметки P
Логотип телеграм канала @pythonotes — Python Заметки
Адрес канала: @pythonotes
Категории: Технологии
Язык: Русский
Количество подписчиков: 2.71K
Описание канала:

Интересные заметки и обучающие материалы по Python
Контакт: @paulwinex
Хештеги для поиска:
#tricks
#libs
#pep
#basic
#regex
#qt
#django
#2to3
#source
#offtop

Рейтинги и Отзывы

3.00

3 отзыва

Оценить канал pythonotes и оставить отзыв — могут только зарегестрированные пользователи. Все отзывы проходят модерацию.

5 звезд

0

4 звезд

2

3 звезд

0

2 звезд

0

1 звезд

1


Последние сообщения 3

2021-11-26 12:01:37 В модуле logging предусмотрен немного необычный способ форматирования строки без форматирования.

logging.info('Message %s %s', arg1, arg2)

На самом деле, если вы его не используете то вы делаете неправильно!

Если вам требуется указать в строке сообщения какой-либо аргумент то обычно это делается форматированием строки

logging.info('New value is %s' % value)

Или любой другой доступный нам способ

logging.info(f'New value is {value}')
logging.info(f'{value=}')

Кажется, всё логично, все так делают. Но нет, это ошибка!

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

logging.debug(f'Current user: {user}')

Что произойдет?
Сообщение не попадает под установленный уровень логирования и будет проигнорировано. Это обрабатывается сразу же первой командой в вызываемой функции debug. Но при этом форматирование строки всё равно произойдёт!
И проблема не в самом форматировании, которое достаточно быстрое (даже при складывании строк через "+"), а в тех возможных действиях, которые придется вызвать для преобразования объекта user в строку.

Возможно, там будет запрос в БД, разбор больших массивов данных или еще что-то не очень быстрое (или не очень умное ).
Нам всё это придётся посчитать чтобы потом.....ничего с этим не сделать.

Поэтому правильно писать так:

logging.debug('Current user: %s', user)

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

#libs #tricks
620 views09:01
Открыть/Комментировать
2021-11-22 12:02:15 Модуль pythonnet позволяет интегрировать ваш код на Python с .NET приложениями.
Например, запускать Python модули внутри .NET или импортировать DLL библиотеки в Python.

Вики по модулю
Урок на гитхабе
Пара примеров использования

Пример от меня:
Использование библиотеки от всем известного софта мониторинга Open Hardware Monitor.
Когда его скачаете, обнаружите там библиотеку OpenHardwareMonitorLib.dll. Вот она нам и нужна!

Для начала поставьте модуль pythonnet

pip install pythonnet

Если установка завершилась ошибкой, скорее всего ваша версия Python еще не поддерживается. Поищите WHL здесь. А потом устанавливайте так:

pip install ...\2.5.2-cp39-cp39-win_amd64.whl

Либо попробуйте другую версию Python.

Теперь нам доступен модуль clr (Common Language Runtime) с помощью которого можно делать DLL доступными для импорта

import clr
from pathlib import Path
clr.AddReference(str(
Path('OpenHardwareMonitorLib.dll').absolute()
))

Предполагается, что библиотека лежит в текущей рабочей директории

Вот и всё, можно импортировать и использовать

from OpenHardwareMonitor.Hardware import Computer
c = Computer()
c.CPUEnabled = True
c.GPUEnabled = True
c.RAMEnabled = True
c.HDDEnabled = True
c.Open()
for hw in c.Hardware:
print(hw.Name)
c.Close()

Теперь можете делать свою мониторилку ресурсов. Например вот так можно считывать данные сенсоров

...
for hw in c.Hardware:
hw.Update()
for sensor in hw.Sensors:
print(sensor.Identifier, sensor.get_Value())
...

Здесь hw.Update() нужен для обновления данных сенсоров на текущий момент, на случай если у вас бесконечный цикл опроса сенсоров.
__________________
PS. Некоторые устройства для получения полной информации требуют запуска от имени администратора.
Например, если видите в списке устройств некий Generic Hard Disk или запрос значения сенсора вернуло None, то это как раз тот случай.

#libs
544 views09:02
Открыть/Комментировать
2021-11-08 12:01:57 ­Размышления насчет ускорений Python идут полным ходом. Прежде всего идут рассуждения о выпиливании GIL, не без участия Гвидо.

Но никто не отменял ускорение выполнения задач через распараллеливание различными способами. Лично я часто использую threading и multiprocessing для массовой обработки картинок или многопоточной закачки файлов. Для фоновой очереди задач использую Celery а для высоконагруженного распределённого рендеринга у меня в арсенале RenderManager'ы Afanasy и Deadline.

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

Вы наверняка знаете что Github полон самыми разными Awesome-листами. Есть даже топик Awesome Lists с подборкой этих списков.
Решил я там поискать какой-то список решений для параллельных/распределённых вычислений на Python. Нашел несколько ссылок в основном Awesome-списке по Python. Не густо , список для С++ и того побольше будет.

В общем, покопавшись немного в сети, нашел-таки подобный список и для Python - Parallel Processing and Multiprocessing in Python. Интересная подборка модулей, есть на что залипнуть!
Вот бы кто запилил нормально на Github в awesome-parallel-computing, как это сделано в Awesome Asyncio.

#libs
982 views09:01
Открыть/Комментировать
2021-10-28 09:00:24
Базы данных & SQL - канал для тех, кому интересна сфера Баз данных.
Здесь ежедневно выкладывают обучающие материалы, новости и статьи о СУБД, языках запроса, методах сбора и обработке данных, которые будут полезны как для новичков, так и для опытных специалистов.

Материалы для знакомства с каналом:
° Учимся применять оконные функции
° Как подружить Python и базы данных SQL
° Многотабличные запросы. Оператор JOIN

Подписаться: @db_in_it
688 viewsedited  06:00
Открыть/Комментировать
2021-10-18 12:00:21 Все уже успели обсудить новые фишки в Python 3.10, такие как ускорение работы базовых типов, удобная типизация и особенно новый паттерн матчинг.
Только ленивый не рассказывал про паттерн матчинг!
Давайте я прикинусь ленивым (но это не так ) и не буду повторяться. Расскажу про другое нововведение.
В противовес мега полезному pattern matching эта штука, на первый взгляд, имеет сомнительную полезность

В Python 3.10 у типа int появился новый метод int.bit_count().
Что он делает? Возвращает количество единиц в битовом представлении числа.
Что? Зачем? Почему?

Это не bit_length(), возвращающий количество бит, необходимых для записи данного числа.
И это не struct.calcsize(I), возвращающий количество байт, в которые точно поместится любой int.
Зачем нам количество ненулевых бит в битовом представлении? Особенно когда новый метод это просто эквивалент строки:

bin(num).count("1")

Цитата из слов автора.

An efficient popcount would be useful for numerics, parsing binary formats, scientific applications and others.

Эта функция называется Population Count (подсчёт популяции). Применяется в алгоритмах теории информации. Почитайте про Теорию Хэминга чтобы понять чуть больше чем сейчас.
Если коротко, это такие алгоритмы, помогающие быстро определить схожесть или различие строк основываясь на их битовом представлении.

Этим применение не ограничивается. Подсчет единиц может быть полезен при работе с битовыми картами.
В Redis тоже есть подобная команда.

Как считаете, это маленькая удобная функция делающая Python ближе к научному сообществу или бесполезная трата места в документации?

#libs
1.1K views09:00
Открыть/Комментировать
2021-10-06 12:00:17
Релиз Python 3.10 случился! Все быстро побежали использовать новые type hints, pattern matching и всё такое

А между тем, на днях вышел Qt6.2.
Наконец-то портировали такие модули как QtBluetooth, QtMultimedia, QtWebEngine, QtWebView и другие полезняхи.
Если вы этого ждали, то пора действовать!

PySide6 тоже подтянулся по версии.

#qt #libs
643 views09:00
Открыть/Комментировать
2021-10-04 19:30:00
Python 3.10 Release Stream — with Pablo Galindo
Стрим, посвящённый релизу Python 3.10!



656 views16:30
Открыть/Комментировать
2021-10-01 11:59:59 Особенно внимательно за закрытием файлов нужно следить в задачах где вы обрабатываете много файлов.
Операционная система имеет ограничение на количество открытых файлов процессом и вы быстро можете дойти до этого предела.

import os
lst = []
for i in range(100000):
lst.append(open(os.devnull, 'w'))

OSError: [Errno 24] Too many open files: 'nul'

Чтобы узнать лимит на Linux вызовите команду

ulimit -n

(Полный список лимитов ulimit -a)
Изменить лимит можно командой

ulimit -n 2048

На Windows можно это сделать с помощью кода

>>> import ctypes
>>> ctypes.windll.msvcrt._getmaxstdio()
512
>>> ctypes.windll.msvcrt._setmaxstdio(2048)
2048

Отсюда вывод: Всегда явно закрывайте файлы! Иначе можете упереться в ограничения системы.

#tricks
619 views08:59
Открыть/Комментировать
2021-09-29 12:00:09 В Python есть удобный режим, определяющий код с неверно закрытыми ресурсами. Этот режим называется Development Mode и включается двумя способами:

Переменная окружения

export PYTHONDEVMODE=1
python3 app.py

Аргументы

python3 -X dev app.py

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

Вот пример файла

# app.py
import psutil, os
open('testfile', 'w')
123
print('process handlers:', psutil.Process(os.getpid()).open_files())

В этом примере я использую пакет psutil, чтобы убедиться, что перед выходом открытых файлов в моём процессе не осталось.
При этом ResourceWarning всё равно будет выброшен, причём еще до использования psutil.

app.py:3: ResourceWarning: unclosed file <_io.TextIOWrapper name='testfile' mode='w' encoding='UTF-8'>
open('testfile', 'w')
Object allocated at (most recent call last):
File "app.py", lineno 3
open('testfile', 'w')
process handlers: []

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

Отсюда вывод: Всегда явно закрывайте файлы! Пишите чистый и предсказуемый код.

#tricks #libs
559 views09:00
Открыть/Комментировать
2021-09-27 12:00:07 В одном из прошлых постов был вопрос в комментариях по поводу закрытия файла.
Тогда я бегло пояснил что Python сам собирает мусор в памяти.

Давайте пройдемся по этому вопросу более внимательно.
Когда вы открываете файл не сохраняя его в переменную, на самом деле файл остаётся открытым. Ссылка на него теряется где-то в памяти пока сборщик мусора не доберется до него.

Давайте сделаем несколько экспериментов. Откроем файл не сохраняя его в переменную и поищем этот объект в памяти.
Для поиска будем использовать вот такую функцию

def check_file():
import io, gc
for obj in gc.get_objects():
if isinstance(obj, io.TextIOWrapper) and \
obj.name == 'testfile':
print('File', obj.name, 'is closed:', obj.closed)
return
print('Not found')

Тест первый: файл, открытый в функции

def func():
open('testfile', 'w')

Вызываем функцию и проверяем наличие файла

>>> func()
>>> check_file()
Not found

Здесь всё предсказуемо. Все локальные переменные функции удаляются когда функция завершится. А при удалении файл закрывается.

Тест второй: теперь откроем файл просто в коде, можно в интерактивной консоли.

open('testfile', 'w')

И снова он не сохранён в переменную, а значит будет удалён сборщиком мусора. Проверим:

>>> check_file()
File testfile is closed: False

Бывалые сразу же скажут, что файл улетел в переменную "_", и будут правы!

>>> print(_)
<_io.TextIOWrapper name='testfile' mode='w' encoding='UTF-8'>

Давайте обнулим её, можно просто распечатать любое число в консоли

>>> 123
>>> print(_)
123

Проверим

>>> check_file()
Not found

Отсюда вывод: Всегда явно закрывайте файлы! Не рассчитывайте что кто-то (gc) сделает это за вас.
_________________
Мои примеры порой содержат оптимизации в угоду краткости но в ущерб правильности.

#tricks
742 views09:00
Открыть/Комментировать