我开发了一个脚本,可以从.txt文件列表中随机选择50个元素。这个过程重复100次。脚本将随机选择的文本文件连接到一个长字符串中,然后过滤出最长的子字符串。
我想在数字海洋上的一个水滴上运行这个脚本。但是,服务器会杀死脚本。当我随机选择3个元素时,它就能工作了。我没记忆了吗?我如何处理这个问题呢?
这是文件我随机选择项目。这是我的密码:
# coding: utf-8
import glob
from collections import Counter
import pickle
import random
de_list_soz = pickle.load(open('de_list_soz.p', 'rb'))
str_seq_list = []
for str_seq in range(0,100):
#creating random list
random_list = []
for item in range(0,50):
list_item = random.choice(de_list_soz)
random_list.append(list_item)
#creating long string
long_str = ''
for de in random_list:
input_file = open('txt_sr_de/txt_sr_de/' + de, 'r')
text = input_file.read()
text = text.replace('\n', ' ').replace('\xa0', '').replace(' ', '')
#Removing these automated notifications
text = text.replace('Wichtiger Hinweis:Diese Website wird in älteren Versionen von Netscape ohne graphische Elemente dargestellt. Die Funktionalität der Website ist aber trotzdem gewährleistet. Wenn Sie diese Website regelmässig benutzen, empfehlen wir Ihnen, auf Ihrem Computer einen aktuellen Browser zu installieren.Zurück zur Einstiegsseite Drucken Grössere Schrift', '')
text = text.replace('Vorwärts ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
text = text.replace('Bundesgericht Tribunal fédéral Tribunale federale Tribunal federal', '')
text = text.replace('Navigation Neue Suche Zurück zum Suchresultat Rang: Zurück 180', '')
text = text.replace('Navigation Neue Suche Zurück zum Suchresultat Rang:1 ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
text = text.replace(' ', ' ')
long_str = long_str + text
times=3
for n in range(1,int(len(long_str)/times+1)):
substrings=[long_str[i:i+n] for i in range(len(long_str)-n+1)]
freqs=Counter(substrings)
if freqs.most_common(1)[0][1]<3:
n-=1
break
else:
seq=freqs.most_common(1)[0][0]
str_seq_list.append(seq)
pickle.dump(str_seq_list, open('SOZIALRECHT_DE.p', 'wb'))发布于 2017-03-07 14:33:19
由于您的代码同时执行多个操作,因此您应该将其拆分为函数以提高可读性。第一次天真的重写会产生以下结果:
from collections import Counter
import random
def filter_text(text):
return (text
.replace('\n', ' ')
.replace('\xa0', '')
.replace(' ', '')
#Removing these automated notifications
.replace('Wichtiger Hinweis:Diese Website wird in älteren Versionen von Netscape ohne graphische Elemente dargestellt. Die Funktionalität der Website ist aber trotzdem gewährleistet. Wenn Sie diese Website regelmässig benutzen, empfehlen wir Ihnen, auf Ihrem Computer einen aktuellen Browser zu installieren.Zurück zur Einstiegsseite Drucken Grössere Schrift', '')
.replace('Vorwärts ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
.replace('Bundesgericht Tribunal fédéral Tribunale federale Tribunal federal', '')
.replace('Navigation Neue Suche Zurück zum Suchresultat Rang: Zurück 180', '')
.replace('Navigation Neue Suche Zurück zum Suchresultat Rang:1 ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
.replace(' ', ' '))
def create_string_from_files(files, root='txt_sr_de/txt_sr_de', sample=50):
#creating random list
random_list = []
for item in range(sample):
list_item = random.choice(files)
random_list.append(list_item)
#creating long string
long_str = ''
for de in random_list:
input_file = open(os.path.join(root, de), 'r')
text = input_file.read()
long_str = long_str + filter_text(text)
return long_str
def extract_most_common_sequence(text, minimum_occurences=3, times=3):
for n in range(1,int(len(text)/times+1)):
substrings=[text[i:i+n] for i in range(len(text)-n+1)]
freqs=Counter(substrings)
if freqs.most_common(1)[0][1] < minimum_occurences:
n-=1
return seq
else:
seq=freqs.most_common(1)[0][0]
def main(files, repeat=100):
str_seq_list = []
for str_seq in range(repeat):
long_str = create_string_from_files(files)
str_seq_list.append(extract_most_common_sequence(long_str))
return str_seq_list
if __name__ == '__main__':
import pickle
de_list_soz = pickle.load(open('de_list_soz.p', 'rb'))
str_seq_list = main(de_list_soz)
pickle.dump(str_seq_list, open('SOZIALRECHT_DE.p', 'wb'))现在我们可以开始清理了。
在create_string_from_files中,您基本上是在重新发明random.sample:
>>> import random
>>> random.sample('abcdefghi', 4)
['h', 'e', 'c', 'f']您也碰巧遇到了open文件,但从未关闭它们:使用with语句自动处理这些文件。
最后,手工连接长句并不是有效的记忆。现在,让我们请求str.join为我们做这件事。但为了更好地完成这一任务,我们需要进一步拆分函数:
def read_and_filter_file(filename):
with open(filename) as input_file:
text = input_file.read()
return filter_text(text)
def create_string_from_files(files, root='txt_sr_de/txt_sr_de', samples=50):
return ''.join(
read_and_filter_file(os.path.join(root, de))
for de in random.sample(files, samples)
)通过将“创建空列表+ for循环+ append”模板替换为更有效的列表理解,可以对主要功能进行类似的改进:
def main(files, repeat=100):
return [
extract_most_common_sequence(create_string_from_files(files))
for _ in range(repeat)
]extract_most_common_sequence函数也可以使用一些迭代工具配方进行优化。我正在考虑pairwise配方的一个变化,因为您的列表理解,n是2差不多就是了。即使用:
>>> long_str = 'This is a test'
>>> n = 2
>>> [long_str[i:i+n] for i in range(len(long_str)-n+1)]
['Th', 'hi', 'is', 's ', ' i', 'is', 's ', ' a', 'a ', ' t', 'te', 'es', 'st']
>>> n = 4
>>> [long_str[i:i+n] for i in range(len(long_str)-n+1)]
['This', 'his ', 'is i', 's is', ' is ', 'is a', 's a ', ' a t', 'a te', ' tes', 'test']所以用这样的方法:
def tuplewise(iterable, length):
tees = itertools.tee(iterable, length)
for i, t in enumerate(tees):
for _ in xrange(i):
next(t, None)
return itertools.izip(*tees)用于Python 2或:
def tuplewise(iterable, length):
tees = itertools.tee(iterable, length)
for i, t in enumerate(tees):
for _ in range(i):
next(t, None)
return zip(*tees)对于Python 3,您可以简化写操作,并节省一些内存使用,如下所示:
def extract_most_common_sequence(text, minimum_occurences=3, times=3):
sequence = ''
for n in range(1, int(len(text)/times+1)):
freqs = Counter(tuplewise(text, n))
(most_frequent, higher_frequency), = freqs.most_common(1)
if higher_frequency < minimum_occurences:
break
sequence = ''.join(most_frequent)
return sequence现在,我将sequence = ''定义为一种安全措施,在不太可能出现文本很短的情况下,“否”字母会出现两次以上。它只是让函数在每一种情况下都返回一些东西。
既然代码的可读性更强,让我们来解决您的内存问题。
需要注意的是,在内存中的单个字符串中聚合50个文件的内容可能会导致崩溃。因此,让我们使用一些磁盘存储。为此,我们将使用tempfile模块。这样做的目的是将过滤过的文本存储到一个文件中,并读取该文件(一遍又一遍),以获得所需的最常见的序列。因此,我们需要对tuplewise进行一点调整,要么一次读取一个字符,然后按请求的大小读取yield单词,或者更好的是,就I/O而言,反复读取一个固定大小的数据块,然后逐个从其中获取字符,以生成所需大小的单词:
import os
import random
import itertools
import tempfile
from collections import Counter
def filter_text(text):
return (text
.replace('\n', ' ')
.replace('\xa0', '')
.replace(' ', '')
#Removing these automated notifications
.replace('Wichtiger Hinweis:Diese Website wird in älteren Versionen von Netscape ohne graphische Elemente dargestellt. Die Funktionalität der Website ist aber trotzdem gewährleistet. Wenn Sie diese Website regelmässig benutzen, empfehlen wir Ihnen, auf Ihrem Computer einen aktuellen Browser zu installieren.Zurück zur Einstiegsseite Drucken Grössere Schrift', '')
.replace('Vorwärts ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
.replace('Bundesgericht Tribunal fédéral Tribunale federale Tribunal federal', '')
.replace('Navigation Neue Suche Zurück zum Suchresultat Rang: Zurück 180', '')
.replace('Navigation Neue Suche Zurück zum Suchresultat Rang:1 ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
.replace(' ', ' '))
def read_and_filter_file(filename):
with open(filename) as input_file:
text = input_file.read()
return filter_text(text)
def create_string_from_files(output, files, root='txt_sr_de/txt_sr_de', samples=50):
for filename in random.sample(files, samples):
output.write(read_and_filter_file(os.path.join(root, filename)))
def read_chunks(file_object, chunk_size, block_size=4096):
word = file_object.read(chunk_size)
yield word
while True:
data = file_object.read(block_size)
if not data:
return
for character in data:
# Drop first character and append the next one
word = word[1:] + character
yield word
def extract_most_common_sequence(input_file, minimum_occurences=3, times=3):
input_file.seek(0, os.SEEK_END)
file_size = input_file.tell()
sequence = ''
for n in range(1, int(file_size/times+1)):
input_file.seek(0) # Be sure to read the whole file each time
freqs = Counter(read_chunks(input_file, n))
(most_frequent, higher_frequency), = freqs.most_common(1)
if higher_frequency < minimum_occurences:
break
sequence = most_frequent
return sequence
def main(files):
with tempfile.NamedTemporaryFile(mode='w+') as storage:
create_string_from_files(storage, files)
return extract_most_common_sequence(storage)
if __name__ == '__main__':
import pickle
de_list_soz = pickle.load(open('de_list_soz.p', 'rb'))
str_seq_list = [main(de_list_soz) for _ in range(100)]
pickle.dump(str_seq_list, open('SOZIALRECHT_DE.p', 'wb'))我将main更改为返回单个元素,而不是返回整个列表,因为使用此实现感觉更清晰。所有重复的事情现在都在测试代码中完成。
发布于 2017-03-07 14:52:17
我只是重写了您搜索最长子字符串的方式,老实说,我并不完全理解您在代码中尝试了什么,但是从我的perspectiv来看,这是您的内存消失的地方。我还添加了一些内容,你应该看看它们是如何工作的,也遵循你的问题评论中的链接。
在此代码中,子字符串以空格“”或行中断"\n“结尾。
import pickle
import random
def longest_substring(s: str) -> str:
indx = 0
lngth = 0
tmpindx = 0
tmplngth = 0
for i, c in enumerate(s):
if c == " " | c == "\n":
if tmplngth > lngth:
lngth = tmplngth
indx = tmpindx
tmplngth = 0
tmpindx = i + 1
else:
tmplngth += 1
return s[indx: indx + lngth]
with open('de_list_soz.p', 'rb') as o:
de_list_soz = pickle.load(o)
str_seq_list = []
for str_seq in range(0, 100):
# creating random list
random_list = []
for item in range(0, 50):
list_item = random.choice(de_list_soz)
random_list.append(list_item)
# creating long string
long_str = ''
for de in random_list:
with open('txt_sr_de/txt_sr_de/' + de, 'r') as input_file:
text = input_file.read()
text = text.replace('\n', ' ').replace('\xa0', '').replace(' ', '')
# Removing these automated notifications
text = text.replace('Wichtiger Hinweis:Diese Website wird in älteren Versionen von Netscape ohne graphische Elemente dargestellt. Die Funktionalität der Website ist aber trotzdem gewährleistet. Wenn Sie diese Website regelmässig benutzen, empfehlen wir Ihnen, auf Ihrem Computer einen aktuellen Browser zu installieren.Zurück zur Einstiegsseite Drucken Grössere Schrift', '')
text = text.replace('Vorwärts ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
text = text.replace('Bundesgericht Tribunal fédéral Tribunale federale Tribunal federal', '')
text = text.replace('Navigation Neue Suche Zurück zum Suchresultat Rang: Zurück 180', '')
text = text.replace('Navigation Neue Suche Zurück zum Suchresultat Rang:1 ähnliche Leitentscheide suchenähnliche Urteile ab 2000 suchen Drucken nach oben', '')
text = text.replace(' ', ' ')
long_str += text
# here wo go search longest substring
long_sub = longest_substring(long_str)
# here we remove all occurrence of longest substring
no_long_sub_long_str = long_str.replace(long_sub, "")
with open('SOZIALRECHT_DE.p', 'wb') as o:
pickle.dump(str_seq_list, o)https://codereview.stackexchange.com/questions/157132
复制相似问题