Skip to content

Python output align by column

wordpress meta

title: 'Python Output Align by Column'
date: '2015-01-23T14:19:52-06:00'
status: publish
permalink: /python-output-align-by-column
author: admin
excerpt: ''
type: post
id: 820
category:
    - Python
tag: []
post_format: []

I have used several ways in the past to have very simple column headers and subsequent output lines line up. Of course everything can be static but I like to have column headers adjust their size based on some of the data.

For example if I have column headers in an array like this:
header = ['File Name','File Size']

I want to use this array to print the header line but before printing it I want to adjust the column width for 'File Name' to the longest file name that is in the list yet to be processed. The following example is one way of doing it.

I played with other options also(see update 01.24.15 below).

Honestly I think the main reason for doing it dynamically is I like to print the headers and data with minimal lines of code.

#!/usr/bin/env python
import os,glob,sys
FORMAT = [('File Name',10),('Size',12)]

## In a real use case this function will probably do a lot more
## for example MB to GB conversions etc.
## But important here is where I make the adjustment to the main array
## to stretch the 'File Name' field.
def makeEntry(fileN,fileS):
  global FORMAT
  entry = []
  entry = [fileN, fileS]

  if len(fileN) > FORMAT[0][1]:
    n = dict(FORMAT)            # tuples are immutable so have to change to something writeable
    n['File Name'] = len(fileN) + 2 # expanding field width
    FORMAT = n.items()          # overwrite original

  return entry

os.chdir('/DATA/')
video_files = []
for files in ('*.m4v', '*.mp4', '*.ts','*.dvr-ms','*.avi','*.mkv'):
  video_files.extend(glob.glob(files))

## Loop through files and build an array
fArr = []
for fileN in video_files:
  fArr.append(makeEntry(fileN, os.path.getsize(fileN)))

## Print header
for item in FORMAT:
  print "{header:{width}}".format (header=item[0], width=item[1]),
print

## Print entries
for entry in fArr:
  #print ("%-" + str(FORMAT[0][1]) + "s %-" + str(FORMAT[1][1]) + "s") % (entry[0], entry[1])       # old style
  print "{f0:{w0}} {f1:{w1}}".format ( f0=entry[0], w0=FORMAT[0][1], f1=entry[1], w1=FORMAT[1][1] ) # new style

Update 01.24.15
Above example is fine except I did not like the way I updated the tuple. Below example use a dict for the header.

#!/usr/bin/env python
import os,glob,sys

FORMAT = {'File Name':10,'Size':12} 

def makeEntry(fileN,fileS):
  global FORMAT
  entry = []
  entry = [fileN, fileS]
  if len(fileN) > FORMAT['File Name']:
    FORMAT['File Name'] = len(fileN) + 2    # expanding field width
  return entry

os.chdir('/DATA/')
video_files = []
for files in ('*.m4v', '*.mp4', '*.ts','*.dvr-ms','*.avi','*.mkv'):
  video_files.extend(glob.glob(files))

fArr = []
for fileN in video_files:
  fArr.append(makeEntry(fileN, os.path.getsize(fileN)))

## Print header.
print "{header:{width}}".format (header='File Name', width=FORMAT['File Name']),
print "{header:{width}}".format (header='Size', width=FORMAT['Size'])
print

for entry in fArr:
  print "{f0:{w0}} {f1:{w1}}".format ( f0=entry[0], w0=FORMAT['File Name'], f1=entry[1], w1=FORMAT['Size'] )