You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.3 KiB

import json
import logging
from multiprocessing.connection import Listener, Connection
from typing import Union
class WorkerIOError(KeyboardInterrupt):
pass
class IOModule:
'''Класс модуля ввода/вывода для воркеров.'''
def __init__(self, listener: Listener, command_name: str):
self._listener: Listener = listener
self._connection: Union[Connection, None] = None
self._command: str = command_name
self._script: str = ""
@property
def command(self) -> str:
return self._command
@property
def script(self) -> str:
return self._script
@script.setter
def script(self, script: str) -> None:
self._script = script
def set_debug(self, msg: str) -> None:
self.output(msg, level=logging.DEBUG)
def set_info(self, msg: str) -> None:
self.output(msg, level=logging.INFO)
def set_warning(self, msg: str) -> None:
self.output(msg, level=logging.WARNING)
def set_error(self, msg: str) -> None:
self.output(msg, level=logging.ERROR)
def set_critical(self, msg: str) -> None:
self.output(msg, level=logging.CRITICAL)
def output(self, text: str, level: int = logging.INFO) -> None:
'''Метод для отправки серверу вывода с указанием уровня.'''
output_request = {"state": "exec",
"status": 0,
"data": {
"type": "message",
"logging": level,
"text": text,
"source": self._script
}
}
self.send(output_request)
def input(self, msg: str) -> str:
'''Метод через который возможен ввод данных в скрипт.'''
input_request = {"state": "input",
"status": 0,
"data": {"text": msg,
"source": f"{self.command}:{self.script}"}}
answer = None
while answer is None:
self.send(input_request)
answer = self.receive()
return answer['data']
def send(self, data: dict) -> None:
'''Метод для отправки данных серверу.'''
if self._connection is None:
raise WorkerIOError("No one is connected now.")
data = json.dumps(data).encode()
self._connection.send_bytes(data)
def receive(self) -> dict:
'''Метод для получения данных от сервера.'''
if self._connection is None:
raise WorkerIOError("No one is connected now.")
data: bytes = self._connection.recv_bytes()
return json.loads(data.decode())
def __enter__(self):
self._connection = self._listener.accept()
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
if exc_type:
print("exc_type =", exc_type)
print("exc_value =", exc_value)
print("exc_traceback =", exc_traceback)
if exc_type is KeyboardInterrupt:
print("correctly")
if not self._connection.closed:
self._connection.close()