使用python读取大量文本文件的有效方法

时间:2020-05-24 05:33:12

标签: python file

我在子目录中有大约20000个文档。我想全部阅读它们,并将它们附加为一个列表列表。到目前为止,这是我的代码,

topics =os.listdir(my_directory)
df =[]
for topic in topics:
    files = os.listdir (my_directory+ '/'+ topic)
    print(files)

    for file in files: 
        print(file)
        f = open(my_directory+ '/'+ topic+ '/'+file, 'r', encoding ='latin1')
        data = f.read().replace('\n', ' ')
        print(data)
        f.close()
    df = np.append(df, data)

但是这效率低下,读取它们并将它们附加到df列表中需要花费很长时间。我的预期输出是

 df= [[doc1], [doc2], [doc3], [doc4],......,[doc20000]]

我运行了上面的代码,花了6个小时以上,但仍未完成(可能是文档的一半)。如何更改代码以使其更快?

3 个答案:

答案 0 :(得分:1)

您只能做很多事情来加快磁盘访问速度。您可以使用线程通过latin1解码和换行符来重叠某些文件读取操作。但实际上,不会有太大的不同。

import multiprocessing.pool

MEG = 2**20
filelist = []

topics =os.listdir(my_directory)
for topic in topics:
    files = os.listdir (my_directory+ '/'+ topic)
    print(files)

    for file in files: 
        print(file)
        filelist.append(my_directory+ '/'+ topic+ '/'+file)

def worker(filename):
    with open(filename, encoding ='latin1',  bufsize=1*MEG) as f:
        data = f.read().replace('\n', ' ')
        #print(data)
        return data

with multiprocessing.pool.ThreadPool() as pool:
    datalist = pool.map(worker, filelist, chunksize=1)
df = np.array(datalist)

答案 1 :(得分:0)

生成器函数使您可以声明行为类似于 一个迭代器,即可以在for循环中使用。

generators

lazy function generator

def read_in_chunks(file, chunk_size=1024):
    """Lazy function (generator) to read a file piece by piece.
    Default chunk size: 1k."""
    while True:
        data = file.read(chunk_size)
        if not data:
            break
        yield data


with open('big_file.dat') as f:
    for piece in read_in_chunks(f):
        process_data(piece)

class Reader(object):
    def __init__(self, g):
        self.g = g
    def read(self, n=0):
        try:
            return next(self.g)
        except StopIteration:
            return ''

df = pd.concat(list(pd.read_csv(Reader(read_in_chunks()),chunksize=10000)),axis=1)
df.to_csv("output.csv", index=False)

答案 2 :(得分:0)

注意

我误读了行df = np.append(df, data),并假定您要追加到DataFrame,而不是numpy数组。因此,我的评论有点无关紧要,但我会将其留给其他人,让我像我一样误读或对熊猫的DataFrame追加有类似的问题。


实际问题

看来您的问题可能无法真正解决您的实际问题。 您是否测量了两个最重要的通话的效果?

  • files = os.listdir (my_directory+ '/'+ topic)
  • df = np.append(df, data)

格式化代码的方式使我认为存在一个错误:df = np.append(df, data)在文件的for循环范围之外,因此我认为只有最后一个data被附加到数据框。如果这只是帖子中代码格式化的问题,而您确实确实将20k文件追加到数据框中,则可能是问题所在-追加到DataFrame很慢。

潜在解决方案

像往常一样,可以通过在问题上投入更多的内存来解决性能下降的问题。如果您有足够的内存来预先加载all个文件,然后再将其插入DataFrame中,则可能会更快。

关键是在加载所有数据之前不要处理任何熊猫操作。只有这样,您才能使用DataFrame的{​​{3}}或其其他工厂方法之一。

一个很好的SO问题,我发现了更多讨论: from_records

TL; DR

  1. 测量读取所有文件而不用处理熊猫的时间
  2. 如果事实证明它要快得多 ,则您有足够的内存来一次加载所有文件的内容,请使用另一种方式来构建DataFrame ,说DataFrame.from_records