2013-02-24 5 views
3

Я делаю программу, которая (по крайней мере прямо сейчас) восстанавливает информацию о потоке с TwitchTV (потоковая платформа). Эта программа предназначена для самообучения, но когда я ее запускаю, требуется всего 2 минуты, чтобы напечатать только название стримера.Моя программа python работает очень медленно

Я использую Python 2.7.3 64bit на Windows7, если это важно в любом случае.

classes.py:

#imports: 
import urllib 
import re 

#classes: 
class Streamer: 

    #constructor: 
    def __init__(self, name, mode, link): 
     self.name = name 
     self.mode = mode 
     self.link = link 

class Information: 

    #constructor: 
    def __init__(self, TWITCH_STREAMS, GAME, STREAMER_INFO): 
     self.TWITCH_STREAMS = TWITCH_STREAMS 
     self.GAME = GAME 
     self.STREAMER_INFO = STREAMER_INFO 

    def get_game_streamer_names(self): 
     "Connects to Twitch.TV API, extracts and returns all streams for a spesific game." 

     #start connection 
     self.con = urllib2.urlopen(self.TWITCH_STREAMS + self.GAME) 
     self.info = self.con.read() 
     self.con.close() 

     #regular expressions to get all the stream names 
     self.info = re.sub(r'"teams":\[\{.+?"\}\]', '', self.info) #remove all team names (they have the same name: parameter as streamer names) 
     self.streamers_names = re.findall('"name":"(.+?)"', self.info) #looks for the name of each streamer in the pile of info 


     #run in a for to reduce all "live_user_NAME" values 
     for name in self.streamers_names: 
      if name.startswith("live_user_"): 
       self.streamers_names.remove(name) 

     #end method 
     return self.streamers_names 

    def get_streamer_mode(self, name): 
     "Returns a streamers mode (on/off)" 

     #start connection 
     self.con = urllib2.urlopen(self.STREAMER_INFO + name) 
     self.info = self.con.read() 
     self.con.close() 

    #check if stream is online or offline ("stream":null indicates offline stream) 
    if self.info.count('"stream":null') > 0: 
     return "offline" 
    else: 
     return "online" 

main.py:

#imports: 
from classes import * 

#consts: 
TWITCH_STREAMS = "https://api.twitch.tv/kraken/streams/?game=" #add the game name at the end of the link (space = "+", eg: Game+Name) 
STREAMER_INFO = "https://api.twitch.tv/kraken/streams/" #add streamer name at the end of the link 
GAME = "League+of+Legends" 

def main(): 
    #create an information object 
    info = Information(TWITCH_STREAMS, GAME, STREAMER_INFO) 

    streamer_list = [] #create a streamer list 
    for name in info.get_game_streamer_names(): 
     #run for every streamer name, create a streamer object and place it in the list 
     mode = info.get_streamer_mode(name) 
     streamer_name = Streamer(name, mode, 'http://twitch.tv/' + name) 
     streamer_list.append(streamer_name) 

    #this line is just to try and print something 
    print streamer_list[0].name, streamer_list[0].mode 


if __name__ == '__main__': 
    main() 

программа сама работает отлично, просто очень медленно

какие-либо идеи?

+2

выяснить, какая часть требует времени. Могут помочь модули 'profile' или' cProfile'. – lgautier

+0

Практически все ваше время захватывает данные с сайта. Если нет более эффективного способа захвата данных, я не вижу, как вы могли бы повысить производительность. –

ответ

4

Вы используете неправильный инструмент здесь для анализа данных json, возвращаемых вашим URL-адресом. Вам необходимо использовать библиотеку json, предоставленную по умолчанию, а не синтаксический анализ данных с помощью regex. Это даст вам толчок в выполнении вашей программы

Измените регулярное выражение парсер

#regular expressions to get all the stream names 
     self.info = re.sub(r'"teams":\[\{.+?"\}\]', '', self.info) #remove all team names (they have the same name: parameter as streamer names) 
     self.streamers_names = re.findall('"name":"(.+?)"', self.info) #looks for the name of each streamer in the pile of info 

Для JSon парсер

self.info = json.loads(self.info) #This will parse the json data as a Python Object 
#Parse the name and return a generator 
return (stream['name'] for stream in data[u'streams']) 
+0

Спасибо, я знал, что это был json, я просто не знал о модуле python json, много помогал. – Shay

6

эффективность программы, как правило, подпадает под правило 80/20 (или что-то люди называют правило 90/10 или даже правило 95/5). То есть, в 80% случаев программа фактически работает в 20% кода. Другими словами, есть хороший шанс, что ваш код имеет «узкое место»: небольшая область кода, которая работает медленно, а остальная часть работает очень быстро. Ваша цель - выявить это узкое место (или узкие места), а затем исправить его (их), чтобы работать быстрее.

Лучший способ сделать это - профилировать свой код. Это означает, что вы регистрируете время, когда происходит определенное действие с модулем logging, используйте timeit, как и предлагаемый комментатор, используйте часть встроенного profilers или просто распечатайте текущее время в самых точках программы. В конце концов, вы найдете одну часть кода, которая, как представляется, занимает больше времени.

Опыт подскажет вам, что ввод/вывод (например, чтение с диска или доступ к ресурсам через Интернет) займет больше времени, чем вычисления в памяти. Мое предположение о том, что вы используете 1 HTTP-соединение, чтобы получить список стримеров, а затем одно HTTP-соединение, чтобы получить статус этого стримера. Предположим, что есть 10000 стримеров: ваша программа должна будет сделать 10001 HTTP-соединений до того, как она закончится.

Там будет несколько способов исправить это, если это действительно так:

  • Смотрите, если Twitch.TV имеет несколько вариантов в их API, что позволяет получить список пользователей с их потоковом режиме так что вам не нужно вызывать API для каждого стримера.
  • Результаты кэш. Это на самом деле не поможет вашей программе работать быстрее при первом запуске, но вы можете сделать это так, чтобы, если он запускается второй раз в течение минуты, он может повторно использовать результаты.
  • Ограничьте свое приложение только при работе с несколькими стримерами одновременно.Если есть 10000 стримеров, что именно делает ваше приложение, что действительно нужно смотреть на режим всех 10000 из них? Возможно, лучше просто захватить верхнюю 20, после чего пользователь может нажать клавишу, чтобы получить следующие 20 или закрыть приложение. Часто программирование связано не только с написанием кода, но и с учетом ожиданий ваших пользователей. Кажется, это проект для домашних животных, поэтому могут быть не «пользователи», а значит, у вас есть свободное владение, чтобы изменить то, что делает приложение.
  • Используйте несколько соединений. Прямо сейчас ваше приложение делает одно соединение с сервером, ждет, пока результаты вернутся, проанализирует результаты, сохранит их, а затем начнет следующее соединение. Этот процесс может занять полсекунды. Если было 250 стримеров, запуск этого процесса для каждого из них занял бы чуть более двух минут. Тем не менее, если вы можете запустить четыре из них за раз, вы можете сократить время до 30 секунд. Проверьте модуль multiprocessing. Имейте в виду, что некоторые API могут иметь ограничения на количество подключений, которые вы можете сделать в определенное время, поэтому одновременное попадание их на 50 подключений может вызвать их раздражение и заставить их запретить вам получать доступ к их API. Соблюдайте осторожность.
+0

, чтобы получить обзор относительной производительности времени: 'python -mcProfile the_script.py' – jfs

+0

Я узнал способ запросить более одного стримера за запрос и ограничить извлеченные стримеры, спасибо за ваш ответ, помог много! – Shay

+0

Профилирование должно быть почти всегда первым шагом к решению проблемы производительности. – TimothyAWiseman

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