Загрузка данных из API в БД Postgres просто прекращается без сообщений об ошибках - PullRequest
0 голосов
/ 06 февраля 2019

Странное поведение началось, когда я перешел на PostgreSQL, раньше использовал sqllite3, и с этим проблем не было.Только что воссоздал базу данных sqllite3 из текущего состояния моего кода.Просто отключил поля JsonFields, которые я использовал для загрузки одного из сценариев на базу Postrgre.Еще работает.

Загрузка в Postgre просто останавливается в случайной точке случайного отчета, без сообщений, командная строка не реагирует на команду Ctrl + K.Я проверил сервер Postgre, он все время работает.Когда я останавливаю службу после этого «замораживания» загрузки в БД из командной строки, иногда выдает ошибку, иногда нет и просто ничего не происходит.Мне нужно снова открыть командную строку.

Я попытался записать видео на экране, чтобы проиллюстрировать это поведение.Но, к сожалению, мое программное обеспечение для записи экрана не работает должным образом.Вы можете увидеть код ниже, я не уверен, что есть проблема в коде.Может быть, что-то еще нужно сделать с настройкой PostgreSQL?В первый день использования Postgre я смог загрузить скрипт полностью.

Есть скриншот с примером того, как он выглядит в командной строке - https://yadi.sk/i/i_LwZHCf_kYpyg

Есть один из скриптов

import os
import urllib.request as urllib

from django.core.management.base import BaseCommand, CommandError
from django.core.files import File
from django.conf import settings

import requests
from tqdm import tqdm

from players.models import Skater
from players.models import Goalie


URL_PLAYERS = 'http://www.nhl.com/stats/rest/{}'
URL_PLAYERS_PICS = 'https://nhl.bamcontent.com/images/headshots/current/168x168/{}.jpg'
PL_TYPE1 = "goalies"
PL_TYPE2 = "skaters"
REP_TYPE1 = 'goaliesummary'
REP_TYPE2 = 'skatersummary'
REP_TYPE3 = 'realtime'
REP_TYPE4 = 'timeonice'
POSITIONS = ['G', 'D', 'C', 'LW', 'RW', 'L', 'R']
WING = 'W'

COUNTRIES = {
    'RUS': 'Russia',
    'CAN': 'Canada',
    'USA': 'USA',
    'CZE': 'Czech Republic',
    'CSK': 'Czech Republic',
    'CHE': 'Switzerland',
    'SWE': 'Sweden',
    'FIN': 'Finland',
    'DEU': 'Germany',
    'DNK': 'Denmark',
    'AUT': 'Austria',
    'FRA': 'France',
    'ITA': 'Italia',
    'NOR': 'Norway',
    'LVA': 'Latvia',
    'SVN': 'Slovenia',
    'SVK': 'Slovakia',
    'NLD': 'Netherlands',
    'AUS': 'Australia',
    'GBR': 'Great Britain',
    'KAZ': 'Kazachstan',
    'BGR': 'Bulgaria',
    'EST': 'Estonia',
    None: '—',
}

HEIGHT_CONVERT = {
    65: "5' 5\"",
    66: "5' 6\"",
    67: "5' 7\"",
    68: "5' 8\"",
    69: "5' 9\"",
    70: "5' 10\"",
    71: "5' 11\"",
    72: "6' 0\"",
    73: "6' 1\"",
    74: "6' 2\"",
    75: "6' 3\"",
    76: "6' 4\"",
    77: "6' 5\"",
    78: "6' 6\"",
    79: "6' 7\"",
    80: "6' 8\"",
    81: "6' 9\"",
    82: "6' 10\"",
}

POSITIONS = ['G', 'D', 'C', 'LW', 'RW', 'L', 'R']



class Command(BaseCommand):

    def import_player(self, player, index):
        # print(player["playerId"])
        # print(player["playerName"])
        id_ = player["playerId"]
        if player['playerDraftOverallPickNo'] is None:
            player['playerDraftOverallPickNo'] = '—'
            player['playerDraftYear'] = '—'

        if player['playerBirthStateProvince'] is None:
            player['playerBirthStateProvince'] = ''

        if player['playerPositionCode'] in POSITIONS[5:]:
            player['playerPositionCode'] += WING

        defaults = {
            'name': player["playerName"],
            'team_abbr': player['playerTeamsPlayedFor'][-3:],
            'position_abbr': player["playerPositionCode"],
            'height': HEIGHT_CONVERT[player["playerHeight"]],
            'weight': player["playerWeight"],
            'birth_date': player["playerBirthDate"],
            'birth_city': player["playerBirthCity"],
            'birth_state': player["playerBirthStateProvince"],
            'birth_country': COUNTRIES[player["playerBirthCountry"]],
            'nation': COUNTRIES[player["playerNationality"]],
            'draft_year': player["playerDraftYear"],
            'draft_number': player["playerDraftOverallPickNo"],
            'games': player["gamesPlayed"],
        }

        if player["playerPositionCode"] == POSITIONS[0]:
            defaults_g = {
                'wins': player["wins"],
                'losses': player["losses"],
                'ot_losses': player["otLosses"],
                'goals_against_av': player["goalsAgainstAverage"],
                'saves_perc': player["savePctg"],
                'saves': player["saves"],
                'shotouts': player["shutouts"],
            }
            defaults = {**defaults, **defaults_g}
            player_obj, created = Goalie.objects.update_or_create(nhl_id=id_, defaults=defaults)

            if self.pic_missing(player_obj):
                self.upload_pic(player_obj)

        else:
            if index == 1:
                defaults_s = {
                    'goals': player["goals"],
                    'goals_avg': player["goals"] / player["gamesPlayed"],
                    'assists': player["assists"],
                    'assists_avg': player["assists"] / player["gamesPlayed"],
                    'points': player["points"],
                    'points_avg': player["points"] / player["gamesPlayed"],
                    'plus_minus': player["plusMinus"],
                    'plus_minus_avg': player["plusMinus"] / player["gamesPlayed"],
                    'penalty_min': player["penaltyMinutes"],
                    'penalty_min_avg': player["penaltyMinutes"] / player["gamesPlayed"],
                    'shots': player["shots"],
                    'shots_avg': player["shots"] / player["gamesPlayed"],
                    'pp_points': player["ppPoints"],
                    'pp_points_avg': player["ppPoints"] / player["gamesPlayed"],
                    'sh_points': player["shPoints"],
                    'sh_points_avg': player["shPoints"] / player["gamesPlayed"],
                }
                defaults = {**defaults, **defaults_s}
                player_obj, created = Skater.objects.update_or_create(nhl_id=id_, defaults=defaults)

                if self.pic_missing(player_obj):
                    self.upload_pic(player_obj)

            elif index == 2:
                defaults = {
                    'hits': player["hits"],
                    'hits_avg': player["hits"] / player["gamesPlayed"],
                    'blocks': player["blockedShots"],
                    'blocks_avg': player["blockedShots"] / player["gamesPlayed"],
                    'faceoff_wins': player["faceoffsWon"],
                    'faceoff_wins_avg': player["faceoffsWon"] / player["gamesPlayed"],
                }
                player_obj, created = Skater.objects.update_or_create(nhl_id=id_, defaults=defaults)

            elif index == 3:
                defaults = {
                    'time_on_ice': time_from_sec(player["timeOnIcePerGame"]),
                    'time_on_ice_pp': time_from_sec(player["ppTimeOnIcePerGame"]),
                    'time_on_ice_sh': time_from_sec(player["shTimeOnIcePerGame"]),
                }
                player_obj, created = Skater.objects.update_or_create(nhl_id=id_, defaults=defaults)


    def pic_missing(self, player_obj):
        file_name = f'{player_obj.slug}.jpg'
        file_path = os.path.join(settings.MEDIA_ROOT, 'players_pics', file_name)
        # player_obj.image.path != file_path can be unnecessary in production
        return not player_obj.image or player_obj.image.path != file_path or not os.path.isfile(file_path)


    def upload_pic(self, player_obj):
        content = urllib.urlretrieve(URL_PLAYERS_PICS.format(player_obj.nhl_id))
        pic = File(open(content[0], 'rb'))
        name_pattern = f'{player_obj.slug}.jpg'
        player_obj.image.save(name=name_pattern, content=pic)


    def handle(self, *args, **options):
        lst = [[REP_TYPE1, PL_TYPE1], [REP_TYPE2, PL_TYPE2], [REP_TYPE3, PL_TYPE2], [REP_TYPE4, PL_TYPE2]]
        for index, item in enumerate(lst):
            print(f'\n Uploading from {item[0]} report')
            data = players_resp(item[0], item[1]).json()["data"]

            for player in tqdm(data):
                self.import_player(player, index)


def time_from_sec(time):
    min_, sec = divmod(time, 60)
    min_ = int(min_)
    sec = str(int(sec)).zfill(2)
    return f'{min_}:{sec}'.rjust(5, '0')


def players_resp(rep_type, pl_type):
    params = {
        'isAggregate': 'false',
        'reportType': 'season',
        'isGame': 'false',
        'reportName': rep_type,
        'cayenneExp': 'gameTypeId=2 and seasonId=20182019',
    }

    return requests.get(URL_PLAYERS.format(pl_type), params=params)

models.py

from django.db import models
from django.contrib.auth.models import User
from django.contrib.postgres.fields import JSONField
from django.utils.text import slugify
from players.storage import OverwriteStorage


class Player(models.Model):
    name = models.CharField(max_length=128, default='nme')
    nhl_id = models.IntegerField(unique=True, default=25)
    slug = models.SlugField()
    image = models.ImageField(upload_to='players_pics', storage=OverwriteStorage(), max_length=None)
    team_abbr = models.CharField(max_length=128, default='')
    team_name = models.CharField(max_length=128, default='')
    position_abbr = models.CharField(max_length=128, default='')
    position_name = models.CharField(max_length=128, default='')
    height = models.CharField(max_length=128, default='')
    weight = models.IntegerField(default=25)
    birth_date = models.CharField(max_length=128, default='')
    birth_city = models.CharField(max_length=128, default='')
    birth_state = models.CharField(max_length=128, default='')
    birth_country = models.CharField(max_length=128, default='')
    nation = models.CharField(max_length=128, default='')
    draft_year = models.CharField(max_length=128, default='')
    draft_number = models.CharField(max_length=128, default='')
    pl_number = models.IntegerField(null=True, default=25)
    age = models.IntegerField(null=True, default=25)
    roster_status = models.CharField(max_length=128, default='')
    captain = models.BooleanField(default=False)
    alt_captain = models.BooleanField(default=False)
    sbs_stats = JSONField(default=dict)
    career_stats = JSONField(default=dict)
    gamelog_stats = JSONField(default=dict)
    games = models.IntegerField(default=25)

    def __str__(self):
        return f'{self.name}'

    def save(self, *args, **kwargs):
        is_new = self.pk is None
        if is_new:
            self.slug = slugify(self.name)
        super(Player, self).save(*args, **kwargs)

    class Meta:
        abstract = True


class Skater(Player):
    favorite = models.ManyToManyField(User, related_name='favorite_s', blank=True)
    goals = models.IntegerField(default=10)
    goals_avg = models.FloatField(default=10)
    assists = models.IntegerField()
    assists_avg = models.FloatField(default=10)
    points = models.IntegerField()
    points_avg = models.FloatField(default=10)
    plus_minus = models.IntegerField()
    plus_minus_avg = models.FloatField(default=10)
    penalty_min = models.IntegerField()
    penalty_min_avg = models.FloatField(default=10)
    shots = models.IntegerField()
    shots_avg = models.FloatField(default=10)
    hits = models.IntegerField(null=True)
    hits_avg = models.FloatField(default=10, null=True)
    blocks = models.IntegerField(null=True)
    blocks_avg = models.FloatField(default=10, null=True)
    faceoff_wins = models.IntegerField(null=True)
    faceoff_wins_avg = models.FloatField(default=10, null=True)
    pp_points = models.IntegerField()
    pp_points_avg = models.FloatField(default=10)
    sh_points = models.IntegerField()
    sh_points_avg = models.FloatField(default=10)
    time_on_ice = models.CharField(max_length=128, default='')
    time_on_ice_pp = models.CharField(max_length=128, default='')
    time_on_ice_sh = models.CharField(max_length=128, default='')


class Goalie(Player):
    favorite = models.ManyToManyField(User, related_name='favorite_g', blank=True)
    wins = models.IntegerField(default=10)
    losses = models.IntegerField()
    ot_losses = models.IntegerField()
    goals_against_av = models.FloatField()
    saves_perc = models.FloatField()
    saves = models.IntegerField()
    shotouts = models.IntegerField()


class Team(models.Model):
    name = models.CharField(max_length=128, default='')
    nhl_id = models.IntegerField(unique=True, default=25)
    abbr = models.CharField(max_length=128, default='')
    slug = models.SlugField()
    image = models.ImageField(upload_to='teams_logos', storage=OverwriteStorage(), max_length=None)
    arena_name = models.CharField(max_length=128, default='')
    arena_location = models.CharField(max_length=128, default='')
    division = models.CharField(max_length=128, default='')
    conference = models.CharField(max_length=128, default='')
    off_site = models.URLField(max_length=128, default='')
    nhl_debut = models.CharField(max_length=128, default='')

    def __str__(self):
        return f'{self.name}'

    def save(self, *args, **kwargs):
        is_new = self.pk is None
        if is_new:
            self.slug = slugify(self.name)
        super(Team, self).save(*args, **kwargs)

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'nhl_web_app_2',
        'USER': 'postgres',
        'PASSWORD': '***',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

views.py

from itertools import chain

import requests
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404

from . import services
from .models import Skater
from .models import Goalie
from .models import Team


def home(request):
    return render(request, 'players/home.html', {'title': 'Home'})


def about(request):
    return render(request, 'players/about.html', {'title': 'About'})


def players(request):
    user = request.user
    context = {
        'goalies': Goalie.objects.all(),
        'skaters': Skater.objects.all(),
        'favorites_g': user.favorite_g.all(),
        'favorites_s': user.favorite_s.all(),
    }
    return render(request, 'players/players.html', context)


def skaters_averages(request):
    user = request.user
    context = {
        'skaters': Skater.objects.all(),
        'favorites_s': user.favorite_s.all(),
    }
    return render(request, 'players/skaters_averages.html', context)


def search(request):
    if 'q' in request.GET and request.GET['q']:
        q = request.GET['q']
        result_s = Skater.objects.filter(name__icontains=q)
        result_g = Goalie.objects.filter(name__icontains=q)
        result_list = result_s.values_list('name', 'nhl_id', 'slug', 'favorite').union(result_g.values_list('name', 'nhl_id', 'slug', 'favorite'))

        context = {
            'players': result_list,
            'query': q,
        }
        return render(request, 'players/search_results.html', context)
    else:
        return HttpResponse('Please submit a search term.')


def player_detail(request, slug, nhl_id):
    bio = services.season_stats(nhl_id)
    player = services.get_player(nhl_id)
    context = {
        'is_favorite': services.is_favorite(request, nhl_id),
        'player': player,
        'bio': bio,
        'stats': bio['stats'][0]['splits'][0]['stat'],
        'total': services.career_stats(nhl_id),
        'sbs_stats': services.sbs_stats(nhl_id),
        'last_gms': player.gamelog_stats[:5],
        'countries': services.COUNTRIES,
        'team': services.TEAM_ABBR,
    }

    return render(request, 'players/player_detail.html', context)


def player_gamelog(request, slug, nhl_id):

    context = {
        'player': services.get_player(nhl_id),
    }
    return render(request, 'players/player_gamelog.html', context)


def player_favorite(request, slug, nhl_id):
    player = services.get_player(nhl_id)
    if player.favorite.filter(id=request.user.id).exists():
        player.favorite.remove(request.user)
    else:
        player.favorite.add(request.user)
    return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))


def favorites(request):
    user = request.user
    context = {
        'favorites_g': user.favorite_g.all(),
        'favorites_s': user.favorite_s.all(),
    }
    return render(request, 'players/favorites.html', context)


def teams(request):
    context = {
        'teams': Team.objects.all(),
    }
    return render(request, 'players/teams.html', context)


def team_detail(request, slug, team_id):
    user = request.user
    skaters = Skater.objects.filter(team_abbr=services.TEAM_ABBR[team_id])
    context = {
        'goalies': Goalie.objects.filter(team_abbr=services.TEAM_ABBR[team_id]),
        'skaters': [
            {
                'type': 'Defencemen',
                'list': skaters.filter(position_abbr=services.POSITIONS[1]),
                'table_id': 'tab6',
            },
            {
                'type': 'Forwards',
                'list': skaters.filter(position_abbr__in=services.POSITIONS[2:]),
                'table_id': 'tab7',
            }
            ],
        'favorites_g': user.favorite_g.all(),
        'favorites_s': user.favorite_s.all(),
        'team': get_object_or_404(Team, nhl_id=team_id)
    }

    return render(request, 'players/team_detail.html', context)

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

Проблема была решена удалением NetWorx .Программа мониторинга пропускной способности и отчетов об использовании данных для Windows.

Ответ был найден случайно, потому что одна и та же программа NetWorx вызывала APPCRASH для Python ~ каждые 3 часа, когда я использовал Jupyter Notebook.Я нашел решение в этом ответе .Кстати, я использую Windows 7.

После удаления NetWorx Jupyter работал просто отлично.И тогда я понял, что это может быть той же самой причиной для Postgres вести себя странно.Поскольку NetWorx в настоящий момент не использовался, просто время от времени просматривайте графики трафика (каждые 1-2 месяца) для развлечения.

0 голосов
/ 06 февраля 2019

Полагаю, что-то связано с кавычками или одинарными кавычками, которые используются в структуре Json.Я не имею понятия о django и о том, как он работает, это может быть полезно, если вы используете некоторые функции postgres json.

Пожалуйста, дайте больше информации о версии и о том, как выполняются запросы.Попробуйте использовать элементы управления транзакцией (BEGIN, COMMIT, ROLLBACK), чтобы выполнить свой блок кода как транзакцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...