2023-07-17 03:21:00 +02:00
\[ [Index ](index.md ) | [Exercise 8.2 ](ex8_2.md ) | [Exercise 8.4 ](ex8_4.md ) \]
# Exercise 8.3
*Objectives:*
- Using coroutines to set up processing pipelines
*Files Created:* `cofollow.py` , `coticker.py`
**Note**
For this exercise the `stocksim.py` program should still be
running in the background.
2023-07-17 17:41:16 +02:00
In [Exercise 8.2 ](ex8_2.md ) you wrote some code that used
2023-07-17 03:21:00 +02:00
generators to set up a processing pipeline. A key aspect of that
program was the idea of data flowing between generator functions. A
very similar kind of dataflow can be set up using coroutines. The
only difference is that with a coroutine, you send data into different
processing elements as opposed to pulling data out with a for-loop.
## (a) A coroutine example
Getting started with coroutines can be a little tricky. Here is an
example program that performs the same task as
2023-07-17 17:41:16 +02:00
[Exercise 8.2 ](ex8_2.md ), but with coroutines. Take this program
2023-07-17 03:21:00 +02:00
and copy it into a file called `cofollow.py` .
```python
# cofollow.py
import os
import time
# Data source
def follow(filename,target):
with open(filename,'r') as f:
f.seek(0,os.SEEK_END)
while True:
line = f.readline()
if line != '':
target.send(line)
else:
time.sleep(0.1)
# Decorator for coroutine functions
from functools import wraps
def consumer(func):
@wraps (func)
def start(*args,**kwargs):
f = func(*args,**kwargs)
f.send(None)
return f
return start
# Sample coroutine
@consumer
def printer():
while True:
item = yield # Receive an item sent to me
print(item)
# Example use
if __name__ == '__main__':
follow('Data/stocklog.csv',printer())
```
Run this program and make sure produces output.. Make sure you understand how the different pieces are hooked together.
## (b) Build some pipeline components
In a file `coticker.py` , build a series of pipeline components that carry out the same tasks as
2023-07-17 17:41:16 +02:00
the `ticker.py` program in [Exercise 8.2 ](ex8_2.md ). Here is the implementation of the
2023-07-17 03:21:00 +02:00
various pieces.
```python
# coticker.py
from structure import Structure
class Ticker(Structure):
name = String()
price =Float()
date = String()
time = String()
change = Float()
open = Float()
high = Float()
low = Float()
volume = Integer()
from cofollow import consumer, follow
from tableformat import create_formatter
import csv
# This one is tricky. See solution for notes about it
@consumer
def to_csv(target):
def producer():
while True:
yield line
reader = csv.reader(producer())
while True:
line = yield
target.send(next(reader))
@consumer
def create_ticker(target):
while True:
row = yield
target.send(Ticker.from_row(row))
@consumer
def negchange(target):
while True:
record = yield
if record.change < 0:
target.send(record)
@consumer
def ticker(fmt, fields):
formatter = create_formatter(fmt)
formatter.headings(fields)
while True:
rec = yield
row = [getattr(rec, name) for name in fields]
formatter.row(row)
```
Your challenge: Write the main program that hooks all of these components together to
generate the same stock ticker as in the previous exercise.
\[ [Solution ](soln8_3.md ) | [Index ](index.md ) | [Exercise 8.2 ](ex8_2.md ) | [Exercise 8.4 ](ex8_4.md ) \]
----
`>>>` Advanced Python Mastery
`...` A course by [dabeaz ](https://www.dabeaz.com )
`...` Copyright 2007-2023
. This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License ](http://creativecommons.org/licenses/by-sa/4.0/ )