Let's say I have this code:
from prettytable import PrettyTable
f = open("test.txt", "w")
t = PrettyTable()
def main():
animal = input("Enter an animal: ")
car = input("Enter a car: ")
column_names = ["animal", "car"]
t.add_column(column_names[0], [animal])
t.add_column(column_names[1], [car])
table_txt = t.get_string()
with open("test.txt", "w") as file:
file.write(table_txt)
def append():
shoe = input("Enter a shoe: ")
table_txt = t.get_string()
with open("test.txt", "a") as file:
file.write(table_txt)
cnt = input("Are you appending, or submitting new data? A for APPEND, N for NEW: ")
if cnt == 'N':
main()
else:
if cnt == 'A':
append()
f.close()
When I first write to the file, I type "N" when asked to create a new table, and enter "cat" for animal, and "Honda" for car and get this result:
+--------+-------+
| animal | car |
+--------+-------+
| cat | Honda |
+--------+-------+
If I wanted to append data (shoe) to the file, I would select "A" when asked, and enter a type of shoe. How can I append this data to the table as a new column, without created a whole new table?
**Update:
The problem with your current approach toward appending newly entered data is that the horizontal width of the rendered table might change depending on the length of the string entered by the user. Because of this, it doesn't seem advisable to open that .txt
file with the a
(append) flag, and you should consider rewriting the entire file once new data has been added to the table.
In order to add a new row to the table, you use the add_row
method and pass a list containing the column values, for example:
t.add_row(['shoe', shoe])
If you really really want to only append the newly added row's rendering to your textfile, you seem in need of some kind of helper function in order to obtain the total number of rows in your table, as I couldn't find any method provided by the PrettyTable
API. Such a function could look like this:
table_rows = lambda t: len(t.get_string().split('\n'))-4
It simply counts the lines in the table's prettyfied rendering as returned by its get_string
method, and substracts three for lines for the header, and one for the bottom hline. Be aware that this very naïve implementation will break as soon as you overwrite the table's hrules
property, so instead of pulling a stunt like this, you should keep track of the table's total row count yourself (assign total_rows += 1
every time a new row gets added)! But as long as you don't change any of the underlying assumptions about the rendering, you can use this function to determine the row index from which on you want to render the table:
table_txt = t.get_string(start=table_rows(t)-1)
row_txt = '\n'.join(table_txt.split('\n')[-2:])
with open("test.txt", "a") as file:
file.write("\n" + table_txt)
This way, you let the library render a table only showing the latest row, which you then break up along the linebreaks so you can get rid of the header using list slicing ([-2:]
). You reassemble the resulting list of individual lines into a single string containing linebreaks by using the '\n'.join()
call. When you append the result to your textfile, you need to insert a linebreak first, because table rendering returned by get_string
doesn't terminate with one.