Christopher Metcalf
Christopher Metcalf

Reputation: 45

How to align text in output to file

I'm finding a lot of solutions on how to print in many styles/formats etc but I need to know how to do them inside of a file.

I have the code below...

import glob
import getpass
user = getpass.getuser()

import time

timestr = time.strftime("%Y%m%d-%H%M%S")
read_files = glob.glob("myOrders/*.txt")

with open("myOrderCopies/" +user+ "_" +timestr+ "_Hard_Drive_Order.txt", "wb") as outfile:
    for f in read_files:
        with open(f, "rb") as infile:
            outfile.write(infile.read())

# Read .txt file and putlines row_name and Product ID into new .txt file
searchquery = 'row_name', 'Product ID'

#source file
with open("myOrderCopies/" +user+ "_" +timestr+ "_Hard_Drive_Order.txt") as f1:
    #output file
    with open("hwOrderCopies/" +user+ "_" +timestr+ "_HardDriveSummary.txt", "wt") as f2:
        lines = f1.readlines()
        for i, line in enumerate(lines):
            if line.startswith(searchquery):
                f2.write("\n" + line)
                #f2.write(lines[i + 1])
                #f2.write(lines[i + 2])

#count how many occurances of 'Product ID'
import os

#def main():
with open("hwOrderCopies/" +user+ "_" +timestr+ "_HardDriveSummary.txt", "a+") as f:
    term = "Product ID"
    count = f.read().count(term)
    f.seek(os.SEEK_END)  # Because we've already read the entire file. Go to the end before writing otherwise we get an IOError
    f.write("\nTotal Number of Hard Drives: "+str(count)+ "\n\n")

which works to get what I want in the file. The problem is with the alignment (below). How can I get the results for row_name to align on the right?

row_name        California Datacenter

Product ID                      : ST3600057SS

Product ID                      : ST3600057SS

Total Number of Hard Drives: 2

Upvotes: 0

Views: 2188

Answers (1)

Chris Larson
Chris Larson

Reputation: 1714

Using a list to illustrate the use of format() to align an item, the way to address your issue is the following:

row_item = ['row_name', 'California Datacenter']
output = '{}{:>40}'.format(row_item[0], row_item[1])

print(output)

Output:

row_name                   California Datacenter

The '{}' occurrences represent a single variable in the format(variable_1, variable_2) example.

The syntax inside the second element ({:>40}) represents right alignment, using the :>. :< would be left alignment. The 40 designates that the width of the output field will be padded to 40 characters.

Here's a somewhat optimized version of your code that should result in your desired output, has variables renamed to be more readable (always a good habit to consider), and formatting available as a variable. As mentioned, the number in the formatting string determines the width of the padding. Adjusting that will move the columns closer or farther. Note that I've taken the liberty of formatting the Product ID rows as well as row_name.

I've also abstracted your filenames to variables, for readability, as well, and moved the second set of nested with open() statements into compound with context managers, as they don't change within the loop.

import glob
import os
import time
import getpass

user = getpass.getuser()

timestr = time.strftime("%Y%m%d-%H%M%S")
read_files = glob.glob("myOrders/*.txt")
myOrderCopies_file = "myOrderCopies/" + user + "_" + timestr + "_Hard_Drive_Order.txt"
hwOrderCopies_file = "hwOrderCopies/" + user + "_" + timestr + "_HardDriveSummary.txt"

searchquery = 'row_name', 'Product ID'
term = "Product ID"

formatting = '{:<40}{:>}\n\n'

# Read .txt files and put lines 'row_name' and 'Product ID' into new .txt file
with open(myOrderCopies_file, "wb") as myOrderCopies:
    for file_name in read_files:
        with open(file_name, "rb") as infile:
            myOrderCopies.write(infile.read())

with open(myOrderCopies_file, 'rb') as myOrderCopies, open(hwOrderCopies_file, "w") as hwOrderCopies:
    term_counter = 0
    lines = myOrderCopies.readlines()
    for line in lines:
        if line.startswith(searchquery):
            if "row_name" in line:
                split_line = line.split('        ')
            else:
                if term in line:
                    term_counter += 1
                split_line = line.split('                      : ')
            hwOrderCopies.write(formatting.format(split_line[0], split_line[1]))
    hwOrderCopies.write("\nTotal Number of Hard Drives: {}\n\n".format(str(term_counter)))

Upvotes: 2

Related Questions