Formatting Text in a Table in Python

Question:

I’m having issues creating a table that is dynamic to adjust to various results.

I’ve written a screen scraper to pull stocks from http://finance.yahoo.com and print the company name, it’s symbol, and it’s current stock price.

However the output looks like this:

 Microsoft Corporation MSFT 29.76

 Apple Inc. AAPL 396.77

 SPDR S&P 500 SPY 155.25

 Google Inc. GOOG 787.76

I want it to look like

Microsoft Corporation        MSFT      29.76

Apple Inc.                   AAPL      396.77

SPDR S&P 500                 SPY       155.25

Google Inc.                  GOOG      787.76

I just started wokring with Python yesterday and am using 3.3.1

My current code is as follows:

import re
import urllib.request
import cgi
from bs4 import BeautifulSoup

price = [0,0,0,0]
namesList = ["string1", "string2", "string3", "string4"]
stocksList = ["msft","aapl","spy","goog"]

def HTML():
    i = 0
    while i < len(stocksList):
        htmlPull = urllib.request.urlopen("http://finance.yahoo.com/q?s="+stocksList[i]+"&ql=1")
        htmlPull = htmlPull.read().decode('utf-8')
        regex = '<span id="yfs_l84_'+stocksList[i]+'">(.+?)</span>'
        pattern = re.compile(regex)
        price[i] = re.findall(pattern,htmlPull)
        htmlParse = BeautifulSoup(htmlPull)
        title = htmlParse.title.contents
        namesList[i] = title        
        i+=1

formatPrice(price)
formatStock(namesList)
formatOutput(namesList, stocksList, price)

def formatPrice(price):
    k=0
    while k < len(price):
        cleaner = str(price[k])
        cleaner = cleaner.replace("[","")
        cleaner = cleaner.replace("]","")
        cleaner = cleaner.replace("'","")
        price[k] = float(cleaner)
        k+=1

def formatStock(namesList):
    k = 0
    while k <len(namesList):
        capital = stocksList[k]
        capital = capital.upper()
        cleaner = str(namesList[k])
        cleaner = cleaner.replace("Summary for ", "")
        cleaner = cleaner.replace(":"," ")
        cleaner = cleaner.replace("- Yahoo! Finance'","")
        cleaner = cleaner.replace("['","")
        cleaner = cleaner.replace("]","")
        cleaner = cleaner.replace(";","")
        cleaner = cleaner.replace(capital, "")
        namesList[k] = cleaner;
        k+=1

    def formatOutput(namesList, stocksList, price):
        i = 0
        while i < len(price):
        capital = stocksList[i]
        capital = capital.upper()
        print(namesList[i],capital, price[i])
        print("")
        i+=1
HTML()

Have tried print ({0},{1},{2}.format (namesList, capital, price[i])), various types of {:<16} variations, etc. It seems to only affect one line and I’m trying to get it to think in terms of columns, or a table, or maybe a certain amount of space that the text and whitespace should fill. I’m not sure what exactly the solution is here, so I’m asking you all 🙂

As you can tell by my code, I’m pretty new to programming, so if there is a better way to do anything in this code, I’d be happy to listen to correction, advice, and suggestions.

Asked By: Ben Sailors

||

Answers:

You want to set the width based on the longest item in the column.

In Python, you use max to find the largest of some group of things. So, outside the loop, you can do:

names_width = max(len(name) for name in namesList)
stock_width = max(len(stock) for stock in stockList)

Then, format each line like you said you tried:

print({0:{3}}  {1:{4}}  {2}.format(namesList[i],
                                   capital,
                                   price[i],
                                   names_width,
                                   stock_width))
Answered By: agf
print('{:<10}{:^20}{:>30}'.format("left","center","right"))

output:
   >>>        left         center          right  

{:> = space in pixles with arbitrary int}
Answered By: runtimejpp