Помогите мне ускорить этот код - Python
Ребята, я пишу эту программу, которая просматривает список твитов и возвращает слова, которые были использованы чаще всего.
Я хочу сделать это быстрее, но мне интересно, если вы можете помочь указать на некоторые проблемы или области, которые я могу улучшить скорость. Спасибо
см код ниже
#import string
import re
from string import punctuation
from operator import itemgetter
import pprint
class Tweet:
def __init__(self, timestamp, userId, message):
self.timestamp = timestamp
self.userId = userId
self.message = message
def getDate(self):
tokens = re.split(' ', self.timestamp)
return tokens[0]
def __repr__(self):
return "[timestamp=%s userId=%s message=%s]" % (self.timestamp, self.userId, self.message)
outfile = file
def readOneTweet(file):
""" Reads a single tweet from the file, and returns the string containing the tweet.
This will often just be a single line from the file, but may be more if it ends with a slash.
"""
lineBuffer = ""
while True:
# TODO: read the line and strip it
rawLine = file.readline().strip('\n')
if (len(rawLine)== 0):
break
lineBuffer +=rawLine
if (rawLine[(len(rawLine)-1)]!= "\\"):
break
return lineBuffer
def readTweets():
tweets = []
inputfile = raw_input("Enter filename: ")
# move the try / except around a single tweet.
# so that we can keep going if we encounter a line with an error.
try:
f = open(inputfile , "r")
while True:
tweet = readOneTweet(f) # readOneTweet is method
if not tweet:
break
try:
lineStrip = tweet.rstrip()
split_word = re.split('\t', lineStrip.lower()) #('/([^a-z])([A-Z]) ([0-9])/n:.;\]+/', line.lower())
tweetTime = split_word[1]
userId = split_word[0]
message = split_word[2]
tweets.append(Tweet(tweetTime, userId, message))
if len(tweets) % 10000 == 0:
print 'read', len(tweets), 'tweets'
except IndexError, e:
print "bad tweet", tweet
except IOError:
print "file not found!"
return tweets
######################DATA ##############
"""
- Need to separate tweets
- Obtain information about each tweet - UserID, Time, words
"""
def writeWordFile(word):
toWrite = 'test.txt'
fileHandle = open ( toWrite, 'w' )
for i in word:
fileHandle.write (i)
def dailyMessages(twt):
dailyMsg =dict ()
for i in twt:
date =i.getDate()
#print i.message
#dailyMsg[date] =messageList
if dailyMsg.has_key(date):
dailyMsg[date].append(twt)
else:
dailyMsg[date] =[twt]
#for k, v in dailyMsg.items():
#print k, v, '\n'
return dailyMsg
"""
Takes dailyTweets and perform word coun.
"""
def dailyWord(tweetsByDay):
dailyTweetsWordCount = { }
for date in tweetsByDay.keys():
dayTweets =tweetsByDay[date]
if len(dayTweets) != 0:
count = wordCount(dayTweets)
dailyTweetsWordCount[date] = count
return dailyTweetsWordCount
def wordCount(tweets):
"""Takes a list of tweets and returns a dictionary of counts for words"""
N = 100
# we'll build a dictionary mapping each word to a SET of users who have used it
wordTweeters = {}
for tweet in tweets:
# print tweet
for i in tweet:
for word in i.message.split():
if not wordTweeters.has_key(word):
wordTweeters[word] = set()
wordTweeters[word].add(i.userId)
# we'll build up a dictionary mapping each word to the number of users who have used it.
p = dict ()
#print wordTweeters
for day in wordTweeters.keys():
usersNo = len (wordTweeters[day])
p[day] = usersNo
#print wordTweeters
return p #wordTweeters, p
def searchForMemes(tweetUserCounts):
for key in tweetsUserCounts.keys():
# for pmeme in tweetUserCounts
pass
"""Takes information returned by daily word"""
def isMeme(word, day1Count, day2Count, day3Count):
#takes the daily count
# check if it is a meme
#First - check count
#check count in different days
# determine the if it qualifies as a tweet
# if not drop it do not do below checks
#Second - time stamp
#CHECK ITS TIME TRACK
#How is the count of over time
# rise and fall
#
#Third - user id
# check if is form different users
#how many of those counts are from different users
pass
def dayUserCount(z,word, d1, d2, d3):
""" assume dictionary will be input"""
# check if the word exist in the dictionary
if z.has_key(d1):
date1 =z[d1]
#print value.keys()
if date1.has_key(word):
print date1
c1 =date1[word]
else:
print "word not used in %s"%d1
c1 =0
else:
print 'date does not exist'
if z.has_key(d2):
#print value.keys()
date2 =z[d2]
if date2.has_key(word):
print date2
c2 =date2[word]
else:
print "word not used in %s"%d2
c2 =0
else:
print 'date does not exist'
if z.has_key(d3):
date3 = z[d3]
if date3.has_key(word):
print date3
c3 =date3[word]
else:
print "word not used in %s" %d3
c3 =0
else:
print 'date does not exist'
result = "Word: %s , %s count: %s, %s count: %s, %s count: %s"%(word,d1,c1,d2,c2, d3,c3)
return result
# supportive functions
def hashtag(tw):
hasht =[]
for word in tw.split():
if word.startswith('#'):
hasht.append(word)
return hasht
def httpTag(tw):
http =[]
for word in tw.split():
if word.startswith('http'):
http.append(word)
return http
def reply(tw):
reply =[]
for word in tw.split():
if word.startswith('@'):
reply.append(word)
return reply
def reTweet(tw):
rt =[]
for word in tw.split():
if word.startswith('rt') or word.startswith('RT'):
rt.append(word)
return rt
"""
Old functions
"""
def writeToFile(tweet):
#filename = test.txt
filek = open('test.txt', 'w')
print "writing on the file: "
filek.write(tweet)
# print " _____--------______" + tweet
filek.close()
# count word frequency.
def f2count():
N = 100000000000
words = {}
words_gen = (word.strip(punctuation).lower()
for line in open('c.txt')
for word in line.split())
for word in words_gen:
words[word] = words.get(word, 0) + 1
top_words = sorted(words.iteritems(),
key=lambda(word, count): (-count, word))[:N]
for word, frequency in top_words:
print "%s: %d" % (word, frequency)
3 ответа
if (len(rawline) == 0):
может быть написано как
if rawline:
Вы никогда не должны использовать len(rawline) - 1
в качестве индекса просто используйте rawline[-1]
,
Я не знаю, почему вы используете re.split()
, когда ты мог просто сделать linestip.lower().split('\t')
,
Не использовать dailyMsg.has_key(date)
использовать date in dailyMsg
,
Когда вы перебираете tweetsByDay
Вы действительно должны делать это:
for date, value in tweetsByDay.items():`
таким образом, вам не нужно вручную связывать значение с ключом.
Это только начало. Есть еще много вопросов, которые нужно проработать. Я думаю, что вам действительно нужно поработать над освоением Python - из чтения вашего кода ясно, что либо Python не является вашим первым языком, либо вы узнали из ресурса, который не научил вас правильно его писать. Например, почему вы ставите круглые скобки вокруг условных выражений? Это не обязательно в Python (хотя это артефакт из Algol-подобных языков, таких как C или Java). Почему вы используете dict()
вместо {}
? Желательно писать пустой диктовку вторым способом. Вы можете найти этот урок по идиоматическому Python полезным.
wordCount()
можно запустить параллельно. Поскольку каждый твит напрямую не зависит от другого, нет причин для последовательного просмотра списка. Разбейте список твитов на более мелкие списки, а затем создайте поток для каждого подсписка. Как только они закончили создавать свои под-словари, вы можете немного поработать, чтобы объединить их все в один словарь.
РЕДАКТИРОВАТЬ:
Пример того, как парализовать суммирование списка. Вы бы изменили тело потока, чтобы сделать то, что ваша задача.
from threading import Thread
numbers = range(1000)
class Sum(Thread):
def __init__(self, numList):
Thread.__init__(self)
self.numList = numList
self.total = 0
def run(self):
for num in self.numList:
self.total += num
numThreads = 7
threads = []
perThread = len(numbers)/numThreads
for i in xrange(numThreads):
start = i*perThread
t = Sum(numbers[start:len(numbers) if i == numThreads-1 else start+perThread])
t.start()
threads.append(t)
grandTotal = 0
for t in threads:
t.join()
grandTotal += t.total
print grandTotal
Этот код полон неоптимизированных фрагментов.
Например, каждый вызов функции занимает время. Не делайте бесполезных вызовов для работы, и вы сэкономите время. Некоторые вызовы могут быть заменены на список понимания: хэштег,httpTag, ... и т. Д.
Я мог бы помочь оптимизировать, но:
1 - мне сейчас не хватает времени на долгую работу такого рода
2 - мы не можем оптимизировать, потому что код не завершен: где вызываются следующие функции?:
readTweets
writeWordFile
dailyMessages
dailyWord
wordCount
searchForMemes
isMeme
dayUserCount
hashtag
httpTag
reply
reTweet
writeToFile
f2count
3 - Я устал отвечать на новые зарегистрированные люди, которые появляются на стеке с тяжелыми вопросами и исчезают после этого, иногда не давая никаких новостей или комментариев. Извините, если вы намеревались этого не делать
РЕДАКТИРОВАТЬ
WriteToFile
f2count
должно быть вычеркнуто из списка.