Introducing python-elections

    Process AP elections data more easily with this new open-source library.

    Los Angeles Times photographic archive, UCLA Library
    TABULATING: Corridor filled with men and women counting ballots for a California primary election in Los Angeles. (1954)

    News or­gan­iz­a­tions have a long his­tory of re­port­ing elec­tion res­ults, but re­port­ing res­ults live and for the Web is still a re­l­at­ively re­cent de­vel­op­ment.

    Thank­fully, the As­so­ci­ated Press has a di­git­al ser­vice called the AP Elec­tions On­line FTP. It up­dates a series of files every few minutes, which news or­gan­iz­a­tions hun­grily down­load and pro­cess in a race to get the res­ults out first.

    At the Data Desk, we’ve writ­ten more than our fair share of code to parse these res­ults. And we know we’re not alone. In fact, we bet that if you saved up all of the hours spent pro­cessing the same AP elec­tion res­ults across all news or­gan­iz­a­tions, there would be enough col­lect­ive spare cycles to save journ­al­ism.

    So, with that in mind, take a gander at our at­tempt to al­le­vi­ate your elec­tion-re­lated is­sues.

    Get­ting star­ted

    First, in­stall the lib­rary from PyPI, prefer­ably in a vir­tualenv, but there’s no ac­count­ing for taste.

    $ pip install python-elections
    

    Then con­nect to the AP data ser­vice with your FTP lo­gin, and grab a state’s data us­ing its postal code. To get a lo­gin, you must pay AP for ac­cess to the data. More in­form­a­tion can be found on the AP’s web­site or by con­tact­ing An­thony Mar­quez at am­ar­quez@ap.org.

    >>> from elections import AP
    >>> client = AP(uname, pwd)
    >>> iowa = client.get_state('IA')
    >>> iowa
    <State: IA>
    

    From there, you should have ac­cess to everything in the ini­tial­iz­a­tion and res­ults files for that state. For ex­amples of the fol­low­ing meth­ods, please see our README:

    • Get or fil­ter the list of races in the state.
    • Get the list of can­did­ates for a race.
    • Get res­ults for the whole state.
    • Get all counties in the state, with res­ults for each County ob­ject.
    • Get the num­ber of del­eg­ates as­signed to a can­did­ate.

    A real-world ex­ample

    Let’s say the GOP is hold­ing its caucuses in Iowa, and your news or­gan­iz­a­tion bought ac­cess to the AP’s FTP ser­vice. Your boss wants you to write a simple wid­get that will sit on the homepage and out­put live res­ults. All you need are the can­did­ate names, their vote totals and per­cent­ages, the num­ber of pre­cincts re­port­ing, the num­ber of del­eg­ates won and wheth­er the AP has called a win­ner yet. How do you feed it?

    Cake.

    from elections import AP
    try:
        import json
    except ImportError:
        import simplejson as json
    
    client = AP(uname, pwd)
    iowa = client.get_state('IA') 
    # Now the iowa variable holds all of the AP result data
    caucus = iowa.filter_races(office_name='President', party='GOP')[0] 
    # caucus is a Race object containing the results of the GOP caucuses
    
    # Set up the main data dict and set the percent of precincts reporting
    data = {
        'precincts_reporting_percent': caucus.state.precincts_reporting_percent,
        'candidates': []
    }
    
    # Loop through the statewide candidate results, and append them
    # in a format we like into the data dict's candidate list.
    for result in caucus.state.results:
        data['candidates'].append({
            'name': result.candidate.last_name,
            'vote_total': result.vote_total,
            'vote_percent': result.vote_total_percent,
            'delegate_total': result.candidate.delegates,
            'is_winner': result.candidate.is_winner,
        })
    
    # Then dump the data dict out as JSON
    print json.dumps(data, indent=4)
    

    There you have it: a simple JSON dump in about 20 lines of code. From here, you can set this script to up­load the JSON file every few minutes to Amazon S3 or a sim­il­ar file-serving ser­vice. Then point your front-end wid­get to pull from there.

    If it’s that simple to get a JSON wid­get set up, ima­gine what else you could do.

    Is­sues

    The fea­ture set is pretty straight­for­ward and simple right now, but there are a few out­stand­ing is­sues we could use some help with:

    So please, feel free to dive in­to our code and send a pull re­quest if you have patches. Check it out on Git­Hub.

    Readers: What’s your take? Share it here.

    Advertisement

    Latest work

      About The Data Desk

      This page was created by the Data Desk, a team of reporters and Web developers in downtown L.A.