'Is there a way to decouple a csv generator in my code that doesn't close the file?
I wanted to write the following to decouple a data feed from the rest of my program, but it doesn't work throwing error - "ValueError: I/O operation on closed file."
class Feed:
def __init__(self, data_loc=None):
self.data_loc = data_loc
with open(self.data_loc, newline='') as f:
self.reader = csv.reader(f)
def get_next_tick(self):
return next(self.reader)
raw_data_loc = '{path to file}'
feed = Feed(data_loc=raw_data_loc)
print(feed.get_next_item())
I understand that after init is run the file closes and hence the error, but is there a way of achieving the separation of this csv generator in my code?
Solution 1:[1]
Expanding on my comment, you can implement Feed as a context manager like so:
class Feed:
def __init__(self, *args, **kwargs):
self.file_obj = open(*args, **kwargs)
self.reader = csv.reader(self.file_obj)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def get_next_tick(self):
return next(self.reader)
def close(self):
self.file_obj.close()
To print the first line of the feed we can do the following:
with Feed('feed.csv') as feed:
print(feed.get_next_tick())
Because we used a context manager, the __exit__ method is called even if the feed is empty and raises a StopIteration exception.
If you want to be able to iterate over the feed, you can add __next__ and __iter__ methods like so:
class Feed:
def __init__(self, *args, **kwargs):
self.file_obj = open(*args, **kwargs)
self.reader = csv.reader(self.file_obj)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def __next__(self):
return self.get_next_tick()
def __iter__(self):
return self
def get_next_tick(self):
return next(self.reader)
def close(self):
self.file_obj.close()
This will allow you to loop over your feed or even call next(feed) directly, eg:
with Feed('feed.csv') as feed:
for item in feed:
print(item)
Python Tips has a great chapter on using Context Managers, which were introduced in PEP343.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Kyle G |
