在python中处理大型文本文件

问题描述 投票:0回答:2

我正在处理2个大文件。主文件有2个字段,例如客户名称,第二个字段是客户ID。我有第二个文件,它是第一个文件的子集,只有客户名称。我希望找到子集文件中存在的名称的客户ID。

第一个文件有3000万行,第二个文件有500万行。

我正在尝试使用字典,但它需要花费大量时间。

你能告诉我一个更好的方法吗?

以下是我的代码中的代码段和我文件中的几行代码。

主文件

#

约翰2343245

卡里姆126754

Rob 6543289

维杰2247861

山姆2649860

....

子集第二个文件

他自己

约翰

def extract_info(sub_file,master_file):
    sub_fh = open(sub_file,'r',16777216)
    sub_inst_list = []
    for line in sub_fh:
        if line.startswith('#'):
            continue
        else:
            name = line.rstrip()
            sub_inst_list.append(name)
    sub_fh.close()


out_file = "results.rpt"
outf = open(out_file,'w')
bunchsize = 10000
bunch = []
master_fh = open(master_file,'r',16777216)
for line in master_fh:
    if line.startswith('#'):
        continue
    else:
        data = line.split()
        name = data[0]
        if str(data[1]) == "n/a":
            continue
        else:
            if name in sub_inst_list:
                id = str(data[1])
                line = "%-80s %-15s\n" % (name, id)
                bunch.append(line)
                if len(bunch) == bunchsize: 
                    outf.writelines(bunch)
                    bunch= []
                outf.writelines(bunch)
  master_fh.close()
  outf.close()
python dictionary large-files
2个回答
1
投票

更好的方法是将主文件中的所有数据放入数据库,然后根据第二个文件中的键查找值:

import sqlite3

conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute("CREATE TABLE data (Name VARCHAR(255), ID INT)")

# fill the DB
with open("master.txt") as f:
    for line in f:
        c.execute("INSERT INTO data VALUES (?, ?)", line.split())
conn.commit()

# search for data
with open("slave.txt") as f:
    for line in f:
        print(c.execute("SELECT ID FROM data WHERE Name=:search_name", {"search_name": line.strip()}).fetchall())

conn.close()

0
投票

另一个可能的解决方案(可能比ForceBru慢,但是编码XD很有趣)是使用线程大幅减少时间:

from queue import Queue
from threading import Thread

q = Queue()
number_of_threads = 3


def get_customer_id():
    while True:
        customer_name = q.get()
        with open('Master.txt', 'r') as f:
            for line in f.readlines():
                if customer_name.strip() in line:
                    print(line.strip())
                    break
        q.task_done()


with open('Slave.txt', 'r') as f:
    for line in f.readlines():
        q.put(line)

for i in range(number_of_threads):
    new_thread = Thread(target=get_customer_id)
    new_thread.setDaemon(True)
    new_thread.start()


print('main thread waiting')
q.join()
print('done')

您可以将线程数增加到100-200,然后让它们离开!这将是计算上非常昂贵的,因为你有最近的迭代次数接近125,000,000,000,000最坏情况。这是相当夸张的,因为break声明应该削减大量的迭代。如果它在100个线程中运行,那么你可以将数字从break减少后将其除以100(假设你还没有达到最大CPU使用率,在这种情况下多处理会更好)。尽管用这种方法计算了LOOOOTS。

这基本上就是你的初始脚本正在做的事情,但通过分割和征服来运行它的次数要快很多倍!

© www.soinside.com 2019 - 2024. All rights reserved.