在python中使用线程时如何保留文件写入顺序

How to preserve file write order when using threading in python

我有一些python代码来读取文件并将数据推送到列表中。然后把这个列表放到队列中,使用线程处理这个列表,比如说一次20个项目。处理后,我将结果保存到一个新文件中。放入新文件的顺序实际上与原始文件的顺序不同。例如,我输入了,

1
2
3
4
5
    1    a
    2    b
    3    c
    4    a
    5    d

但是输出看起来是:

1
2
3
4
5
    2    aa
    1    ba
    4    aa
    5    da
    3    ca

有没有办法保留原来的订单?这是我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    import threading,Queue,time,sys
    class eSS(threading.Thread):
        def __init__(self,queue):
            threading.Thread.__init__(self)
            self.queue = queue
            self.lock = threading.Lock()
        def ess(self,email,code,suggested,comment,reason,dlx_score):
            #do something
        def run(self):
            while True:
                info = self.queue.get()
                infolist = info.split('\t')
                email = infolist[1]
                code = infolist[2]
                suggested = infolist[3]
                comment = infolist[4]
                reason = infolist[5]
                dlx_score = (0 if infolist[6] == 'NULL' else int(infolist[6]))
                g.write(info + '\t' + self.ess(email,code,suggested,comment,reason,dlx_score) +'

'
)
                self.queue.task_done()

    if __name__ =="__main__":
        queue = Queue.Queue()
        filename = sys.argv[1]
        #Define number of threads
        threads = 20
        f = open(filename,'r')
        g = open(filename+'.eSS','w')
        lines = f.read().splitlines()
        f.close()
        start = time.time()
        for i in range(threads):
            t = eSS(queue)
            t.setDaemon(True)
            t.start()
        for line in lines:
            queue.put(line)    
        queue.join()
        print time.time()-start
        g.close()


我想到了三个想法。对所有人来说,常见的做法是将索引与排队等待处理的数据包一起包含在一起。

  • 一种想法是使用控制器/工人/输出框架,在这个框架中,输出线程对工人处理的数据进行去队列、组装和输出。
  • 第二种想法是使用内存映射文件进行输出,并使用索引计算写入文件的偏移量(假设写入的长度可能是固定的)。
  • 第三种方法是使用索引将处理过的数据放入一个新的列表中,当列表完成时,在末尾而不是在运行中写出项目。