utils.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import asyncio
  2. import random
  3. import socket
  4. import string
  5. import time
  6. from collections import OrderedDict
  7. from contextlib import closing
  8. import queue
  9. from os.path import abspath, dirname
  10. project_dir = dirname(abspath(__file__))
  11. STATIC_PATH = '%s/html' % project_dir
  12. class LimitedSizeQueue(queue.Queue):
  13. """
  14. 有限大小的队列
  15. `get()` 返回全部数据
  16. 队列满时,再 `put()` 会阻塞
  17. """
  18. def get(self):
  19. """获取队列全部数据"""
  20. try:
  21. return super().get(block=False)
  22. except queue.Empty:
  23. return []
  24. def _init(self, maxsize):
  25. self.queue = []
  26. def _qsize(self):
  27. return len(self.queue)
  28. # Put a new item in the queue
  29. def _put(self, item):
  30. self.queue.append(item)
  31. # Get an item from the queue
  32. def _get(self):
  33. all_data = self.queue
  34. self.queue = []
  35. return all_data
  36. async def wait_host_port(host, port, duration=10, delay=2):
  37. """Repeatedly try if a port on a host is open until duration seconds passed
  38. from: https://gist.github.com/betrcode/0248f0fda894013382d7#gistcomment-3161499
  39. :param str host: host ip address or hostname
  40. :param int port: port number
  41. :param int/float duration: Optional. Total duration in seconds to wait, by default 10
  42. :param int/float delay: Optional. Delay in seconds between each try, by default 2
  43. :return: awaitable bool
  44. """
  45. tmax = time.time() + duration
  46. while time.time() < tmax:
  47. try:
  48. _reader, writer = await asyncio.wait_for(asyncio.open_connection(host, port), timeout=5)
  49. writer.close()
  50. await writer.wait_closed()
  51. return True
  52. except:
  53. if delay:
  54. await asyncio.sleep(delay)
  55. return False
  56. def get_free_port():
  57. """
  58. pick a free port number
  59. :return int: port number
  60. """
  61. with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
  62. s.bind(('', 0))
  63. s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  64. return s.getsockname()[1]
  65. def random_str(len=16):
  66. """生成小写字母和数组组成的随机字符串
  67. :param int len: 字符串长度
  68. """
  69. return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(len))
  70. def run_as_function(gen):
  71. res = None
  72. while 1:
  73. try:
  74. res = gen.send(res)
  75. except StopIteration as e:
  76. if len(e.args) == 1:
  77. return e.args[0]
  78. return
  79. async def to_coroutine(gen):
  80. res = None
  81. while 1:
  82. try:
  83. c = gen.send(res)
  84. res = await c
  85. except StopIteration as e:
  86. if len(e.args) == 1:
  87. return e.args[0]
  88. return
  89. class LRUDict(OrderedDict):
  90. """
  91. Store items in the order the keys were last recent updated.
  92. The last recent updated item was in end.
  93. The last furthest updated item was in front.
  94. """
  95. def __setitem__(self, key, value):
  96. OrderedDict.__setitem__(self, key, value)
  97. self.move_to_end(key)