Оформление службы в systemd из файла python

Для того чтобы служба полноценно работала, в файле python необходимо предусмотреть:

  1. Блокировку запуска копии скрипта
  2. Создание pid файла с номером процесса

Теоретически это возможно возложить и на плечи systemd, но «классически» делать это самому.

Пример создания pid файла:

import os
    # выясним id процесса т создадим pid файл
    try:
        pid=os.getpid()
        with open(f"/var/run/ocpp_{sys.argv[1]}.pid", "w") as file:
            file.write(str(pid))
    except Exception as e:
        functions.logapi.error(f"Не удалось создать PID файл {e}");

Пример блокировки запуска копии:

from filelock import FileLock,Timeout    
    lock = FileLock(f"{sys.argv[1]}.lock",0)
    try:
        lock.acquire()
    except Timeout:
        functions.logapi.error(f"инстанс {sys.argv[1]} уже запущен на сервере");
        exit(-1);
    with lock:
        functions.logapi.debug(f"включена блокировка запусков других инстансов");

Пример файла настройки службы в этом случае (xx.service):

[Unit]
Description=ocpp1

[Service]
ExecStart=python3 /home/user/цувцув/цувцу.py ocpp1
PIDFile=/var/run/ocpp_ocpp1.pid

[Install]
WantedBy=multi-user.target

В Ubuntu его необходимо положить в /etc/systemd/system и перезапустить службу:

sudo systemctl daemon-reload

Python: минимальный каркас websocket сервера

Из «коробки» в этом каркасе работа в потоках для обработки каждого сообщения. Собрано на основе пакета websockets.

Все клиенты хранятся в массиве clients. При отключении клиента — из массива он удаляется.

#!/usr/bin/env python3
#encoding: utf-8
import asyncio
import sys
import os
import websockets
from threading import Thread

# массив клиентов
clients=[]

# отправляем сообщение
def SendMessage(connect, message):
    asyncio.run(connect["connect"].send(message))

def MessageProcessing(websocket,message):
  # выясняем от кого обрабатываем сообщения
  for connect in clients:
     if connect["connect"] == websocket:
        print(f"IN: {message}")
        SendMessage(connect,"Hello")

# новый клиент
async def OnNewClient(websocket, path):
        requested_protocols = websocket.request_headers['Sec-WebSocket-Protocol']
        patch = path.strip('/')
        print(f"Новый клиент: {requested_protocols},{patch}")
        try:
          pasket = {}
          pasket["connect"] = websocket
          pasket["host"] = websocket.request_headers['Host']
          clients.append(pasket)
          async for message in websocket:
               th = Thread(target=MessageProcessing, args=(websocket,message,))
               th.start()
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(f"Прерывание: {e} ({fname},строка: {exc_tb.tb_lineno})")

        finally:
            print(f"соединение закрыто..")
            for connect in clients:
                if connect["connect"]==websocket:
                    clients.remove(connect)

async def main():
  async with websockets.serve(OnNewClient, "0.0.0.0", 35609,subprotocols=["virtual"]):
    print("сервер стартовал и ждёт клиентов")
    await asyncio.Future()

asyncio.run(main())

PHP AMP Websocket: указание произвольных заголовков при рукопожатии

Задача: добавить произвольный заголовок клиенту при рукопожатии с сервером. Например Sec-WebSocket-Protocol

Решение:

use Amp\Delayed;
use Amp\Websocket\Client\Connection;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\Message;
use function Amp\Websocket\Client\connect;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;

            Amp\Loop::run(function () use ($wss_url,$ip,$port,$pascket,&$answer,$wait_reseive) {                            
                $tlsc=new ClientTlsContext("");
                $tlw=$tlsc->withoutPeerVerification();
                $connectContext = (new ConnectContext)->withTlsContext($tlw);
                $handshake = (new Handshake("ws://1.18.24.70:$port/virtual_api_1c"))->withHeader('Sec-WebSocket-Protocol', 'virtual');  
                $connection = yield connect($handshake,$connectContext);   
                yield $connection->send($pascket);
                yield $connection->close();
            });  

NetBeans 14 и поддержка Python

Начиная с версии 8.1, python плагины не поддерживаются официально и установить из самой IDE их нельзя, однако неофициальные плагины таки существуют.

Скачать пакет с плагинами можно здесь

Установка: Tools -> Plugins -> Downloaded -> Add Plugins

PostgreSQL: вывод числа в виде значения часы:минуты:секунды

Задача: в одной из колонок хранятся секунды в виде значения int, необходимо при выводе преобразовать их по маске hh:mm:ss

Решение:

TO_CHAR((docs_charge.duration || ' second')::interval, 'HH24:MI:SS') as duration
1 64 65 66 67 68 308