Как я могу избежать добавления ошибок, используя concurrent.futures в Python? - PullRequest
0 голосов
/ 12 января 2020

Я пытаюсь создать таблицу с информацией об API. Когда я анализирую игру за игрой, она работает нормально, но когда я пытаюсь проанализировать большое количество игр, используя «concurrent.futures» для ускорения процесса, она добавляет некоторую неверную информацию в таблицу. Каждый раз, когда я запускаю сценарий, ошибки появляются в разных строках, это плохо.

Кроме того, я заметил печать проанализированных game_ids, что скрипт не смотрит их в порядке. Возможно ошибка в этой проблеме.

Как я могу решить эту проблему? Спасибо!

Это код, который я использую.

import requests as r
import pandas as pd
import concurrent.futures

pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

game_id = [100, 101, 102] #This is an example, I use a large number of games

d = {'game_id'        : [],
     'atbat_num'      : [],
     'play_index'     : [],
     'batter_id'      : [],
     'batter_name'    : [],
     'pitcher_id'     : [],
     'pitcher_name'   : [],
     'runner_id'      : [],
     'runner_name'    : [],
     'event'          : [],
     'start'          : [],
     'end'            : [],
     'movementReason' : []
        }

def get_url(gids):
    url = (f'http://examplelink.com/str(gids)}/')
    req  = r.get(url)
    json = req.json()

    for i in json['allPlays']:

        if 'runners' in i:

            for p in i['runners']:

                d['game_id'].append(gids)
                if 'atBatIndex' in i:
                    d['atbat_num'].append(i['atBatIndex'])
                else: d['atbat_num'].append(None)
                if 'playIndex' in p['details']:
                    d['play_index'].append(p['details']['playIndex'])
                else: d['play_index'].append(None)
                if 'matchup' in i:
                    if 'batter' in i['matchup']:
                        d['batter_id'].append(i['matchup']['batter']['id'])                    
                    else: d['batter_id'].append(None)
                else: d['batter_id'].append(None)
                if 'matchup' in i:
                    if 'batter' in i['matchup']:
                        d['batter_name'].append(i['matchup']['batter']['fullName'])
                    else: d['batter_name'].append(None)
                else: d['batter_name'].append(None)
                if 'matchup' in i:
                    if 'pitcher' in i['matchup']:
                        d['pitcher_id'].append(i['matchup']['pitcher']['id'])
                    else: d['pitcher_id'].append(None)
                else: d['pitcher_id'].append(None)
                if 'matchup' in i:
                    if 'pitcher' in i['matchup']:
                        d['pitcher_name'].append(i['matchup']['pitcher']['fullName'])
                    else: d['pitcher_name'].append(None)
                else: d['pitcher_name'].append(None)
                if 'details' in p:
                    if 'runner' in p['details']:
                        if 'id' in p['details']['runner']:
                            d['runner_id'].append(p['details']['runner']['id'])
                        else: d['runner_id'].append(None)
                    else: d['runner_id'].append(None)
                else: d['runner_id'].append(None)
                if 'details' in p:
                    if 'runner' in p['details']:
                        if 'fullName' in p['details']['runner']:
                            d['runner_name'].append(p['details']['runner']['fullName'])
                        else: d['runner_name'].append(None)
                    else: d['runner_name'].append(None)
                else: d['runner_name'].append(None)
                if 'details' in p:
                    d['event'].append(p['details']['event'])
                else: d['event'].append(None)
                if 'movement' in p:
                    d['start'].append(p['movement']['start'])
                else: d['start'].append(None)
                if 'movement' in p:
                    d['end'].append(p['movement']['end'])
                else: d['end'].append(None)
                if 'details' in p:
                    d['movementReason'].append(p['details']['movementReason'])
                else: d['movementReason'].append(None)

    print(f'Game {gids} analyzed')          

    with concurrent.futures.ThreadPoolExecutor() as executor:
        executor.map(get_url, game_id)

table = pd.DataFrame(d)

export_csv = table.to_csv ('runner.csv', index = None, header=True)

1 Ответ

1 голос
/ 12 января 2020

Executor.map вызвал func одновременно, поэтому нет гарантии, что упорядочение результатов соответствует итерируемому.

Я предполагаю, что данные структурированы таким образом, чтобы впоследствии его можно было представить в виде табличных данных с использованием библиотеки pandas.

Я предлагаю использовать другую структуру данных, которая не заботится о порядке, например, список. pandas.DataFrame параметр данных может быть диктат списков или список диктов

d = []
game_id = [100, 101, 102] #This is an example, I use a large number of games

def get_url(gid):
    url = f"http://examplelink.com/{gid}/"
    req = r.get(url)
    json = req.json()

    for i in json["allPlays"]:
        for p in i.get("runners", []):
            matchup = i.get("matchup", {})
            batter = matchup.get("batter", {})
            pitcher = matchup.get("pitcher", {})
            details = p.get("details", {})
            runner = details.get("runner", {})
            event = details.get("event", {})

            d.append(
                dict(
                    game_id=gid,
                    atbat_num=i.get("atBatIndex"),
                    play_index=details.get("playIndex"),
                    batter_id=batter.get("id"),
                    batter_name=batter.get("fullName"),
                    pitcher=pitcher.get("id"),
                    pitcher_name=pitcher.get("fullName"),
                    runner_id=runner.get("id"),
                    runner_name=runner.get("fullName"),
                    event=details.get("event"),
                    start=p.get("movement", {}).get("start"),
                    end=p.get("movement", {}).get("end"),
                    movementReason=details.get("movementReason"),
                )
            )

    print(f"Game {gid} analyzed")

with concurrent.futures.ThreadPoolExecutor() as executor:
        executor.map(get_url, game_id)
...