Programming, electronics, lifestyle
Some time ago I realized that there is no a library to keep a stack of strings in a text file efficiently in Python. So I coded own one. I commented the code, and I suppose that any additional words will be redundant.
#! /usr/bin/env python3
#####################################################################
# The library allows to work with stack of strings in a text file #
# To use import this file as library (ex. for same dir) #
# from stack import Stack #
# Author: Artem Smirnov <[email protected]> #
#####################################################################
import threading
class Stack():
"""
The class allows to work with stack of strings in a text file
"""
def __init__(self, filepath: str):
"""
Provide path to file where stack is located.
"""
self.path = filepath
self.lock = threading.Lock()
def is_empty(self):
"""
Method allows to get state of the stack
"""
with self.lock:
with open(self.path, 'r') as fd:
fd.seek(0, 2)
return fd.tell() < 1
def pop(self) -> str:
"""
Method allow to pop one string from the stack
"""
with self.lock:
with open(self.path, 'r+') as fd:
# go to last character in the file
fd.seek(0, 2)
end = fd.tell()
pos = end
buf = ""
nlpos = -1
# for better performance it should be a little bit more than medium line size
chunk_size = 1
# while not found
while nlpos == -1 and pos != 0:
pos -= chunk_size
# if it is a last string in the file
if pos < 0: pos = 0
fd.seek(pos)
buf = fd.read(chunk_size) + buf
# try to find nl (newline) symbol, except last
nlpos = buf.rfind("\n", 0, -1)
pos = pos + nlpos + 1
fd.seek(pos)
fd.truncate()
if buf == "":
return None
else:
buf = buf[nlpos+1:-1]
return buf
def push(self, line: str):
"""
Method allow to push one string to the stack
"""
with self.lock:
with open(self.path, 'a') as fd:
fd.write(line + "\n")
def main():
"""
Example of usage. It will create 10 items in stack,
and will pop it
"""
FILENAME = "./testfile.sql"
stack = Stack(FILENAME)
for i in range(1,10):
stack.push(f"push-{i}")
while not stack.is_empty():
print(stack.pop())
if __name__ == "__main__":
main()