As Ludisposed said in his answer, yours is a very top-down approach. The minimum you should do is put this into a function, so you can re-use it. Here I rewrote your code quite significantly. Instead of returning -1
, use the fact that a Python function returns None
by default, which is a better safe value than -1
.
I also completely re-wrote your getData
function. Honestly, I have no idea what half of that was trying to do. All you need to do is iterate over the data
. No need for a try: sys.exit(...) except:
(which will always call what is inside the except
, so why bother?). Also no need for a while True
loop, if you are only ever going to go through it once.
I added the simple argparse
parser and added the calling code under a if __name__ == "__main__":
guard.
import argparse
import time
import sys
import requests
URL = "http://svc.metrotransit.org/NexTrip/{}?format=json"
def get(path, key, value, arg):
resp = requests.get(URL.format(path))
data = resp.json()
for item in data:
if arg in item[key].lower():
return item[value]
def next_bus(route, stop, direction):
route_id = get("Routes", "Description", "Route", route)
if route_id is None:
raise RuntimeError("{} is not a valid route.".format(route))
direction_id = get("Directions/{}".format(route_id),
"Text", "Value", direction)
if direction_id is None:
raise RuntimeError("{} does not go {}.".format(route, direction))
stop_id = get("Stops/{}/{}".format(route_id, direction_id), "Text", "Value", stop)
if stop_id is None:
raise RuntimeError("{} is not along {} going {}.".format(
stop, route, direction))
time_ = get("{}/{}/{}".format(route_id, direction_id, stop_id),
"RouteDirection", "DepartureTime", direction)
if time_ is None:
raise RuntimeError("Could not get next connection.")
return int((float(time_[6:16]) - time.time()) // 60)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("route")
parser.add_argument("stop")
parser.add_argument("direction")
args = parser.parse_args()
time = next_bus(**vars(args))
if time > 1:
print "{} minutes".format(time)
else:
print "1 minute or less"
Alternatively, you could make this a class
and use property
for the different ids. This would allow you to have an object like trip_home = Connection(route, direction, stop)
, on which you could call trip_home.next
to get the latest connection.
The different ids are looked up upon the initialization of the class. Calls to trip_home.next
will only need to get the next connection. This assumes that the ids do not change during the runtime of the program, of course.
import argparse
import time
import sys
import requests
class Connection:
url = "http://svc.metrotransit.org/NexTrip/{}?format=json"
def __init__(self, route, stop, direction):
self.route = route
self.stop = stop
self.direction = direction
self.route_id = self.get_route_id()
self.direction_id = self.get_direction_id()
self.stop_id = self.get_stop_id()
def __str__(self):
return "{self.route} from {self.stop} due {self.direction}. Next connection in {self.next} minutes.".format(self=self)
def get(self, path, key, value, arg):
resp = requests.get(self.url.format(path))
data = resp.json()
for item in data:
if arg in item[key].lower():
return item[value]
def get_route_id(self):
id_ = self.get("Routes", "Description", "Route", self.route)
if id_ is None:
raise RuntimeError(
"{self.route} is not a valid route.".format(self=self))
return id_
def get_direction_id(self):
id_ = self.get(
"Directions/{self.route_id}".format(self=self), "Text", "Value", self.direction)
if id_ is None:
raise RuntimeError("{self.route} does not go {self.direction}.".format(
self=self))
return id_
def get_stop_id(self):
id_ = self.get(
"Stops/{self.route_id}/{self.direction_id}".format(self=self), "Text", "Value", self.stop)
if id_ is None:
raise RuntimeError(
"{self.stop} is not along {self.route} going {self.direction}.".format(self=self))
return id_
@property
def next(self):
time_ = self.get("{self.route_id}/{self.direction_id}/{self.stop_id}".format(self=self),
"RouteDirection", "DepartureTime", self.direction)
if time_ is None:
raise RuntimeError(
"Could not find next connection on route {self.route} from {self.stop} due {self.direction}".format(self=self))
return int((float(time_[6:16]) - time.time()) // 60)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("route")
parser.add_argument("stop")
parser.add_argument("direction")
args = parser.parse_args()
trip_home = Connection(args.route, args.stop, args.direction)
print trip_home