Найти - Пользователи
Полная версия: .read() - низкая скорость, threads
Начало » Python для новичков » .read() - низкая скорость, threads
1
snakeand1
Привет всем!
Есть код, в котором происходит запрос к Steam API. Запрос - urllib.request.urlopen(url). Запрос занимает около половины секунды, что меня устраивает. Меня не устраивает .read(), который занимает около 2 секунд. Из-за большого кол-ва запроса 2 секунды могут перерасти в минуты. Как можно его ускорить?
Может я не прав, но по-моему единственный шанс ускорить код - использовать потоки. И если я прав как это сделать? Пробовал запускать в двух потоках, одну и ту же функцию(включает в себя вызов других функций), потоки шли друг за другом, а не одновременно.
JOHN_16
я что то не могу понять о чем речь идет. это какая библиотека urllib, где есть request? Да и лучше сразу бы код показать. А то как то 2 секунды на read() это выглядит странно, если понимать этот метод как и в случае стандартной urllib
snakeand1
import urllib.request
import time
import sqlite3
import json
token = ''
#Должен быть токен от стима
def check_id64(str, name):
    req = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s' % (token, str)
    req = urllib.request.urlopen(req).read().decode('utf-8')
    if name in req:
        return True
    else:
        return False
def parse():
#    gamers = str(input())
    gamers = 'Member[0] id = [U:1:103130828] name = !Butthurtus Maximus'.split('\n')
    ids = []
    nicks = []
    for x in range(len(gamers)):
        id = gamers[x].split(':')[2].split(']')[0]
        nick = gamers[x].split('=')[2][1:]
        ids.append(id)
        nicks.append(nick)
    return ids, nicks
def get_id64(id, nick):
    key = 76561197960265728
    id64s = []
    for x in range(len(id)):
        id64 = int(id[x]) + key
        result = check_id64(str(id64), nick[x])
        if result:
            id64s.append(id64)
        else:
            id64 = id64 + 1
            id64s.append(id64)
    return id64s
def get_backpack(id):
    req = 'http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=%s&steamid=%s' % (token, str(id[0]))
    request = urllib.request.urlopen(req).read() #Тот самый read
    request = request.decode()
    json_item = json.loads(request)['result']['items']
    player_items = []
    for elem in json_item:
        defindex = elem['defindex']
        if defindex not in player_items:
            player_items.append(defindex)
    return player_items
def find(defind):
    t = (defind, )
    conn = sqlite3.connect('dota2items.db')
    c = conn.cursor()
    c.execute('select * from items where defindex=?', t)
    return c
def get_items(sorted_items):
    items_ready = []
    for elem in sorted_items:
        item = find(str(elem)).fetchone()
        items_ready.append(item)
    return items_ready
def main():
    data = parse()
    id = data[0]
    nickname = data[1]
    id64 = get_id64(id, nickname)
    items = get_items(get_backpack(id64))
if __name__ == '__main__':
    a = time.time()
    main()
    print(time.time() - a)

python 3.3.2
py.user.next
JOHN_16
я что то не могу понять о чем речь идет. это какая библиотека urllib, где есть request?
это не requests
в третьем питоне urllib и urllib2 собрали в один пакет, упорядочив его

snakeand1
Меня не устраивает .read(), который занимает около 2 секунд. Из-за большого кол-ва запроса 2 секунды могут перерасти в минуты. Как можно его ускорить?
вообще, можно не через .read() читать, а через next()

>>> import urllib.request
>>> data = urllib.request.urlopen('http://python.su')
>>> next(data)
b'\n'
>>> next(data)
b'\n'
>>> next(data)
b'\n'
>>> next(data)
b'\n'
>>> next(data)
b'\n'
>>> next(data)
b'<!doctype html>\n'
>>>
>>> 
>>> for i, _ in zip(data, range(3)):
...   i
... 
b'<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->\n'
b'<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->\n'
b'<!--[if IE 7 ]>    <html lang="en" class="no-js ie7"> <![endif]-->\n'
>>>

snakeand1
Может я не прав, но по-моему единственный шанс ускорить код - использовать потоки.
если запросов много, то лучше распределить их, чтобы они параллельно работали

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

можно построчно читать через next() (явно или в цикле) и помещать строки в очередь (queue.Queue), а там уже другим потоком из очереди распределять

но всё это в одном случае: если распараллеливание необходимо
snakeand1
Запускал я потоки, скорее всего, неправильно
t1 = threading.Thread(target=main, args=(0, ))
t2 = threading.Thread(target=main, args=(1, ))
t1.start()
t2.start()
t1.join(); t2.join()
Аргументы для запусков потоков - это задержка. Делал через time.sleep()
В итоге время было в два раза больше, чем когда я запускал функцию main()
snakeand1
Попытался написать потокобезопасный код(заменил все списки на очереди)
def get_id64(id, nick):
    key = 76561197960265728
    for x in range(len(id)):
        id64 = int(id[x]) + key
        result = check_id64(str(id64), nick[x])
        if result:
            info = id64, nick[x]
            gamer_queue.put(info)
        else:
            id64 += 1
            info = id64, nick[x]
            gamer_queue.put(info)
В итоге gamer_queue.put() срабатывает только один раз, будто написан вне цикла.
Такая же проблема в другой функции.
В чем может быть проблема?

Все получилось!
snakeand1
Вообщем все сделал - потоки работают, но работают они через одно место.
Код
a = time.time()
    find_info()
    thread1 = threading.Thread(target=main)
    thread2 = threading.Thread(target=main)
    thread1.start()
    thread2.start()
    print(time.time() - a)

Вывод консоли
http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=&steamid=76561198063396556
http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=&steamid=76561198075819059
3.1671149730682373
http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=&steamid=76561198043509835
http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=&steamid=76561198079601121
http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=&steamid=76561197980940780
http://api.steampowered.com/IEconItems_570/GetPlayerItems/v0001/?key=&steamid=76561198070399982
Process finished with exit code 0
snakeand1
Все сделал! Чтобы все выполнялось по-порядку, надо было написать thread1.join()
thread2.join().
Тему можно закрывать!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB