3
\$\begingroup\$

The code uses the XML-based OC Transpo data feed to create a list of the bus name, where it's headed, and the times. Keep in mind that I am a beginner at python so any advice at all is appreciated.

import subprocess, pprint
from bs4 import BeautifulSoup


def format_set(result_set):
    new_set = []
    for el in result_set:
        new_set.append(str(el.get_text()))
    return new_set



def get_stop_number():
    print('Please enter your desired stop number (or \'quit\'):')
    stop_numb = raw_input('> ')
    try:
        return int(stop_numb)
    except:
        print('Exiting...')
        return 'quit'


def get_stop_info(stopNo):
    try:
        output = subprocess.check_output(('curl -d "appID=ba91e757&apiKey=…'
            '&stopNo={}&format=xml" https://api.octranspo1.com/v1.2/GetNextTripsForStopAllRoutes').format(stopNo), shell=True)
        soup = BeautifulSoup(output, 'xml')
    except:
        print('An error occured!')
        return None
    summary = []
    for el in soup.find_all('Route'):
        routeNo = int(el.find('RouteNo').get_text()) 
        routeHeading = str(el.find('RouteHeading').get_text())
        times = format_set(el.find_all('TripStartTime'))
        x = [routeNo, routeHeading, times]
        summary.append(x)
    return summary


def is_empty(any_structure):
    if any_structure:
        return False
    else:
        return True


if __name__ == '__main__':
    while True:
        stop_number = get_stop_number()
        if stop_number == 'quit':
            break
        summary = get_stop_info(stop_number)
        pprint.pprint(summary)

Sample output:

Please enter your desired stop number (or 'quit'):
> 3058
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7756  100  7679  100    77   4654     46  0:00:01  0:00:01 --:--:--  4656
[[92, 'St-Laurent', ['11:30', '12:00', '12:30']],
 [92, 'Stittsville', []],
 [96, 'St-Laurent', ['10:51', '11:21', '11:51']],
 [96, 'Terry Fox', ['10:09', '10:39', '11:09']],
 [118, 'Hurdman', ['11:20', '11:40', '12:00']],
 [118, 'Kanata', []],
 [162, 'Stittsville', ['11:55', '12:55', '13:55']],
 [162, 'Terry Fox', []],
 [168, 'Bridlewood', ['11:35', '12:05', '12:35']],
 [168, 'Terry Fox', []]]
Please enter your desired stop number (or 'quit'):
> quit
Exiting...
\$\endgroup\$
1
\$\begingroup\$
  • Imports are okay, you'll find different advice about whether to import individual functions, so I'll say no more.
  • You have __name__ ..., good, perhaps just move the contained block into another function main so that you can easily invoke it from the REPL.
  • is_empty is obsolete, at some point you'll just remember that empty lists are False in a boolean context. Oh and it's unused as well.
  • You have a lot of quoting options in Python, so if you need a literal ' in a string, consider delimiting it with " instead of using the backslash syntax.
  • You're in Python, so perhaps also use the built-in HTTP library instead of shelling out to curl.
  • format_set is more easily written with a list comprehension, e.g.:

    def format_set(result_set):
        return [str(el.get_text()) for el in result_set]
    
  • Technically get_stop_number accepts more than just numbers and 'quit', so just be aware of that. I'd inline the stop_numb variable as well (n.b. why care about saving two characters there?)

    ...
    return int(raw_input('> '))
    
  • get_stop_info has a camel-case variable s, that's inconsistent with the rest and in general not advised in Python. Again, the loop can be a list comprehension, but maybe that'll be a bit too dense, your choice. In general returning an unstructured list like is will also prevent the reader from getting a clearer understanding of the code, but if it's just for display purposes that's fine.

    ...
    return [[int(el.find('RouteNo').get_text()),
             str(el.find('RouteHeading').get_text()),
             format_set(el.find_all('TripStartTime'))]
            for el in soup.find_all('Route')]
    
  • I'm a fan of aggressively factoring out common code, you can try and see how you like e.g. creating smaller functions for int(el.find(name).get_text()) and so on; that can be helpful later on as your program(s) grow(s).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.