handler.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import os
  2. import sys
  3. import pathlib
  4. import asyncio
  5. class handler:
  6. """
  7. That is used to appending data into log files, stdout and stderr.
  8. It requires file which is used to store logs.
  9. Methods
  10. -------
  11. async _to_file(content: str) : None
  12. That add content, as new line, to the file.
  13. async _to_stdout(content: str) : None
  14. That add content, as new line, to the stdout.
  15. async _to_stderr(content: str) : None
  16. That add content, as new line, to the stderr.
  17. """
  18. def __init__(self, target: pathlib.Path | None) -> None:
  19. """
  20. That create required locks, and log file when it is not exists.
  21. Parameters
  22. ----------
  23. target : pathlib.Path | None
  24. File which would be used to store logs. If it is set to None, then
  25. only stdout and stderr could be used.
  26. """
  27. self.__file_lock = asyncio.Lock()
  28. self.__stderr_lock = asyncio.Lock()
  29. self.__stdout_lock = asyncio.Lock()
  30. self.__target = target
  31. self.__pipe = None
  32. if target is not None and not target.exists():
  33. target.touch()
  34. async def _to_file(self, content: str) -> None:
  35. """
  36. That adding given content as new line in the file.
  37. Parameters
  38. ----------
  39. content : str
  40. Content which would be added as new line in the file.
  41. """
  42. if self.__target is None:
  43. return
  44. async with self.__file_lock:
  45. await asyncio.to_thread(self.__add_file, content)
  46. def __add_file(self, content: str) -> None:
  47. """
  48. That adding given content as new line to the file. It is synchronized
  49. function, running in new thread. When file is not open, that open it.
  50. Parameters
  51. ----------
  52. content : str
  53. Content to append into file as new line.
  54. """
  55. if self.__pipe is None or self.__pipe.closed:
  56. self.__pipe = self.__target.open("a")
  57. self.__pipe.write(content + os.linesep)
  58. async def _to_stdout(self, content: str) -> None:
  59. """
  60. That add content to stdout fifo as new line.
  61. Parameters
  62. ----------
  63. content : str
  64. New content which would be add to stdout.
  65. """
  66. content = content + os.linesep
  67. async with self.__stdout_lock:
  68. await asyncio.to_thread(sys.stdout.write, content)
  69. async def _to_stderr(self, content: str) -> None:
  70. """
  71. That add content to stderr fifo as new line.
  72. Parameters
  73. ----------
  74. content : str
  75. New content, which would be add to stderr.
  76. """
  77. content = content + os.linesep
  78. async with self.__stderr_lock:
  79. await asyncio.to_thread(sys.stderr.write, content)
  80. def __del__(self) -> None:
  81. """
  82. That is object destructor, which close log file, when it is not
  83. closed yet.
  84. """
  85. if self.__pipe is None:
  86. return
  87. if self.__pipe.closed:
  88. return
  89. self.__pipe.close()