Добро пожаловать, Гость
Вам необходимо зарегистрироваться перед тем, как пытататься написать сообщение.
Поиск по форумам
Статистика форума
 Участники: 166
 Последний участник: masvavoja
 Темы форума: 378
 Сообщения форумов: 2,288

Полная статистика
Пользователи в сети
Сейчас 6 пользователей в сети.
 0 Участник(-ов) | 6 Гость(-ей)

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

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

В Go учли этот момент и сделали штатный механизм.

В начале нужной функции берем время начала:

Код:
start := time.Now()

Затем выполняем все нужные действия и в конце берем время окончания:

Код:
duration := time.Since(start)

Теперь просто выводим результат:

Код:
fmt.Println(duration)

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

Вот и всё что я хотел вам сказать!

Убиваю остаток сегодняшнего дня!

Гарри Поттер и тайная комната на freebsd

сабж

[Изображение: DKVvvnM.png]

Я давно присматривался к оконному менеджеру ctwm. После кропотливого изучения мануала и просмотра чужих конфигов, понял, что это очень мощный wm. Очень мощный и гибкий. Думаю, он гибче и мощнее fvwm.

Установил я его (версия в Debian Bullseye 3.7-5, а в unstable уже новая-4.0.3-2), и настроил так, чтобы напоминало мне BeOS.

Также настроил хоткей, наподобие вимовских....


Эскизы(ов)
   

Почти во всех 3D играх воспроизводится разная анимация ног в зависимости от направления движения. Т.е. если персонаж смотрит вперёд, но идёт назад - то будет воспроизводиться анимация ходьбы назад.

Один из самых простых способов реализовать это в Unity:

Код:
public static Vector2 getAnimationDirection(Vector3 referenceVectorUp, Vector3 referenceVectorRight, Vector2 movementVector, Transform objectTransform)
{
    Vector2 animationFinalDirection = Vector2.zero;

    Vector3 dirForward = Vector3.Scale(referenceVectorUp, new Vector3(1f, 0f, 1f)).normalized;
    Vector3 animMoveDir = movementVector.y * dirForward + movementVector.x * referenceVectorRight;

    if (animMoveDir.magnitude > 1)
        animMoveDir.Normalize();

    Vector3 localMove = objectTransform.transform.InverseTransformDirection(animMoveDir);

    animationFinalDirection.x = localMove.x;
    animationFinalDirection.y = localMove.z;

    return animationFinalDirection;
}

Данная функция готова для использования без MonoBehaviour.

Пояснения по коду

referenceVectorUp и referenceVectorRight - transform.up и transform.right объекта, от которого будет отталкиваться функция для поворота. Например, в данный момент мы разрабатываем Top Down Shooter, и в них передаются трансформы камеры.

movementVector - нажатия клавиш или левого стика геймпада. Значения от -1 до 1 по осям X и Y.

objectTransform - трансформ объекта персонажа.

В итоге в зависимости от поворота персонажа будут разные значения вектора.

Как использовать

Пример: есть 2D дерево смешивания. В нём есть две переменные: run и strafe, которые получают float от -1 до 1. И четыре анимации (но можно и больше, если есть отдельные анимации для бега по диагонали).

В нашем проекте это выглядит так:
Код:
Vector2 animDir = getAnimationDirection(playerCamera.GetComponent<Transform>().up, playerCamera.GetComponent<Transform>().right, movementVector, transform)

animator.SetFloat("run", animDir.y);
animator.SetFloat("strafe", animDir.x);

Также можно вместо камеры можно передавать transform.forward игрока, чтобы корректировать анимации. Подойдёт для игр от третьего лица или ботов.

Сразу скажу, что использование Python для написания простых скриптов - оверкилл. Потому что, в отличие от скриптовых языков (Bash/SH), это полноценный язык программирования. Тем не менее в этом есть свои плюсы. Я так и не осилил скриптовые языки, и каждая попытка воспользоваться оными оборачивалась болью.

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

Для понимания статьи у Вас уже должны быть базовые знания питона.

Много кода было взято отсюда, не забудьте посетить ссылку: https://github.com/ninjaaron/replacing-b...ith-python

Причины

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

Заголовок немного лукавит. Питон не является равноценной заменой скриптовым языкам, т.к. они состоят в разных весовых категориях. Однако питон имеет замену большинству возможностей Bash/SH. Разумеется, ни о какой замене всего Bash/SH на Python (в т.ч. для установки по умолчанию в терминале) речи не идёт.

Для себя я выбрал питон по следующим причинам:

  • Работа со строками. Т.к. это полноценный язык программирования, то в нём присутствует полноценная работа со строками. Парсинг, форматирование, разделение и т.д. Никакого жонглирования с grep и awk.
  • Различные типы переменных. Строки являются строками, числа - числами. Это позволяет нормально сравнивать переменные и проводить с ними операции.
  • Возможность писать код полностью без функций. Т.е. прямо как Bash/SH.
  • Полноценные циклы и итераторы
  • Обработка данных средствами языка, без вызова внешних программ. Bash/SH являются всего лишь клеем для внешних приложений.
  • Наличие API у различных штук, что позволяет не парсить выхлоп программы, а взаимодействовать с ней по-человечески
  • Да и в целом приятнее писать, благодаря синтаксическому сахару

А ещё питон позволяет избежать подобных нюансов:
Код:
foo = 'test   test1  test2'
echo $foo
# test test1 test2
echo "$foo"
# test   test1   test2

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


Примеры

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

Начнём с простого. Есть модуль shutil, который реализовывает многие низкоуровневые вещи. Ещё есть модуль os.
Код:
shutil.move(src, dest) //mv
shutil.copy2(src, dest) //cp
shutil.copytree(src, dest) //cp -r
shutil.rmtree(dir) //rm -r
shutil.chown(file, user, group) //chown
shutil.which(file) //which
os.remove(file) //rm
os.rename(old_name, new_name) //mv
os.mkdir(dir) //mkdir
os.makedirs(dir) //mkdir -p

Например, вам надо произвести некую каталогизацию. В данном случае это будут директории с годом в названии, а в них - директории с номером месяца.
Код:
import os

base_path = "."

for year in range(2000, 2011):
    for month in range(1, 13):
        os.makedirs(f"{base_path}/{year}/{month}", exist_ok=True)

Я не знаю, почему верхняя граница диапазона требует указать на единицу больше. Тем не менее всё работает. Аргумент exist_ok=True указывает не выдавать ошибку, если директория уже существует.

Скрипт можно сделать чуть гибче:
Код:
import os
import sys

if len(sys.argv) < 2:
    print("Укажите базовый путь")
    sys.exit(-1)

base_path = sys.argv[1]

for year in range(2000, 2011):
    for month in range(1, 13):
        os.makedirs(f"{base_path}/{year}/{month}")

Теперь можно указать директорию, в которой будут создаваться другие директории, аргументом для скрипта. Что-то вроде python yourscript.py /home/user/your_folder/.

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

В Python есть средства для получения информации. Давайте напишем небольшой скрипт, отображающий информацию о системе (что-то вроде screenfetch):
Код:
import os
import platform
import psutil


def get_uptime():
    with open("/proc/uptime", "r") as f:
        uptime = f.read().split(" ")[0].strip()

    uptime = int(float(uptime))

    return uptime

# Переменные

fetch_user = os.environ["USER"]
fetch_host = os.environ["HOSTNAME"]
fetch_de = os.environ["DESKTOP_SESSION"]
fetch_shell = os.environ["SHELL"]
fetch_home = os.path.expanduser("~")
fetch_os = platform.system();
fetch_kernel = platform.uname()
fetch_cpu = platform.processor()
fetch_dist = platform.freedesktop_os_release()
fetch_ram = psutil.virtual_memory()
fetch_swap = psutil.swap_memory()


print(f"{fetch_user}@{fetch_host}")
print(f"Shell: {fetch_shell}")
print(f"Home: {fetch_home}")
print(f"OS: {fetch_os}")
print(f"Distro: {fetch_dist['PRETTY_NAME']}")
print(f"Kernel: {fetch_kernel.release}")
print(f"Desktop: {fetch_de}")
print(f"CPU: {fetch_cpu}")
print(f"Memory (GB): {fetch_ram[0] // 1000000000} (total), {fetch_ram[3] // 1000000000} (used)")
print(f"Swap (GB): {fetch_swap[0] // 1000000000} (total), {fetch_swap[3] // 1000000000} (used)")
print(f"Uptime: {get_uptime() // 3600} hours, {(get_uptime() % 3600) // 60} minutes")
Пример выхлопа команды:
Код:
user@desktop
Shell: /usr/bin/zsh
Home: /home/user
OS: Linux
Distro: Fedora Linux 36 (KDE Plasma)
Kernel: 6.0.8-xm1.0.fc36.x86_64
Desktop: plasma
CPU: x86_64
Memory (GB): 16 (total), 9 (used)
Swap (GB): 17 (total), 0.0 (used)
Uptime: 9 hours, 51 minutes

Все модули отработали, кроме отображения модели процессора. Не знаю, только ли у меня такой косяк. Но раз модуль не отработал, то можно пропарсить /proc/cpuinfo, благо что в питоне это делается очень легко:
Код:
def get_cpu():
    with open("/proc/cpuinfo", "r") as f:
        for line in f:
            if "model name" in line:
                return(line.split(": ")[1].strip())


Здесь мы проверили строки на предмет содержания "model name" и разделили найденную строку по двоеточию с пробелом. В данном случае процессор у меня один, и я просто сделал возврат первого совпадения. Но что, если установлены два разных процессора?

Мы не будем учитывать количество ядер (т.к. я не знаю, как), только разные модели процессоров.

Поменяем функцию:
Код:
def get_cpu():
    cpu_list = []
    with open("/proc/cpuinfo", "r") as f:
        for line in f:
            if "model name" in line:
                cpu_model = line.split(": ")[1].strip()
                if cpu_model not in cpu_list:
                    cpu_list.append(cpu_model)
                   
    return cpu_list

И поменяем код вывода модели процессора:
Код:
if len(fetch_cpu) == 1:
    print(f"CPU: {fetch_cpu[0]}")
else:
    for cpu in fetch_cpu:
        print(f"CPU {fetch_cpu.index(cpu) + 1}: {cpu}")

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

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

Я уже писал выше, что Bash/SH - это клей для внешних приложений. И питон тоже может быть им!
Код:
import os
import subprocess
import sys

ISO_LIST = os.listdir(sys.argv[1])

FOLDER_NAME = sys.argv[2]

os.makedirs(FOLDER_NAME, exist_ok=True)

for iso in ISO_LIST:
    if iso.endswith(".iso"):
        print(f"Now compressing: {iso}")
        out_file = os.path.splitext(iso)[0] + '.cso'
        sp = subprocess.run(["./ciso", "9", iso, f"{FOLDER_NAME}/{out_file}"])

В данном скрипте в цикле запускается внешний бинарь, а у выходных файлов указывается расширение .CSO. За запуск внешних процессов отвечает модуль subprocess.
Код:
user@desktop ~/G/ciso> python ciso_all_isos.py . cso_files                                                 master?
Now compressing: From Russia with Love - 007.iso
Compressed ISO9660 converter Ver.1.02 by BOOSTER
Compress 'From Russia with Love - 007.iso' to 'cso_files/From Russia with Love - 007.cso'
Total File Size 732495872 bytes
block size      2048  bytes
index align     1
compress level  9
ciso compress completed , total size = 565886491 bytes , rate 77%
Now compressing: Family Guy.iso
Compressed ISO9660 converter Ver.1.02 by BOOSTER
Compress 'Family Guy.iso' to 'cso_files/Family Guy.cso'
Total File Size 1186463744 bytes
block size      2048  bytes
index align     1
compress level  9
ciso compress completed , total size = 1101765517 bytes , rate 92%

Вообще, пакетная обработка в питоне сделана довольно приятно. Вот ещё один пример. В нём я хочу залить несколько картинок на сервер https://0x0.st.
Код:
import os
import requests

FILE_LIST = os.listdir()

def upload_pic(filename):
    with open(filename, "rb") as fname:
        r = requests.post("https://0x0.st", files={"file": fname})
        return r.text.strip()

for f in FILE_LIST:
    if f.endswith(".jpg"):
        print(upload_pic(f))

Запускаем:
Код:
# python upload_pics.py
https://0x0.st/ohHP.jpg
https://0x0.st/ohHZ.jpg
https://0x0.st/ohHN.jpg
https://0x0.st/ohHq.jpg
https://0x0.st/ohHb.jpg

requests - неофициальный, но очень популярный модуль реализующий HTTP клиент.

Или наоборот, сделаем качалку:
Код:
import sys
import requests

with open(sys.argv[1], "r") as fname:
    FILE_LIST = fname.readlines()

    for line in FILE_LIST:
        line = line.strip()

        r = requests.get(line)

        outfile = line.split("/")[-1]
       
        with open(outfile, "wb") as ofname:
            ofname.write(r.content)

Закидываем ссылки в текстовик и запускаем:
Код:
python download_files.py files.txt

Пример парсинга файла. Подсчитаем количество уникальных IP адресов в логе веб-сервера Nginx.
Код:
import sys

LOG_FILE = sys.argv[1]
UNIQUE_IPS = []
ALL_IPS = 0

logfile = open(LOG_FILE, "r")

for line in logfile:
    ip = line.split(" ")[0]
    ALL_IPS += 1
    if ip not in UNIQUE_IPS:
        UNIQUE_IPS.append(ip)

logfile.close()

print(f"Unique IPs: {len(UNIQUE_IPS)}, all IPs: {ALL_IPS}")

Пример работы:
Код:
# python unique_ips.py access.log
Unique IPs: 215, all IPs: 4373

Можно было бы воспользоваться регуляркой, или добавить дополнительные проверки... но сам формат лог-файла простой. Хотя... А вдруг нам подсунули не лог-файл?
Код:
import sys
import re

LOG_FILE = sys.argv[1]
UNIQUE_IPS = []
ALL_IPS = 0
IP_REGEX = r"(?:[0-9]{1,3}\.){3}[0-9]{1,3}"

logfile = open(LOG_FILE, "r")

for line in logfile:
    ip = re.findall(IP_REGEX, line)[0]
    ALL_IPS += 1
    if ip not in UNIQUE_IPS:
        UNIQUE_IPS.append(ip)

logfile.close()

print(f"Unique IPs: {len(UNIQUE_IPS)}, all IPs: {ALL_IPS}")


Заключение

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

Статья будет дополняться.

Прошивальщики

Samsung
  • JOdin - кроссплатформенный аналог прошивальщика Odin для прошивки смартфонов от Samsung. Требуется Java.

Sony
  • Flashtool - прошивка смартфонов от Sony

Xiaomi

Qualcomm
  • edl - прошивка устройств на Qualcomm через режим EDL. Требуется Python.
  • qdl - прошивка через EDL, не требует установки Python.

MTK

Собственно, это моя последняя машина, на которой установлен Линукс, а точнее Debian 11. Я ее использую для всяких экспериментов.

Накатил я Fvwm3. Хотел посмотреть, как там дела с ним. Оказывается, все очень хорошо (чего не скажешь про FreBSD. Там он неюзабельный). А тут все хорошо. Устанавливал по Дебиановскому рецепту.  Конечно, все заработало.  

А еще я накатил NcCDE. Люблю я олдскульные окружения. Компелять CDE не было охоты, да и идея эта так себе....прочитав мануалы понял, что несекюрно это все. Фиг знает, какие там дыры в коде. Так что остановился я на вышеупомянутом NcCDE.

Что могу сказать? Все работает, зомби процессов не создает, жрет ОЗУ как старый добрый lxde.

Мой вывод.

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


Эскизы(ов)
   

Поздравляем участников и посетителей форума с Новым 2023 годом!

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

С уважением, администрация форума /bin/dev.

Приветствую.

Вот и сам сабж. Название скрина говорит само за себя.

Это моя минималистская настройка для FVWM. Это все крутится на FreeBSD 13.1 Все работает. От звука, до 3d ускорения.

Звук идет через oss, так что имею теплый и ламповый звук. Ютуб работает, звук проигрывается, ненужны всякие ptlseaudio или apulse.

Флешки монтируются через dsbmc-cli. Это простая утилита, работающая из коробки. Хочется отметить, что автомонтирование в FreeBSD стало проще некуда. Есть утилита automount, которая тоже отлично работает.

Аптайм доходит до пару суток. Никаких фризов, утечек памяти. Ничего такого не наблюдаю. Очень доволен. Буду переводить все свои машины на FreeBSD.


Эскизы(ов)
   

Скажу так: тут ничего не изменилось с осени. Та же Fedora 37, GNOME 43 с BlurMyShell.

Но за последние три месяца я собрал сервер, накатил на него RHEL и ощущаю себя довольно сурьёзным деловым человеком, не абы какой бомж с улицы с Rocky Linux, а таки человек с большой... подпиской (хоть и бесплатной).

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

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

Ваш бункер уже наряжен? Гирляндочки моргают, елочка горит? Отлично, осталось лишь украсить рабочий стол.

Первым делом завозим снег. Снежок на компьютере обязателен, поэтому ставим xsnow и запускаем.
Открываем CCTV и смотрим количество снега снаружи нашего бункера, подкручиваем ползунки в настроечках до нужного количества, редактируем места обитания и объекты под свою местность.

Теперь черед игор. Обязательны к установке SuperTuxKart и OpenArena. Так я встречал 2022 год. Заходим на зимнюю карту с вашим любимым персонажем и начинаем гонку. Не забываем дрифтить и испускать запасы N2O. Затем, после того, как часы станут больше 00:00, запускаем OpenArena и дубасим всех, кого видим. Главное настройки под себя не забыть сконфигурировать, графику получше, если можно.

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


Эскизы(ов)
   
  • 1(current)
  • 2
  • 3
  • 4
  • 5
  • ...
  • 37
  • Следующий