我有大约1000万个条目要处理。当前,我逐项检查条目并运行一个子例程,例如,当处理1000个条目时,我打开一个csv文件并将结果保存到其中。
for num, i in enumerate (some iterator)
function(i)
if num is multiple of 1000
open file and save
在利用队列和线程处理时如何保存部分?现在,我将10个工厂条目放入队列中,并启动线程以运行该子例程。可以,但是我不能把头放在保存部分上。
put all entries in queue
for i in number of threads
run function
start thread
答案 0 :(得分:0)
几件事。您将希望每个线程写入一个单独的文件,然后在最后合并文件。使用锁定机制可以起作用,但可能会导致您的应用程序性能回到单个线程,具体取决于您写入CSV的次数。
此处提供了一个创建池和队列的出色教程:
https://www.metachris.com/2016/04/python-threadpool/
并且:
Threading pool similar to the multiprocessing Pool?
最后,您将需要合并文件(如果需要),最好是在操作系统级别执行此操作,但是在python中,您可以执行以下操作:
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for fname in filenames:
with open(fname) as infile:
for line in infile:
outfile.write(line)
答案 1 :(得分:0)
这是假设您已经设置了所有其他线程
在初始化线程的地方,需要创建一个线程锁定对象
threadLock = threading.Lock()
然后在您正在编写的函数中执行以下操作:
for num, i in enumerate (some iterator)
function(i)
if num is multiple of 1000
threadLock.acquire()
#open file with an append
#save
#close file
threadLock.release()
threadLock.acquire()
可能需要放在if语句之前
在其他线程上锁定代码的某些部分或访问共享变量(如文件)时,它们“关门”,而另一个线程已经在使用它时,它们必须等待转过那扇门
答案 2 :(得分:0)
使用"secret sauce" of CPython threading-队列!
写入文件本质上是顺序的,因此您最好将一个线程负责所有编写。 让所有辅助线程将其结果推送到公共输出队列。 从此输出队列中读取单个编写器线程,然后 每隔1000个条目或在所有辅助线程完成后再写入csv。
通过这种方式,您可以避免需要锁定或之后合并部分文件的麻烦。
这是我建议的基本结构。它创建2500个条目,使它们具有5个线程,并在每10个结果之后输出:
import queue
import threading
SENTINEL = None
def worker(in_queue, out_queue):
for n in iter(in_queue.get, SENTINEL):
# print('task called: {n}'.format(n=n))
out_queue.put(n*2)
def write(out_queue, chunksize=10):
results = []
for n in iter(out_queue.get, SENTINEL):
results.append(n)
if len(results) >= chunksize:
print(results)
results = []
if len(results):
# SENTINEL signals the worker threads are done.
# print the remainder of the results
print(results)
in_queue = queue.Queue()
out_queue = queue.Queue()
num_threads = 5
N = 2500
for i in range(N):
in_queue.put(i)
for i in range(num_threads):
# ad a SENTINEL to tell each worker to end
in_queue.put(SENTINEL)
writer = threading.Thread(target=write, args=(out_queue,))
writer.start()
threads = [threading.Thread(target=worker, args=(in_queue, out_queue))
for n in range(num_threads)]
for t in threads:
t.start()
for t in threads:
t.join()
# tell the writer to end
out_queue.put(SENTINEL)
writer.join()
可打印
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38]
[40, 42, 44, 46, 48, 50, 52, 54, 56, 58]
...
[4940, 4942, 4944, 4946, 4948, 4950, 4952, 4954, 4956, 4958]
[4960, 4962, 4964, 4966, 4968, 4970, 4972, 4974, 4976, 4978]
[4980, 4982, 4984, 4986, 4988, 4990, 4992, 4994, 4996, 4998]
请注意,打印的值可能不会按排序顺序显示。这取决于并发线程将结果推入out_queue
的顺序。