我的python程序正在运行

2024-05-14 17:26:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在制作一个程序(至少现在)从TwitchTV(流媒体平台)检索流信息。这个程序是自我教育,但当我运行它时,只需2分钟就可以打印出拖缆的名称。

我正在Windows7上使用Python2.7.364bit,如果这在任何情况下都很重要的话。

类.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"

主.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()

程序本身工作得很好,只是速度很慢

有什么想法吗?


Tags: thenameselfinfogamefornamesmode
2条回答

程序效率通常低于80/20规则(或者一些人称之为90/10规则,甚至95/5规则)。也就是说,80%的时间程序实际运行在20%的代码中。换句话说,有一个很好的例子表明你的代码有一个“瓶颈”:一小部分代码运行得很慢,而其余的代码运行得很快。您的目标是确定瓶颈(或瓶颈),然后修复它(或瓶颈)以更快地运行。

最好的方法是分析你的代码。这意味着您要记录在logging模块中发生特定操作的时间,使用timeit就像建议的注释程序一样,使用一些内置的profilers,或者只是在程序的各个点打印出当前时间。最后,您将发现代码中似乎占用了最多时间的一部分。

经验会告诉你,I/O(比如从磁盘读取,或者通过internet访问资源)比内存计算要花更长的时间。我对这个问题的猜测是,您使用一个HTTP连接来获取拖缆列表,然后使用一个HTTP连接来获取该拖缆的状态。假设有10000个拖缆:您的程序在完成之前需要建立10001http连接。

如果真是这样的话,有几种方法可以解决这个问题:

  • 查看Twitch.TV的API中是否有其他选项,允许您检索流模式用户的列表,这样就不需要为每个流调用API。
  • 缓存结果。这实际上不会帮助您的程序在第一次运行时运行得更快,但是您可以使它在一分钟内再次运行,从而可以重用结果。
  • 将应用程序限制为一次只处理几个拖缆。如果有10000个拖缆,那么您的应用程序到底做了什么?它确实需要查看所有10000个拖缆的模式?也许最好是抓住前20名,此时用户可以按一个键获得下20名,或者关闭应用程序。通常,编程不仅仅是编写代码,而是管理用户的期望。这似乎是一个宠物项目,所以可能没有“用户”,这意味着你有自由支配权来改变应用程序的功能。
  • 使用多个连接。现在,你的应用程序与服务器建立一个连接,等待结果返回,分析结果,保存结果,然后开始下一个连接。这个过程可能需要半秒钟。如果有250个拖缆,则为每个拖缆运行此过程总共需要两分钟多一点的时间。然而,如果你一次能跑四次,你可能会把你的时间减少到总共不到30秒。查看multiprocessing模块。请记住,某些API可能会限制您在某个时间可以建立多少个连接,因此一次使用50个连接来攻击它们可能会使它们厌烦,并导致它们禁止您访问它们的API。注意这里。

您使用了错误的工具来解析URL返回的json数据。您需要使用默认提供的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'])

相关问题 更多 >

    热门问题