2016-07-12 6 views
2

Я создал программу для заполнения банка данных, и к тому времени он работает. В принципе, программа делает запрос на приложение, которое я использую (через REST API) возвращает данные, которые я хочу, а затем манипулирую с приемлемой формой для банка данных.Улучшение производительности - Looping with Get Method

Проблема заключается в следующем: метод GET делает алгоритм слишком медленным, потому что я обрабатываю детали отдельных записей, поэтому для каждой записи я должен сделать 1 запрос. У меня есть что-то около 15000 запросов, и каждая строка в банке занимает 1 секунду.

Есть ли способ ускорить запрос? Как я могу улучшить работу этого метода? И, кстати, какие-нибудь советы по измерению производительности кода?

Спасибо заранее!

вот код:

# Retrieving all the IDs I want to get the detailed info 
abc_ids = serializers.serialize('json', modelExample.objects.all(), fields=('id')) 
abc_ids = json.loads(abc_ids) 
abc_ids_size = len(abc_ids) 

# Had to declare this guys right here because in the end of the code I use them in the functions to create and uptade the back 
# And python was complaining that I stated before assign. Picked random values for them. 
age = 0 
time_to_won = 0 
data = '2016-01-01 00:00:00' 

# First Loop -> Request to the detailed info of ABC 
for x in range(0, abc_ids_size): 

id = abc_ids[x]['fields']['id'] 
url = requests.get(
    'https://api.example.com/v3/abc/' + str(
     id) + '?api_token=123123123') 

info = info.json() 
dealx = dict(info) 

# Second Loop -> Picking the info I want to uptade and create in the bank 
for key, result in dealx['data'].items(): 
    # Relevant only for ModelExample -> UPTADE 
    if key == 'age': 
     result = dict(result) 
     age = result['total_seconds'] 
    # Relevant only For ModelExample -> UPTADE 
    elif key == 'average_time_to_won': 
     result = dict(result) 
     time_to_won = result['total_seconds'] 

    # Relevant For Model_Example2 -> CREATE 
    # Storing a date here to use up foward in a datetime manipulation 
    if key == 'add_time': 
     data = str(result) 

    elif key == 'time_stage': 

     # Each stage has a total of seconds that the user stayed in. 
     y = result['times_in_stages'] 
     # The user can be in any stage he want, there's no rule about the order. 
     # But there's a record of the order he chose. 
     z = result['order_of_stages'] 

     # Creating a list to fill up with all stages info and use in the bulk_create. 
     data_set = [] 
     index = 0 

     # Setting the number of repititions base on the number of the stages in the list. 
     for elemento in range(0, len(z)): 
      data_set_i = {} 
      # The index is to define the order of the stages. 
      index = index + 1 

      for key_1, result_1 in y.items(): 
       if int(key_1) == z[elemento]: 
        data_set_i['stage_id'] = int(z[elemento]) 
        data_set_i['index'] = int(index) 
        data_set_i['abc_id'] = id 

        # Datetime manipulation 
        if result_1 == 0 and index == 1: 
         data_set_i['add_date'] = data 

        # I know that I totally repeated the code here, I was trying to get this part shorter 
        # But I could not get it right. 
        elif result_1 > 0 and index == 1: 
         data_t = datetime.strptime(data, "%Y-%m-%d %H:%M:%S") 
         data_sum = data_t + timedelta(seconds=result_1) 
         data_sum += timedelta(seconds=3) 
         data_nova = str(data_sum.year) + '-' + str(formaters.DateNine(
          data_sum.month)) + '-' + str(formaters.DateNine(data_sum.day)) + ' ' + str(
          data_sum.hour) + ':' + str(formaters.DateNine(data_sum.minute)) + ':' + str(
          formaters.DateNine(data_sum.second)) 
         data_set_i['add_date'] = str(data_nova) 

        else: 
         data_t = datetime.strptime(data_set[elemento - 1]['add_date'], "%Y-%m-%d %H:%M:%S") 
         data_sum = data_t + timedelta(seconds=result_1) 
         data_sum += timedelta(seconds=3) 
         data_nova = str(data_sum.year) + '-' + str(formaters.DateNine(
          data_sum.month)) + '-' + str(formaters.DateNine(data_sum.day)) + ' ' + str(
          data_sum.hour) + ':' + str(formaters.DateNine(data_sum.minute)) + ':' + str(
          formaters.DateNine(data_sum.second)) 
         data_set_i['add_date'] = str(data_nova) 

        data_set.append(data_set_i) 

Model_Example2_List = [Model_Example2(**vals) for vals in data_set] 
Model_Example2.objects.bulk_create(Model_Example2_List) 

ModelExample.objects.filter(abc_id=id).update(age=age, time_to_won=time_to_won) 
+0

Кому-то нужно обновить этот API, чтобы получать информацию навалом, а не только по одному элементу за раз. Это значительно улучшит производительность. – Rohan

ответ

1

если узкое место в запросе сети, существует не так много вы можете сделать, за исключением, возможно, использовать GZIP или выкачать но с requests ..

Кодировки gzip и deflate автоматически декодируются для вас.

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

{ 'Accept-Encoding': 'gzip,deflate'} 

Другой альтернативой является использование многопоточности и имеют много запросов работать в parrallel, хороший вариант, если у вас есть много о пропускной способности и нескольких ядер.

Наконец, есть много разных способов профилировать python, включая команду cprofile + kcachegrind.

+0

Большое спасибо за ответ =) Я попытался добавить gzip и deflate в свой заголовок запроса, но я не почувствовал никаких изменений. Я постараюсь углубиться в оба параметра, чтобы понять, не хватает ли я чего-то. Но в любом случае параллельная обработка будет лучшим вариантом прямо сейчас. Полагаю, мне придется быть маленьким пациентом с этим конкретным кодом. –

+0

добро пожаловать. Я думаю, что лучше инвестировать в потоки. – e4c5

Смежные вопросы