Особенно внимательно за закрытием файлов нужно следить в задачах где вы обрабатываете много файлов.
Операционная система имеет ограничение на количество открытых файлов процессом и вы быстро можете дойти до этого предела.
Изменить лимит можно командой
#tricks
Операционная система имеет ограничение на количество открытых файлов процессом и вы быстро можете дойти до этого предела.
import osЧтобы узнать лимит на Linux вызовите команду
lst = []
for i in range(100000):
lst.append(open(os.devnull, 'w'))
OSError: [Errno 24] Too many open files: 'nul'
ulimit -n(Полный список лимитов
ulimit -a)Изменить лимит можно командой
ulimit -n 2048На Windows можно это сделать с помощью кода
>>> import ctypes➡️ Отсюда вывод: Всегда явно закрывайте файлы! Иначе можете упереться в ограничения системы.
>>> ctypes.windll.msvcrt._getmaxstdio()
512
>>> ctypes.windll.msvcrt._setmaxstdio(2048)
2048
#tricks
Python 3.10 Release Stream — with Pablo Galindo
Стрим, посвящённый релизу Python 3.10!
➡️ https://www.youtube.com/watch?v=AHT2l3hcIJg
Стрим, посвящённый релизу Python 3.10!
➡️ https://www.youtube.com/watch?v=AHT2l3hcIJg
Релиз Python 3.10 случился! Все быстро побежали использовать новые type hints, pattern matching и всё такое😁
А между тем, на днях вышел Qt6.2.
Наконец-то портировали такие модули как QtBluetooth, QtMultimedia, QtWebEngine, QtWebView и другие полезняхи.
Если вы этого ждали, то пора действовать!
PySide6 тоже подтянулся по версии.
#qt #libs
А между тем, на днях вышел Qt6.2.
Наконец-то портировали такие модули как QtBluetooth, QtMultimedia, QtWebEngine, QtWebView и другие полезняхи.
Если вы этого ждали, то пора действовать!
PySide6 тоже подтянулся по версии.
#qt #libs
Все уже успели обсудить новые фишки в Python 3.10, такие как ускорение работы базовых типов, удобная типизация и особенно новый паттерн матчинг.
Только ленивый не рассказывал про паттерн матчинг!
Давайте я прикинусь ленивым (но это не так😉) и не буду повторяться. Расскажу про другое нововведение.
В противовес мега полезному pattern matching эта штука, на первый взгляд, имеет сомнительную полезность🧐
В Python 3.10 у типа int появился новый метод int.bit_count().
Что он делает? Возвращает количество единиц в битовом представлении числа.
Что? Зачем? Почему? 😭❓😱
Это не bit_length(), возвращающий количество бит, необходимых для записи данного числа.
И это не
Зачем нам количество ненулевых бит в битовом представлении? Особенно когда новый метод это просто эквивалент строки:
An efficient popcount would be useful for numerics, parsing binary formats, scientific applications and others.
Эта функция называется Population Count (подсчёт популяции). Применяется в алгоритмах теории информации. Почитайте про Теорию Хэминга чтобы понять чуть больше чем сейчас.
Если коротко, это такие алгоритмы, помогающие быстро определить схожесть или различие строк основываясь на их битовом представлении.
Этим применение не ограничивается. Подсчет единиц может быть полезен при работе с битовыми картами.
В Redis тоже есть подобная команда.
Как считаете, это маленькая удобная функция делающая Python ближе к научному сообществу или бесполезная трата места в документации?
#libs
Только ленивый не рассказывал про паттерн матчинг!
Давайте я прикинусь ленивым (но это не так😉) и не буду повторяться. Расскажу про другое нововведение.
В противовес мега полезному 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
Размышления насчет ускорений 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
Но никто не отменял ускорение выполнения задач через распараллеливание различными способами. Лично я часто использую 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
GitHub
GitHub is where people build software. More than 150 million people use GitHub to discover, fork, and contribute to over 420 million projects.
👍1
Модуль pythonnet позволяет интегрировать ваш код на Python с .NET приложениями.
Например, запускать Python модули внутри .NET или импортировать DLL библиотеки в Python.
📖 Вики по модулю
📕 Урок на гитхабе
📙 Пара примеров использования
📌 Пример от меня:
Использование библиотеки от всем известного софта мониторинга Open Hardware Monitor.
Когда его скачаете, обнаружите там библиотеку OpenHardwareMonitorLib.dll. Вот она нам и нужна!
Для начала поставьте модуль pythonnet
Теперь нам доступен модуль clr (Common Language Runtime) с помощью которого можно делать DLL доступными для импорта
Вот и всё, можно импортировать и использовать
__________________
PS. Некоторые устройства для получения полной информации требуют запуска от имени администратора.
Например, если видите в списке устройств некий Generic Hard Disk или запрос значения сенсора вернуло None, то это как раз тот случай.
#libs
Например, запускать 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
PyPI
pythonnet
.NET and Mono integration for Python
👍1
В модуле logging предусмотрен немного необычный способ форматирования строки без форматирования.
Если вам требуется указать в строке сообщения какой-либо аргумент то обычно это делается форматированием строки
Функция записи сообщения должна быть очень быстрой. Да, она в любом случае занимает время, но чем меньше тем лучше. И особенно, когда это сообщение не проходит по фильтру уровня логирования.
Например, у меня установлен уровень WARNING и выполняется вот такой вызов
Сообщение не попадает под установленный уровень логирования и будет проигнорировано. Это обрабатывается сразу же первой командой в вызываемой функции debug. Но при этом форматирование строки всё равно произойдёт!
И проблема не в самом форматировании, которое достаточно быстрое (даже при складывании строк через "+"), а в тех возможных действиях, которые придется вызвать для преобразования объекта user в строку.
Возможно, там будет запрос в БД, разбор больших массивов данных или еще что-то не очень быстрое (или не очень умное🤪).
Нам всё это придётся посчитать чтобы потом.....ничего с этим не сделать.
Поэтому правильно писать так:
#libs #tricks
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
Если часто работаете с архивами, то наверняка знакомы с модулем zipfile.
Нет ничего сложного добавить директорию в архив.
Здесь проще, даже с
▫️ В данном случае функция из
Поддерживаются форматы
▫️ Из недостатков можно назвать невозможность запаковать просто один файл. Источником может быть только директория. Проблема легко решается, но всё же.
▫️ Интересный момент. При наличии в Python2 функции
#libs #tricks
Нет ничего сложного добавить директорию в архив.
import zipfileДовольно немногословно. Но можно короче! В модуле
from pathlib import Path
dir_name = '~/input_files'
zip_name = '~/archive.zip'
with zipfile.ZipFile(zip_name, 'w') as zip:
for file in Path(dir_name).glob('**/*'):
zip.write(file, file.relative_to(dir_name).as_posix())
shutil уже есть готовый методdir_name = '~/input_files'А что насчет распаковки?
zip_name = '~/archive'
zip_file = shutil.make_archive(zip_name, 'zip', root_dir=dir_name)
Здесь проще, даже с
zipfile это одна строкаzip_file = '~/archive.zip'Ну и тем более в
out_dir = '~/out_dir'
zipfile.ZipFile(zip_file).extractall(out_dir)
shutil
shutil.unpack_archive(zip_file, out_dir)В примерах не делается expanduser для краткости
▫️ В данном случае функция из
shutil более универсальна, так как второй аргумент format задаёт алгоритм сжатия, от чего зависит выбор библиотеки. Если написать формат tar, то вместо zipfile будет использоваться tarfile.Поддерживаются форматы
zip, tar, gztar, bztar, xztar. Но только если на текущем хосте доступны соответствующие библиотеки.▫️ Из недостатков можно назвать невозможность запаковать просто один файл. Источником может быть только директория. Проблема легко решается, но всё же.
▫️ Интересный момент. При наличии в Python2 функции
shutil.make_archive() там отсутствует shutil.unpack_archive(). А появился он только в 3.7! Не очень понятно почему, но это еще один повод переходить на Python3 😊#libs #tricks
🤟😜🍺🎁🎉🍻🎂
Поздравляю всех 3Dшников с проф-праздником!
PS. А еще на канале юбилейный пост под номером 300! 😎
#offtop
Поздравляю всех 3Dшников с проф-праздником!
PS. А еще на канале юбилейный пост под номером 300! 😎
#offtop
😋 Заметка от читателя @nencoru
Как смержить несколько файлов с отсортированными строками в один файл, тоже отсортированный?
🔸 Исходный файл:
▫️ в одной строке находится одна запись
▫️ запись содержит предсказуемое поле с некими данными для сортировки. Например, логи с указанием времени.
▫️ все записи в файле отсортированы по этому полю
🔸 Задача:
Смержить несколько таких файлов так, чтобы в финальном файле все записи были также отсортированы.
🔸 Решение 1:
Предположим, у меня JSON-логи
Это означает, что вам потребуется оперативной памяти 5*len(files) Gb.
И уже не каждый компьютер сможет смержить 3-4 таких файла. А если их 100?
fileinput может помочь написать более красивый код, но с памятью не поможет.
🔸 Решение 2:
Можно использовать готовую функцию heapq.merge() из стандартного модуля heapq!
Heap - это бинарное дерево, где каждый родительский элемент в дереве имеет значение меньшее чем дочерний.
То есть, по умолчанию все элементы как-либо отсортированы.
И тут вы спросите: что за магия?
Тоже самое только без расхода памяти? Волшебный генератор всех спасёт?
Нет, за всё приходится платить. В случае с heapq весь процесс драматически замедлится.
Но задача будет выполнена! 😎
Сделал для вас синтетический пример для генерации и мержа подобных файлов
Код смотреть здесь ↗️
▫️ make_logs() генерит 30 файлов по 50Mb для теста
▫️ merge_list() мержит файлы через простой список
▫️ merge_heapq() мержит файлы через heapq
▫️ memory_profiler считает используемую память (нужно установить модуль)
▫️ также есть замер времени
Кому лениво там же смотрите мои тесты:
1.5Gb и 19.5с против 19Mb и 2м 43с
памяти в 80 раз меньше, но времени в 8 раз больше
⚠️ ВАЖНО
для чистоты эксперимента запускать следует из консоли и по одному тесту на процесс. То есть закоментили второй, запустили первый, закоментили первый, запустили второй.
#bacik
Как смержить несколько файлов с отсортированными строками в один файл, тоже отсортированный?
🔸 Исходный файл:
▫️ в одной строке находится одна запись
▫️ запись содержит предсказуемое поле с некими данными для сортировки. Например, логи с указанием времени.
▫️ все записи в файле отсортированы по этому полю
🔸 Задача:
Смержить несколько таких файлов так, чтобы в финальном файле все записи были также отсортированы.
🔸 Решение 1:
Предположим, у меня JSON-логи
files = ['file1.jsonl', 'file2.jsonl', ...]
data = []
for file in files:
with open(file) as f:
data.expand(
f.readlines()
)
data.sort(key=lambda line: json.loads(line)['timestamp'])
with open('merged.jsonl', 'w') as f:
f.writelines(data)
Усложним задачу — размер каждого файла 5Gb 😱Это означает, что вам потребуется оперативной памяти 5*len(files) Gb.
И уже не каждый компьютер сможет смержить 3-4 таких файла. А если их 100?
fileinput может помочь написать более красивый код, но с памятью не поможет.
🔸 Решение 2:
Можно использовать готовую функцию heapq.merge() из стандартного модуля heapq!
Heap - это бинарное дерево, где каждый родительский элемент в дереве имеет значение меньшее чем дочерний.
То есть, по умолчанию все элементы как-либо отсортированы.
from heapq import merge
items = [
[3,2,6],
[1,5,4]
]
print(list(merge(*items)))
# [1, 2, 3, 4, 5, 6]
А учитывая, что merge это генератор, умеет работать с файлами и ему можно передать функцию для сортировки, он отлично подойдет для нашей задачи, так как полной загрузки в память не происходит!И тут вы спросите: что за магия?
Тоже самое только без расхода памяти? Волшебный генератор всех спасёт?
Нет, за всё приходится платить. В случае с heapq весь процесс драматически замедлится.
Но задача будет выполнена! 😎
Сделал для вас синтетический пример для генерации и мержа подобных файлов
Код смотреть здесь ↗️
▫️ make_logs() генерит 30 файлов по 50Mb для теста
▫️ merge_list() мержит файлы через простой список
▫️ merge_heapq() мержит файлы через heapq
▫️ memory_profiler считает используемую память (нужно установить модуль)
▫️ также есть замер времени
Кому лениво там же смотрите мои тесты:
1.5Gb и 19.5с против 19Mb и 2м 43с
памяти в 80 раз меньше, но времени в 8 раз больше
⚠️ ВАЖНО
для чистоты эксперимента запускать следует из консоли и по одному тесту на процесс. То есть закоментили второй, запустили первый, закоментили первый, запустили второй.
#bacik
Gist
Merging of huge sorted files
Merging of huge sorted files. GitHub Gist: instantly share code, notes, and snippets.
👍3
Наверняка вы замечали, что в Python есть удобная функция для получения переменной окружения
Почему так?
На самом деле энвайромент обновляется, но это значение не добавляется в словарь
Откройте исходник функции
Словарь
В тоже время, когда вы создаёте или изменяете ключ в
То есть, технически
Аналогично при удалении переменной вызывается еще одна built-in функция
Итого
▫️ Удобней всего явно обновлять переменные через
▫️
#basic
os.getenv(NAME)
И её "сестра" для создания или изменения переменных окруженияos.putenv(NAME, VALUE)
Но почему-то putenv() не работает как должно. Энвайромент не обновляется!os.putenv('MYVAR', '1')
print(os.getenv('MYVAR'))
... и ничего 😴Почему так?
На самом деле энвайромент обновляется, но это значение не добавляется в словарь
os.environ.Откройте исходник функции
os.getenv(). Это просто шорткат для os.environ.get()
В то время как putenv() это built-in С-функция.Словарь
os.environ (или точней класс из MutableMapping) создаётся из энвайромента в момент инициализации. Функция putenv() самостоятельно его не изменяет.В тоже время, когда вы создаёте или изменяете ключ в
os.environ, автоматически вызывается putenv() в методе __setitem__().То есть, технически
putenv() всё делает верно, но в os.environ это не отражается. Можно проверить так:>>> os.putenv('MYVAR', '123')
>>> os.system('python -c "import os;print(os.getenv(\'MYVAR\'))"')
123
Я объявил переменную в текущем процессе и вызвал дочерний процесс, который её унаследовал и получил в составе os.environ.Аналогично при удалении переменной вызывается еще одна built-in функция
unsetenv(), удаляющая переменную из системы.Итого
▫️ Удобней всего явно обновлять переменные через
os.environ
▫️ Есть способ неявно создать/удалить переменную через putenv/unsetenv, что не повлияет на os.environ но изменит энвайромент и передаст изменения сабпроцессам. Но так лучше не делать!▫️
os.environ это просто обертка для built-in функций putenv() и unsetenv(). #basic
GitHub
cpython/Lib/os.py at 3.10 · python/cpython
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.
👍2
При форматировании числа в строку можно задать паддинг - заполнение нулями до нужной длины.
К сожалению (а может к счастью), уровень вложенности ограничен двумя. То есть, форматирование внутри форматирования внутри форматирования это ...
(Пример странный, но зато рабочий)
>>> '{}_v{:05d}'.format('name', 125)
'name_v00125'
А что если паддинг тоже задан переменной? В таком случае мы можем добавить форматирование этой переменной внутри формата первой. Порядок переменных следует указывать в порядке появление открывающейся скобки.>>> '{}_v{:0{}d}'.format('name', 125, 5)
'name_v00125'
Или вот так>>> '{}_v:{:{:02d}{}}'.format('name', 125, 5, 'd')
'name_v00125'
А можно глубже? К сожалению (а может к счастью), уровень вложенности ограничен двумя. То есть, форматирование внутри форматирования внутри форматирования это ...
ValueError: Max string recursion exceededНо никто не запрещает использовать один тип форматирования внутри другого.
(Пример странный, но зато рабочий)
>>> ('{}_v{:{:%0.2dd}{}}' % 2).format('name', 125, 5, 'd')
'name_v00125'
С f-string можно использовать 4 уровня, по количеству доступных типов кавычек. Можно, но не нужно 😕f'''{f"""{f'{f"{x}"}'}"""}'''
#tricks🔥13👍3
Ещё пара триков с форматированием!
▫️Порядки больших чисел можно разделять запятой (и только запятой)
#tricks
▫️Порядки больших чисел можно разделять запятой (и только запятой)
>>> '{:,}'.format(1_231_312)
'1,231,312'
▫️Если оставить пробел в форматировании float после ":" то он добавится в строку>>> '{: .2f}'.format(15)
' 15.00'
Но если подать отрицательное число, то знак минуса займёт этот пробел>>> '{: .2f}'.format(-15)
'-15.00'
Удобно для формирования строк одинаковой длины независимо от знака числа.#tricks
👍8
Синтаксис f-string позволяет использовать в строке символ обратного слеша "
▫️ вынести этот символ за скобки
\" но не позволяет использовать его внутри фигурных скобок.>>> lines = ['line1','line2']
>>> print(f'ITEMS: \n {"\n".join(lines)}')
SyntaxError: f-string expression part cannot include a backslash
Решения:▫️ вынести этот символ за скобки
n = '\n'
print(f'ITEMS: \n{n.join(lines)}')
▫️ заменить его на другое представление, например создавать нужный символ с помощью функции chr()
print(f'ITEMS: \n{chr(10).join(lines)}')
Чтобы узнать код символа следует использовать функцию ord()
>>> ord('\n')
10
А с юникодом не выйдет, там тоже слеш>>> print(f'ITEMS: \n{"\u000a".join(lines)}')
SyntaxError: f-string expression part cannot include a backslash
#tricks👍11😱1
Метод строки
А вот что будет по умолчанию
По умолчанию в качестве разделителя используется любой пробельный символ, будь то табуляция или новая строка. Включая несколько таких символов идущих подряд. А также игнорируются пробельные символы по краям строки.
#tricks #basic
split() разделяет строку на несколько строк по указанному символу>>> "a_b_c".split('_')
['a', 'b', 'c']
Можно указать максимальное количество разделений>>> "a_b_c".split('_', 1)
['a', 'b_c']
Или резать с другой стороны с помощью rsplit() (right split)>>> "a_b_c".rsplit('_', 1)
['a_b', 'c']
А что будет если оставить аргументы пустыми?>>> "a_b_c".split()Получаем список с одним элементом, потому что по умолчанию используется пробельный символ.
['a_b_c']
>>> "a b c".split()То есть это равнозначно такому вызову?
['a', 'b', 'c']
>>> "a b c".split(" ")
['a', 'b', 'c']
Кажется да, но нет! Давайте попробуем добавить пробелов между буквами>>> "a b c".split(" ")
['a', '', '', 'b', '', '', 'c']
И вот картина уже не так предсказуема 😕А вот что будет по умолчанию
>>> "a b c".split()Всё снова красиво! 🤩
['a', 'b', 'c']
По умолчанию в качестве разделителя используется любой пробельный символ, будь то табуляция или новая строка. Включая несколько таких символов идущих подряд. А также игнорируются пробельные символы по краям строки.
>>> "a\t b\n c ".split()Аналогичный способ можно собрать с помощью регулярного выражения. Но пробелы по краям строки придется обрабатывать дополнительно.
['a', 'b', 'c']
>>> import reЗдесь тоже можно указать количество разделений
>>> re.split(r"\s+", ' a b c '.strip())
['a', 'b', 'c']
>>> re.split(r"\s+", 'a b c', 1)А что если мы хотим написать красиво, то есть
['a', 'b c']
split() без аргументов, но при этом указать количество разделений? В этом случае первым аргументом передаём None
>>> "a\n b c".split(None, 1)Данный метод не учитывает строки с пробелами, взятые в кавычки
['a', 'b c']
'a "b c" '.split()Но для таких случаев есть другие способы.
['a', '"b', 'c"']
#tricks #basic
Telegram
Python Заметки
В посте про правильное использование аргумента shell упоминалось что в некоторых случаях атрибуты следует отправлять списком а не строкой. Что делать, если команда приходит именно строкой? Как её преобразовать в список?
Ответ очевиден
>>> cmd_str = 'ls …
Ответ очевиден
>>> cmd_str = 'ls …
👍25😱1😢1
Сегодня будет самый "двоичный" ("двойковый"? "двушный"? "двойственный"?) момент на вашем веку 🤩
Больше двоек в дататайме вы не застанете!
Успейте поймать момент! Будете показывать эпичный скриншот своим внукам)))
🥸 Для продуманных (ленивых): код на скрине, который сработает только сегодня и только 1 раз!
⏱ Открывайте окошки с часами и вперёд!
#offtop
Больше двоек в дататайме вы не застанете!
Успейте поймать момент! Будете показывать эпичный скриншот своим внукам)))
🥸 Для продуманных (ленивых): код на скрине, который сработает только сегодня и только 1 раз!
⏱ Открывайте окошки с часами и вперёд!
#offtop
😁10🔥5
⚠️ События последних дней сильно изменили жизнь многих из нас. Мы уже не будем прежними и мир вокруг не будет прежним.
Лично я всё ещё в некотором тупняке от происходящего...
Но этот канал не о политике и здесь я не буду рассуждать кто прав а кто виноват. Для нас сейчас главное — пережить пик кризиса и адаптироваться к новым реалиям. Обязательно беречь себя и помогать окружающим.
В свою очередь я хочу помочь всем, кто меня знает и читает. Поэтому у меня к вам есть три предложения...
#offtop
Лично я всё ещё в некотором тупняке от происходящего...
Но этот канал не о политике и здесь я не буду рассуждать кто прав а кто виноват. Для нас сейчас главное — пережить пик кризиса и адаптироваться к новым реалиям. Обязательно беречь себя и помогать окружающим.
В свою очередь я хочу помочь всем, кто меня знает и читает. Поэтому у меня к вам есть три предложения...
#offtop
❤3👍3
Из-за всем известных событий очень многие потеряли работу.
Для поиска вакансий вполне можно использовать паблики в telegram. Вот несколько которые мне известны:
https://t.iss.one/django_jobs
https://t.iss.one/javascript_jobs
https://t.iss.one/workzavr
https://t.iss.one/workoo
https://t.iss.one/Workesss
@g_jobbot
➡️ Чем шире о себе заявите, тем больше шансов найти нужный контакт. Поэтому предлагаю айтишникам и художникам бесплатно разместить на моём канале @pythonotes информацию о вас.
Формат сообщения можно сделать примерно следующий:
_______________________________
Имя Фамилия
Специализация
О себе
- Долго думаю, быстро делаю.
Кем хочу работать
- Разработчик мобильных приложений
Локация
- Удалённо, возможен переезд в ГородНейм
Знаю языки программирования
- JSON
- CSS
- HTML
Хорошо владею софтом
- Maya. Ротоскопинг, трекинг
- Nuke. Персонажная анимация
- 3DsMax. Композитинг и кленап
Где работал
- Microsoft, админ лифта
- Yandex, доставка пончиков
- Disney, протирка шариков от мышей
Контакты
- Телеграм: @username
- Почта: [email protected]
- Полное резюме (ссылка на GoogleDoc/LinkedIn/PDF)
_______________________________
Картинки не надо, смайлы без фанатизма.
Текст присылайте в этот временный канал, где будем обсуждать все вопросы:
▶️ @pn_work
🌼 Если найдутся желающие, вакансии тоже могу запостить
📅 Предложение актуально как минимум до лета 2022г.
Если будет хоть один пост, уже не зря старался)
📌 @pythonotes
#offtop
Для поиска вакансий вполне можно использовать паблики в telegram. Вот несколько которые мне известны:
https://t.iss.one/django_jobs
https://t.iss.one/javascript_jobs
https://t.iss.one/workzavr
https://t.iss.one/workoo
https://t.iss.one/Workesss
@g_jobbot
➡️ Чем шире о себе заявите, тем больше шансов найти нужный контакт. Поэтому предлагаю айтишникам и художникам бесплатно разместить на моём канале @pythonotes информацию о вас.
Формат сообщения можно сделать примерно следующий:
_______________________________
Имя Фамилия
Специализация
О себе
- Долго думаю, быстро делаю.
Кем хочу работать
- Разработчик мобильных приложений
Локация
- Удалённо, возможен переезд в ГородНейм
Знаю языки программирования
- JSON
- CSS
- HTML
Хорошо владею софтом
- Maya. Ротоскопинг, трекинг
- Nuke. Персонажная анимация
- 3DsMax. Композитинг и кленап
Где работал
- Microsoft, админ лифта
- Yandex, доставка пончиков
- Disney, протирка шариков от мышей
Контакты
- Телеграм: @username
- Почта: [email protected]
- Полное резюме (ссылка на GoogleDoc/LinkedIn/PDF)
_______________________________
Картинки не надо, смайлы без фанатизма.
Текст присылайте в этот временный канал, где будем обсуждать все вопросы:
▶️ @pn_work
🌼 Если найдутся желающие, вакансии тоже могу запостить
📅 Предложение актуально как минимум до лета 2022г.
Если будет хоть один пост, уже не зря старался)
📌 @pythonotes
#offtop
👍3
Помогая окружающим, лучше всего делать то, что умеешь делать лучше всего! Поэтому я решил сделать все свои курсы бесплатными и выложить в открытый доступ❗️
Был период в моей жизни, когда эти курсы помогли мне выжить. Теперь, я надеюсь, они помогут кому-то еще.
Спасибо всем, кто покупал мои курсы, даже если потом не смотрел 😁
Навыки программирования нынче оцениваются достаточно высоко, это шанс найти работу с зарплатой повыше, попросить повышения или просто улучшить свою продуктивность с помощью кодинга! Так что пользуйтесь 😉
Сразу скажу, курсы не свежие, записанны в 2014-2015 гг. Некоторая информация устарела но примерно на ±90% всё еще актуально.
Какие курсы доступны:
▫️ Advanced Python Scripting
Это компиляция из 3х курсов начального, среднего и высокого уровня сложности. С нуля до создания собственных десктоп-приложений.
▫️ Python for Maya
Курс для Python-разработчиков в Maya. Да, Autodesk ушел от нас, но скорее всего, вернётся)
▫️ Python for Nuke
Курс для Python-разработчиков в Nuke.
▫️ Python for Houdini
Курс для Python-разработчиков в Houdini. Самый отстающий в актуальности курс, так как Houdini развивается и меняется очень стремительно и кардинально. Тем не менее, 80-90% курса актуальна.
▫️ Houdini Fundamentals
Курс поможет познакомиться с крутым софтом для 3D графики — SideFX Houdini. Записан на версии 16. Рассчитан на нулевой уровень подготовки.
На этот раз курс не про Python, только про сам софт.
Все Python-курсы записаны с Python2, вам потребуется изучить особенности перехода на версию Python3, о чем я не раз говорил на своём канале. Ищите по хэштегу #2to3
💬 Остальные подробности в комментах
Переходите на сайт школы и выбирайте курс:
➡️ https://cgninjas.ru/ ⬅️
📌 @pythonotes
#offtop
Был период в моей жизни, когда эти курсы помогли мне выжить. Теперь, я надеюсь, они помогут кому-то еще.
Спасибо всем, кто покупал мои курсы, даже если потом не смотрел 😁
Навыки программирования нынче оцениваются достаточно высоко, это шанс найти работу с зарплатой повыше, попросить повышения или просто улучшить свою продуктивность с помощью кодинга! Так что пользуйтесь 😉
Сразу скажу, курсы не свежие, записанны в 2014-2015 гг. Некоторая информация устарела но примерно на ±90% всё еще актуально.
Какие курсы доступны:
▫️ Advanced Python Scripting
Это компиляция из 3х курсов начального, среднего и высокого уровня сложности. С нуля до создания собственных десктоп-приложений.
▫️ Python for Maya
Курс для Python-разработчиков в Maya. Да, Autodesk ушел от нас, но скорее всего, вернётся)
▫️ Python for Nuke
Курс для Python-разработчиков в Nuke.
▫️ Python for Houdini
Курс для Python-разработчиков в Houdini. Самый отстающий в актуальности курс, так как Houdini развивается и меняется очень стремительно и кардинально. Тем не менее, 80-90% курса актуальна.
▫️ Houdini Fundamentals
Курс поможет познакомиться с крутым софтом для 3D графики — SideFX Houdini. Записан на версии 16. Рассчитан на нулевой уровень подготовки.
На этот раз курс не про Python, только про сам софт.
Все Python-курсы записаны с Python2, вам потребуется изучить особенности перехода на версию Python3, о чем я не раз говорил на своём канале. Ищите по хэштегу #2to3
💬 Остальные подробности в комментах
Переходите на сайт школы и выбирайте курс:
➡️ https://cgninjas.ru/ ⬅️
📌 @pythonotes
#offtop
❤37👍19🥰1😁1