我想将大文件放入小文件中。文件中大约有200万个ID,我想按模块对它们进行排序。运行程序时,应询问要分割主文件的文件数。(x = int(input))。我想按模块功能分隔文件。我的意思是,如果ID%x == 1,则应将此ID分别添加到q1和f1。但是它只添加了满足需求的第一行。
import multiprocessing
def createlist(x,i,queue_name):
with open("events.txt") as f:
next(f)
for line in f:
if int(line) % x == i:
queue_name.put(line)
def createfile(x,i,queue_name):
for i in range(x):
file_name = "file{}.txt".format(i+1)
with open(file_name, "w") as text:
text.write(queue_name.get())
if __name__=='__main__':
x= int(input("number of parts "))
i = 0
for i in range(x):
queue_name = "q{}".format(i+1)
queue_name = multiprocessing.Queue()
p0=multiprocessing.Process(target = createlist, args = (x,i,queue_name,))
process_name = "p{}".format(i+1)
process_name = multiprocessing.Process(target = createfile, args = (x,i,queue_name,))
p0.start()
process_name.start()
答案 0 :(得分:0)
您的createfile
有两个功能问题。
parts - 1
个空文件。要解决您的问题,请使createfile
像这样:
def createfile(i, queue_name): # Note: x has been removed from the args
file_name = "file{}.txt".format(i + 1)
with open(file_name, "w") as text:
while True:
if queue.empty():
break
text.write(queue.get())
由于x
已从createfile
的参数中删除,因此您也将从流程实例中删除它:
process_name = multiprocessing.Process(target = createfile, args = (i,queue_name,))
但是...不要这样。所需的子集越多,创建的进程和队列就越多(每个子集两个进程和一个队列)。这是您创建的很多的开销。
虽然每个输出文件都有一个负责任的进程来写可能仍然有意义,但让多个进程完全读取同一个(巨大)文件却没有意义。
我对包含1000行的输入文件做了一些计时和测试,每个文件由0到9999之间的一个随机整数组成。我创建了三种算法,并在跟踪执行时间的同时进行了十次迭代。我对所需数量的1、2、3、4、5和10的子集进行了此操作。对于下图,我采用了每个系列的平均值。
orwqpp(绿色):是每部分一个读写器队列。 您的方法。每增加一个子集,执行时间平均增加0.48秒。
orpp(蓝色):每部分一个读者。这是一个通用的编写器过程,该过程负责写入所有文件。每增加一个子集,执行时间平均增加0.25秒。
of(黄色):是一对一的。一项功能,无需在单独的过程中运行,只需一次即可读写。每增加一个子集,执行时间平均增加0.0014秒。
请记住,这些数字是使用输入文件的1/2000大小创建的。类似于您的方法的过程是如此迅速地完成,彼此之间几乎是相互阻碍的。一旦输入大到足以使进程运行更长的时间,CPU资源的争用就会增加,随着请求更多的子集,拥有更多进程的代价也会增加。
这是一对一的方法:
def one_for_all(parts):
handles = dict({el: open("file{}.txt".format(el), "w") for el in range(parts)})
with open("events.txt") as f:
next(f)
for line in f:
fnum = int(line) % parts
handles.get(fnum).write(line)
[h.close() for h in handles.values()]
if __name__ == '__main__':
x = int(input("number of parts "))
one_for_all(x)
当前,这基于模运算的结果来命名文件,因此int(line) % parts
为0的数字将位于file0.txt
中,依此类推。
如果不希望这样,只需在格式化文件名时加1:
handles = dict({el: open("file{}.txt".format(el+1), "w") for el in range(parts)})