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­

    >>> from elec­tions im­port AP
    >>> cli­ent = AP(un­ame, pwd)
    >>> iowa = cli­ent.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?


    from elec­tions im­port AP
        im­port json
    ex­cept Im­por­t­Er­ror:
        im­port sim­plejson as json
    cli­ent = AP(un­ame, pwd)
    iowa = cli­ent.get_state('IA') 
    # Now the iowa vari­able holds all of the AP res­ult data
    caucus = iowa.fil­ter­_races(of­fice_­name='Pres­id­ent', party='GOP')[0] 
    # caucus is a Race ob­ject con­tain­ing the res­ults of the GOP caucuses
    # Set up the main data dict and set the per­cent of pre­cincts re­port­ing
    data = {
        'pre­cinct­s_re­port­ing_­per­cent': caucus.state.pre­cinct­s_re­port­ing_­per­cent,
        'can­did­ates': []
    # Loop through the statewide can­did­ate res­ults, and ap­pend them
    # in a format we like in­to the data dict's can­did­ate list.
    for res­ult in caucus.state.res­ults:
            'name': res­ult.can­did­ate.last_­name,
            'vote_total': res­ult.vote_total,
            'vote_­per­cent': res­ult.vote_total_­per­cent,
            'del­eg­ate_total': res­ult.can­did­ate.del­eg­ates,
            'is_win­ner': res­ult.can­did­ate.is_win­ner,
    # Then dump the data dict out as JSON
    print json.dumps(data, in­dent=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.


    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.


    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.