panzarino / mlbgame

A Python API to retrieve and read MLB GameDay data
http://panz.io/mlbgame/
MIT License
526 stars 112 forks source link

player_stats not handling some spring training games #8

Closed rationalpastime closed 8 years ago

rationalpastime commented 8 years ago

Occasionally MLB teams play non-MLB teams in exhibition. Two of these games took place on April 4, 2016. combine_games handles this okay, simply ignoring the non-MLB match-ups. See the April 4 scoreboard:

Nationals (4) at Braves (3) Giants (12) at Brewers (3) Mariners (2) at Rangers (3) White Sox (4) at Athletics (3) Rockies (10) at D-backs (5) Cubs (9) at Angels (0) Blue Jays (5) at Rays (3) Red Sox (0) at Indians (0) Phillies (2) at Reds (6) Twins (2) at Orioles (3) Dodgers (15) at Padres (0) Astros (0) at Yankees (0)

However, player_stats does not handle these well. Below is the error message I receive when I try to run mlbgame.player_stats(game.game_id) on one of those games, for instance the Miami Marlins vs. the Diablos Rojos:

Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mlbgame/data.py", line 47, in get_boxscore data = urlopen("http://gd2.mlb.com/components/game/mlb/year%s/month%s/day%s/gid_%s/boxscore.xml" % (year, month, day, game_id)) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 162, in urlopen return opener.open(url, data, timeout) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 471, in open response = meth(req, response) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 581, in http_response 'http', request, response, code, msg, hdrs) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 509, in error return self._call_chain(_args) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 443, in _call_chain result = func(_args) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 589, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 404: Not Found

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "", line 1, in File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mlbgame/init.py", line 238, in player_stats data = mlbgame.stats.player_stats(game_id) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mlbgame/stats.py", line 11, in player_stats data = mlbgame.data.get_box_score(game_id) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/mlbgame/data.py", line 49, in get_box_score raise ValueError("Could not find a game with that id.") ValueError: Could not find a game with that id.

panzarino commented 8 years ago

How did you get the ID for that game? It is not listed by the MLB on the scoreboard for that game. The MLB also has no stats for that game. I can't really do anything if the data is not provided by MLB.com.

rationalpastime commented 8 years ago

It was one of the game IDs your module generated it via mlbgame.day(2016, 4, 4). I know you can't get the data if the data aren't provided. I mention this in case you wanted to build in some error checking before your module tries to pull a URL that doesn't exist. When your module tries to pull one of those pages and gets an error, it stops whatever program is running it dead in its tracks.

panzarino commented 8 years ago

I will add some sort of try/except for that.

rationalpastime commented 8 years ago

Note: also seems to happen with some rainouts, for instance last night's Royals/Sox game. The following code generates the same error.

game = mlbgame.day(2016, 5, 16, home="Royals")[0] stats = mlbgame.player_stats(game.game_id)

Super useful module otherwise.

panzarino commented 8 years ago

I think you could check the game_type to determine if the game was rained out or not.

Also, I do not know if I want to make the requests silently fail. Without showing the error message, it could break parts of programs when they try to use what is returned from the function.

rationalpastime commented 8 years ago

Alright I'll give that a shot. I get not wanting errors to silently fall, though I thought it might be possible to catch them, return a message and then continue on with a routine. Maybe not. I'm a novice coder.

panzarino commented 8 years ago

I think it would be more beneficial for the user to try/catch so they at least know that something didn't work right.

Also, thanks for using mlbgame.

rationalpastime commented 8 years ago

In case anyone runs into the same trouble I did, I thought I'd post the workaround I'm using. I use the mlbgame.game.scoreboard module to generate a list of game IDs with finals. For instance, for the games of May 16, 2016, I use:

statuslist = []
finalgames = []

for game in list(mlbgame.game.scoreboard(2016, 5, 16).keys()):
    game_status = (mlbgame.game.scoreboard(2016, 5, 16)[game]['game_status'])
        game_id_status = [game, game_status]
        statuslist.append(game_id_status)

for item in statuslist:
        if item[1] == 'FINAL':
            finalgames.append(item)

This creates a list of MLB Game IDs named finalgames that only includes IDs from games with finals. That list doesn't always play nice with other modules, but when it doesn't it's easy to use scoreboard to get the data I need with my custom list.