Certainly, we’d need to put some logic into our script in order to be able to parse arguments. Let’s think of all the arguments that we could possibly want to pass to our API Python script are:

API key for Giantbomb

path to CPI file

URL to get CPI data (default will be our global CPI_DATA_URL we defined earlier)

Path to CSV file which will contain the data output

Path to PNG file which will contain the graphed data output

Output level for logging (whether just informational, or debugging, etc)

Maximum number of platforms we want to look at, if any

Python’s standard library has a great module, argparse that we’ll use. We’ll create separate parsing function as a helper to our main function that we’ll write out after this.

First, import argparse,

1

importargparse

then let’s define our parsing function, and use argparse’s ArgumentParser to initialize a parser class:

1
2

defparse_args():parser=argparse.ArgumentParser()

The ArgumentParser class implicitly gives us an argument for free, the -h and --help flags for showing the usage of the script, python platform_pricing.py [options] [args], as well as a list of available commands and their help strings we assign.

Now we should add all the arguments that could possibly be passed through from the command line with the add_argument method that ArgumentParser class gives us:

We also tell add_argument that this is a required field by passing the required=True parameter. The ArgumentParser class will take care of erroring out for us if that argument isn’t given in the command line.

Lastly, we pass in a string for our help parameter – this text will show whenever a user passes the -h or --help flag.

The rest of our arguments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

defparse_args():parser=argparse.ArgumentParser()parser.add_argument('--giantbomb-api-key',required=True,help='API key provided by Giantbomb.com')parser.add_argument('--cpi-file',default=os.path.join(os.path.dirname(__file__),'CPIAUCSL.txt'),help='Path to file containing the CPI data (also acts'' as target file if the data has to be downloaded''first).')parser.add_argument('--cpi-data-url',default=CPI_DATA_URL,help='URL which should be used as CPI data source')parser.add_argument('--debug',default=False,action='store_true',help='Increases the output level.')parser.add_argument('--csv-file',help='Path to CSV file which should contain the data''output')parser.add_argument('--plot-file',help='Path to the PNG file which should contain the''data output')parser.add_argument('--limit',type=int,help='Number of recent platforms to be considered')opts=parser.parse_args()ifnot(opts.plot_fileoropts.csv_file):parser.error("You have to specify either a --csv-file or --plot-file!")returnopts

Note that when running this script, you don’t have to have the output files, CSV or PNG, already created – just tell the script where you want it saved and what you want it saved as by giving it the full directory path and desired filename.

The Python docs have a great tutorial on how to use the argparse module if you’d like additional work on this module.

Main function

The CPIData and GiantbombAPI classes have been defined with their methods, as well as functions generate_plot, generate_csv, and is_valid_dataset. Let’s now make one main() function that runs whenever we call our platform_pricing.py file (with arguments) that instantiates (uses) everything.

We’ll first want to take care of the arguments passed through the command line by calling our parse_args function.

1
2
3
4
5
6
7
8

defmain():"""This function handles the actual logic of this script."""opts=parse_args()ifopts.debug:logging.basicConfig(level=logging.DEBUG)else:logging.basicConfig(level=logging.INFO)

Here, we also handle the level of logging – if the user uses the --debug flag (perhaps s/he wants extra level of detail of what is going on, or is troubleshooting), then we assign our logging variable a level of DEBUG, else, the default will be INFO.

Since we did not specify any file to save our logs to, it will just write our logging statement that we defined in GiantbombAPI.get_platforms() to the terminal when we run our Python program.

Next, we’ll instantiate both the CPIData class and the GiantbombAPI class and use some of the arguments that we parsed to pass the API key, the CPI URL (if we don’t want to use the default defined in our global variable, CPI_DATA_URL, and CPI file (if we gave it a file).

We also print to the console – using the print function imported from future (Python 3), rather than the print keyword in Python 2 – that gives a disclaimer to the user what the script will be doing.

We need to iterate over each platform (up to the limit if one is set as an argument from the command line) to fetch the adjusted price (the de/inflated price of the platform) based on the data we grabbed from the FRED. We build/append each piece of data to the platforms list.

We then take our platforms list and pass it to either generate_plot or generate_csv, depending on what arguments were passed from the command line.

# <-- snip -->platforms=[]counter=0# Now that we have everything in place, fetch the platforms and calculate# their current price in relation to the CPI value.forplatformingb_api.get_platforms(sort='release_date:desc',field_list=['release_date','original_price','name','abbreviation']):# Some platforms don't have a release date or price yet. These we have# to skip.ifnotis_valid_dataset(platform):continueyear=int(platform['release_date'].split('-')[0])price=platform['original_price']adjusted_price=cpi_data.get_adjusted_price(price,year)platform['year']=yearplatform['original_price']=priceplatform['adjusted_price']=adjusted_priceplatforms.append(platform)# We limit the resultset on this end since we can only here check# if the dataset actually contains all the data we need and therefor# can't filter on the API level.ifopts.limitisnotNoneandcounter+1>=opts.limit:breakcounter+=1ifopts.plot_file:generate_plot(platforms,opts.plot_file)ifopts.csv_file:generate_csv(platforms,opts.csv_file)

That’s all for our main() function – just the final boilerplate code at the tail end:

1
2

if__name__=='__main__':main()

Try it yourself

In your terminal, with your APIProj virtual environment activated, and from within your API project directory, try your new script with different arguments (be sure to use your own directory paths instead of ~/Projects/new-coder/apis/* unless you have that exact directory setup):