python_async_loops

Eight different ways to implement an asyncronous loop in python  http://tobib.spline.de/xi/posts/2023-01-29-python-async-loops/
git clone https://git.ce9e.org/python_async_loops.git

commit
ca72ba1be3057594e39072768ade224b0bb54482
parent
9fef609449cc7859af9a8b0f1d773e8bd71968f8
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-01-29 17:03
tweak generator loops

Diffstat

M 06_generator_loop.py 52 ++++++++++++++++++++++++----------------------------
M 07_async_await_loop.py 52 ++++++++++++++++++++++++----------------------------

2 files changed, 48 insertions, 56 deletions


diff --git a/06_generator_loop.py b/06_generator_loop.py

@@ -34,11 +34,6 @@ class Task:
   34    34         self.done = False
   35    35         self.result = None
   36    36 
   37    -1     def select(self):
   38    -1         now = time.time()
   39    -1         timeout = min((t - now for t in self.times), default=None)
   40    -1         return {key.fileobj for key, mask in selector.select(timeout)}
   41    -1 
   42    37     def step(self, files, now):
   43    38         try:
   44    39             if self.done:
@@ -56,6 +51,19 @@ class Task:
   56    51         self.gen.close()
   57    52 
   58    53 
   -1    54 def run(gen):
   -1    55     task = Task(gen)
   -1    56     try:
   -1    57         while not task.done:
   -1    58             now = time.time()
   -1    59             timeout = min((t - now for t in task.times), default=None)
   -1    60             files = {key.fileobj for key, mask in selector.select(timeout)}
   -1    61             task.step(files, time.time())
   -1    62         return task.result
   -1    63     finally:
   -1    64         task.close()
   -1    65 
   -1    66 
   59    67 def sleep(t):
   60    68     yield set(), {time.time() + t}
   61    69 
@@ -80,28 +88,11 @@ def gather(*generators):
   80    88             task.close()
   81    89 
   82    90 
   83    -1 def run(gen):
   84    -1     task = Task(gen)
   85    -1     try:
   86    -1         while not task.done:
   87    -1             files = task.select()
   88    -1             task.step(files, time.time())
   89    -1         return task.result
   90    -1     finally:
   91    -1         task.close()
   92    -1 
   93    -1 
   94    91 def render():
   95    92     data[0] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
   96    93     print(' '.join(data))
   97    94 
   98    95 
   99    -1 def clock():
  100    -1     while True:
  101    -1         yield from sleep(10)
  102    -1         render()
  103    -1 
  104    -1 
  105    96 def popen(cmd, i):
  106    97     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
  107    98     reader = LineReader(proc.stdout)
@@ -109,18 +100,23 @@ def popen(cmd, i):
  109   100     try:
  110   101         while True:
  111   102             yield {proc.stdout}, set()
  112    -1             try:
  113    -1                 reader.read_line()
  114    -1                 data[i] = reader.line
  115    -1                 render()
  116    -1             except ValueError:
  117    -1                 break
   -1   103             reader.read_line()
   -1   104             data[i] = reader.line
   -1   105             render()
   -1   106     except ValueError:
   -1   107         pass
  118   108     finally:
  119   109         selector.unregister(proc.stdout)
  120   110         proc.terminate()
  121   111         proc.wait()
  122   112 
  123   113 
   -1   114 def clock():
   -1   115     while True:
   -1   116         yield from sleep(10)
   -1   117         render()
   -1   118 
   -1   119 
  124   120 def amain():
  125   121     yield from gather(
  126   122         popen(['./random.sh'], 1),

diff --git a/07_async_await_loop.py b/07_async_await_loop.py

@@ -43,11 +43,6 @@ class Task:
   43    43         self.done = False
   44    44         self.result = None
   45    45 
   46    -1     def select(self):
   47    -1         now = time.time()
   48    -1         timeout = min((t - now for t in self.times), default=None)
   49    -1         return {key.fileobj for key, mask in selector.select(timeout)}
   50    -1 
   51    46     def step(self, files, now):
   52    47         try:
   53    48             if self.done:
@@ -65,6 +60,19 @@ class Task:
   65    60         self.gen.close()
   66    61 
   67    62 
   -1    63 def run(coro):
   -1    64     task = Task(coro)
   -1    65     try:
   -1    66         while not task.done:
   -1    67             now = time.time()
   -1    68             timeout = min((t - now for t in task.times), default=None)
   -1    69             files = {key.fileobj for key, mask in selector.select(timeout)}
   -1    70             task.step(files, time.time())
   -1    71         return task.result
   -1    72     finally:
   -1    73         task.close()
   -1    74 
   -1    75 
   68    76 async def sleep(t):
   69    77     await AYield((set(), {time.time() + t}))
   70    78 
@@ -89,28 +97,11 @@ async def gather(*coros):
   89    97             task.close()
   90    98 
   91    99 
   92    -1 def run(coro):
   93    -1     task = Task(coro)
   94    -1     try:
   95    -1         while not task.done:
   96    -1             files = task.select()
   97    -1             task.step(files, time.time())
   98    -1         return task.result
   99    -1     finally:
  100    -1         task.close()
  101    -1 
  102    -1 
  103   100 def render():
  104   101     data[0] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  105   102     print(' '.join(data))
  106   103 
  107   104 
  108    -1 async def clock():
  109    -1     while True:
  110    -1         await sleep(10)
  111    -1         render()
  112    -1 
  113    -1 
  114   105 async def popen(cmd, i):
  115   106     proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
  116   107     reader = LineReader(proc.stdout)
@@ -118,18 +109,23 @@ async def popen(cmd, i):
  118   109     try:
  119   110         while True:
  120   111             await AYield(({proc.stdout}, set()))
  121    -1             try:
  122    -1                 reader.read_line()
  123    -1                 data[i] = reader.line
  124    -1                 render()
  125    -1             except ValueError:
  126    -1                 break
   -1   112             reader.read_line()
   -1   113             data[i] = reader.line
   -1   114             render()
   -1   115     except ValueError:
   -1   116         pass
  127   117     finally:
  128   118         selector.unregister(proc.stdout)
  129   119         proc.terminate()
  130   120         proc.wait()
  131   121 
  132   122 
   -1   123 async def clock():
   -1   124     while True:
   -1   125         await sleep(10)
   -1   126         render()
   -1   127 
   -1   128 
  133   129 async def amain():
  134   130     await gather(
  135   131         popen(['./random.sh'], 1),