编辑:
我需要帮助将下面的代码(尤其是列表)转换为生成器,以便我可以在计算机上保存内存。
我将doclist转换为可迭代对象,并删除了slist和seuslist,之前是一个很大的名称列表。 https://www.jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/
seuslist1 = open('/Users/AJ/Desktop/Dropbox/DOS_Python/docs/US/socialentrepreneurship_US_list.txt', mode= 'r+')
seuslist = seuslist1.read()
slist = seuslist.split('\n')
slist = slist[:len(slist)-1] #I have to take out the last entry because of a weird space. Also explore using OSwalk later.
#I switched to just using a list of docs because it's easier to deal with than a dictionary
doclist = []
for i, doc in enumerate(slist):
string = 'docs/US/', doc
string = ''.join(string)
doclist.append(open(string, mode='r+').read())
#clear these variables to free up memory. Turn doclist into an generator object to save memory.
doclist = iter(doclist)
del seuslist
del slist
seuslist1.close()
答案 0 :(得分:0)
尝试类似:
main_file = '/Users/AJ/Desktop/Dropbox/DOS_Python/docs/US/socialentrepreneurship_US_list.txt'
def data_from_file_generator():
with open(main_file, mode= 'r+') as path_file:
for my_path in path_file:
with open("docs/US/" + my_path, mode='r+') as data_file:
yield data_file.read()
答案 1 :(得分:0)
正如您所指出的,您的基本问题是您将所有这些文件的所有内容保存在一个庞大的列表中。幸运的是,将该列表转换为生成器非常简单。为了保持可读性和Pythonic,我们将doclist
重命名为docs
,因为它不再是列表。
# Use a generator expression to quickly create a generator.
# This will iterate over ever entry in slist.
# For each entry: build the path, open the file, read it, and yield the contents
docs = (open(path).read() for path in ('docs/US/'+entry for entry in slist))
for doc in docs:
print(len(doc)) # Do something useful here.
使用这样的生成器时要记住几件事。
首先,它会帮助你解决内存问题,因为你一次只能在内存中存储一个文件的内容(除非你将它存储在其他地方,但由于上述内存问题,这可能是一个坏主意)。
其次,仅当迭代(for doc in docs
)进行到下一步时才加载每个文件。这意味着如果您的进程在每次迭代中花费很长时间(或者即使它没有),您也可以在进程运行时修改文件,无论好坏。
第三,这里的生成器表达式并不是最强大的东西,因为你已经进行了那些裸open
次调用,其中任何一个都可以抛出异常并终止你的剩余处理。为了使它更加坚固,你需要编写一个像Calpratt's answer这样的实际生成器函数,这样你就可以使用上下文管理器,基于每个文件包装异常,等等。
最后,请记住,生成器只能按原样使用一次!一旦你筋疲力尽,它就完成了。这通常很好,但您需要确保在第一次提取所需的所有信息(此外,您不希望反复重读所有这些文件!)。