1

I am sorry for re-asking this but I made the mistake of not providing enough detail. I want to align string and adjust spacing in a column I asked this question.

Here: How to align strings in columns?

But I was not able to apply it to my detailed code which was my mistake for not providing.

My code:

import time
seperator='|'+'-'*33+'|\n'
seperator2='|'+'='*33+'|\n'
end = '|'+'^'*33+'|'
t=['Tuesday','July','2022','03','06']
try:
 with open('time.txt','r') as f: 
    content = f.readlines()
except:
 with open('time.txt','w') as f: 
    f.write('pass')
with open('time.txt','r') as f: 
 content = f.readlines()
if content[0] != '_________________________________\n':
 with open('time.txt','w') as f:
            header= '_'*33+'\n'+\
                    '|Day |Month |Year |Hour |Minute |\n'
            data = (f'|{t[0]} |{t[1]} |{t[2]}'
            f'|{t[3]} |{t[4]} |\n')
            f.write(header+seperator+data+end)
elif content[0] == '_________________________________\n':
 with open('time.txt','r+') as f:
            saved=f.readlines()[:-1]
            f.seek(0)
            data = (f'|{t[0]} |{t[1]} |{t[2]}'
            f'|{t[3]} |{t[4]} |\n')
            f.writelines(saved+[seperator2,data,end]) 

Output in the time.txt file(if it has been ran once):

_________________________________
|Day |Month |Year |Hour |Minute |
|---------------------------------|
|Tuesday |July |2022|03 |06 |
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|

Output(twice)(showing this to clarify that the data should be saved and re-printed):


_________________________________
|Day |Month |Year |Hour |Minute |
|---------------------------------|
|Tuesday |July |2022|03 |06 |
|=================================|
|Tuesday |July |2022|03 |06 |
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|

The output I want:

_________________________________
|Day |Month |Year |Hour |Minute |
|-------------------------------|
|Tuesday |July |2022|03 |06     |
|===============================|
|Tuesday |July |2022|03 |06     |
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|

The post I made at first is here: How to align strings in columns?

The one I didn't detail my post in maybe you could read the question I asked their and the answers.

Sorry for not adding detail the first time.

Any help would be appreciated, Thanks.

Jeremy
  • 22,188
  • 4
  • 68
  • 81
  • 1
    Why don't you just use the `pprint` or `tabulate` or `prettytable` modules? Less code to print only an array with data. – Laurent Jul 07 '22 at 17:01

2 Answers2

3

As someone already mentioned, if you want the print statement to look exactly like the dashed table you should use tabulate

I guess if you use tabulate there should be a cleaner way of parsing the .txt file, here is an example on how to use tabulate

table = tabulate(rows, headers=["Day","Month","Year", "Hour","Minute"])

Where rows is a list of lists or another tabular data type.

pterodactella
  • 121
  • 12
1

Though there may be alternative approaches that will save you some effort if you don't mind parsing the entire existing file (pandas, tabulate, etc.), here's a strategy specific to your datetime data and your approach of appending to an arbitrary number of rows of existing data (which requires that the existing data is already in a predetermined format consistent with the row to be appended) that will ensure field labels, fields and separators are all aligned:

import calendar

def appendDatetimeToFile(t, fname='time.txt'):
    labels = ['Day', 'Month', 'Year', 'Hour', 'Minute']
    maxDayLen = len(max(calendar.day_name, key=len))
    maxMonthLen = len(max(calendar.month_name, key=len))
    fieldLens = [maxDayLen + 1, maxMonthLen + 1, 5, 3, 3]
    fieldLens = [max(fieldLens[i], len(labels[i])) for i in range(len(labels))]

    def makeLineFromFields(fields):
        toEval = [f'f"{{\'{fields[i]}\':{fieldLens[i] + 1}}}"' for i in range(len(fields))]
        return '|'.join([''] + [eval(toEval[i]) for i in range(len(fields))] + ['\n'])

    def makeSeparator(c, border=None):
        border = border if border else c
        return ''.join([border] + [c] * (sum(fieldLens) + 2 * len(fieldLens) - 1) + [border] + ['\n'])
    labelsHeader = makeSeparator('_')
    labelsFooter = makeSeparator('-', '|')
    dataSeparator = makeSeparator('=', '|')
    dataFooter = makeSeparator('^', '|')

    data = makeLineFromFields(t)

    try:
        with open('time.txt','r') as f: 
            content = f.readlines()
    except:
        with open('time.txt','w') as f: 
            f.write('pass')
    with open('time.txt','r') as f: 
        content = f.readlines()
    if content[0] != labelsHeader:
        with open('time.txt','w') as f:
            header = labelsHeader + makeLineFromFields(labels) + labelsFooter
            f.write(header + data + dataFooter)
    else:
        with open('time.txt','r+') as f:
            saved = f.readlines()[:-1]
            f.seek(0)
            f.writelines(saved +[dataSeparator, data, dataFooter]) 

t=['Tuesday','July','2022','03','06']
appendDatetimeToFile(t)

Output if file doesn't exist:

______________________________________________
|Day        |Month      |Year  |Hour |Minute |
|--------------------------------------------|
|Tuesday    |July       |2022  |03   |06     |
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|

Output if file exists with one row:

______________________________________________
|Day        |Month      |Year  |Hour |Minute |
|--------------------------------------------|
|Tuesday    |July       |2022  |03   |06     |
|============================================|
|Tuesday    |July       |2022  |03   |06     |
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|
constantstranger
  • 9,176
  • 2
  • 5
  • 19
  • Umm first of all the formatting is wrong second of all im not just going to be using times i can be using any custom string with any length the formatting between the header is |-----------| not =========== the formatting for the rest is |=============| and the end is |^^^^^^^^^^^^^^^^| –  Jul 08 '22 at 03:16
  • Updated answer to fix the lines that are not labels or data. Regarding your clarification that you are not just going to be using times, that was not stated in your original question. If you want a solution that works for "any custom string with any length", it will be challenging to have the rows in the file adhere to a uniform width without using two passes: one to ascertain the maximum width of the data (likely at a field-by-field granularity) and a second to rewrite all lines. In other words, the idea of reusing `saved` as-is would need to be abandoned. – constantstranger Jul 08 '22 at 14:46
  • This is excellent. It wasn't what I was looking for, but it helps to solidify in my mind what I would do if I needed to build an aligner myself. +1 – bballdave025 Jul 25 '23 at 21:02