Ускорьте функцию разбора с помощью многопроцессорной обработки - PullRequest
0 голосов
/ 23 июня 2018

Я пытаюсь получить средний день рождения ваших друзей с помощью парсинга.Но это занимает около минуты.Я попытался ускорить с многопроцессорным, но получил ошибку.Как я могу ускорить свою функцию.Также пробовал session.get, но он не влияет на скорость функции

def mean_friend_age(idi):
    mean_age_id = []
    mean_age = []
    age_number = []
    session = requests.Session()
    r_mean_id = requests.get('https://api.vk.com/method/friends.get? user_id='+ str(idi) + '&v=5.52&access_token=TOKEN')
    json_mean_id = r_mean_id.text
    string_mean_id = json_mean_id[34:-3]
    mean_ids_list = string_mean_id.split(',')
    for item in mean_ids_list:
        mean_age_id.append(item)
    for item in mean_age_id:
        req_mean = session.get('https://api.vk.com/method/users.getuser_id='+ str(item) + '&v=5.52&access_token=TOKEN&fields=counters,sex,bdate,country,hometown,lists,last_seen,verified,occupation,wall_comments,can_write_private_message, can_see_audio, can_see_all_posts, can_post')
        json_mean = req_mean.json()
        for item in json_mean['response']:
            json_dict = item
        while True:
            try:
                age = json_dict['bdate']
                break
            except KeyError:
                age = '0'
                break
        mean_age.append(age)
    for item in mean_age:
        if len(item) >= 7:
            dt_obj = datetime.datetime.strptime(item, '%d.%m.%Y')
            item_number = get_age(dt_obj)
            age_number.append(item_number)
    mean = statistics.mean(age_number)
    return mean

, затем я пытаюсь выполнить многопроцессорность и получаю ошибку:

if __name__ == '__main__':
    with Pool(5) as p:
        a = p.map(mean_friend_age, '181145622')



Traceback (most recent call last):
File "/usr/lib/python3.6/multiprocessing/pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
File "/usr/lib/python3.6/multiprocessing/pool.py", line 44, in mapstar
return list(map(*args))
File "<ipython-input-63-2984c547fa8d>", line 18, in mean_friend_age
age = json_dict['bdate']
UnboundLocalError: local variable 'json_dict' referenced before 
assignment

The above exception was the direct cause of the following exception:

UnboundLocalError                         Traceback (most recent call 
last)
<ipython-input-65-39dd60c6a8fb> in <module>()
  1 if __name__ == '__main__':
  2     with Pool(5) as p:
----> 3         a = p.map(mean_friend_age, '181145622')

/usr/lib/python3.6/multiprocessing/pool.py in map(self, func, 
iterable, chunksize)
264         in a list that is returned.
265         '''
--> 266         return self._map_async(func, iterable, mapstar, 
chunksize).get()
267 
268     def starmap(self, func, iterable, chunksize=None):

/usr/lib/python3.6/multiprocessing/pool.py in get(self, timeout)
642             return self._value
643         else:
--> 644             raise self._value
645 
646     def _set(self, i, obj):

UnboundLocalError: local variable 'json_dict' referenced before 
assignment

Как я могу ускорить функцию?

1 Ответ

0 голосов
/ 23 июня 2018

Проблема в вашем коде проста.

Здесь в цикле for вы присваиваете item переменной json_dict:

for item in json_mean['response']:
    json_dict = item

И затем вы хотите получить доступ к этомуjson_dict в другом while цикле:

while True:
    try:
        age = json_dict['bdate']

Проблема здесь scoping.Таким образом, каждая переменная почти в каждом языке (например, var в JS отличается) имеет область видимости.Это означает, что если вы создаете его в блоке кода (который в таких языках, как C / C ++ / Java и т. Д. Находится между {}, а в Python это делается с помощью отступа в коде), ваша переменная «жива» до тех пор, пока вы не покинетеэтот блок кода.

В представленном вами коде не только вы теряете область видимости переменной json_dict (поэтому она не известна компилятору или в данном текущем примере интерпретатору) после того, как вы оставилицикл, и вы не можете получить к нему доступ из цикла while, но, кроме того, вы overwrite делаете это при каждой итерации цикла for (я не знаю, действительно ли это то, что вы действительно хотели сделать).

Решение будетсоздайте json_dict выше для цикла (и присвойте его None, как угодно), а затем получите доступ к нему как из for, так и while циклов

...