在python中将线程安全写入文件

时间:2015-05-09 01:44:21

标签: python

如何在Python线程安全的情况下将数据写入文件? 我想为每个请求保护一些变量到一个文件,每小时我想做一些分组并将它写入mysql。

在Java中,我现在把它放在一个缓存的数组中,当数组已满时将其写入文件。

我怎样才能在Python中执行此操作?有许多并发请求因此必须是线程安全的。

编辑:

我们最终使用的日志模块工作正常。

3 个答案:

答案 0 :(得分:6)

查看Queue类,它是线程安全的。

from Queue import Queue
writeQueue = Queue()

在线程中

writeQueue.put(repr(some_object))

然后将其转储到文件

outFile = open(path,'w')
while writeQueue.qsize():
  outFile.write(writeQueue.get())
outFile.flush()
outFile.close()

Queue将接受任何python对象,因此如果您尝试执行除打印到文件之外的其他操作,只需通过Queue.put存储工作线程中的对象。

如果需要跨脚本的多个调用拆分提交,则需要一种方法将部分构建的提交缓存到磁盘。要避免多个副本同时尝试写入文件,请使用可通过pip获得的lockfile模块。我通常使用json为这些目的编码数据,它支持序列化字符串,unicode,列表,数字和dicts,并且比pickle更安全。

with lockfile.LockFile('/path/to/file.sql'):
  fin=open('/path/to/file')
  data=json.loads(fin.read())
  data.append(newdata)
  fin.close()
  fout=open('/path/to/file','w')
  fout.write(json.dumps(data))
  fout.close()

请注意,根据操作系统功能,锁定和解锁文件以及为每个请求重写文件所花费的时间可能比您预期的要多。如果可能的话,尝试只追加到文件,因为这会更快。此外,您可能希望使用客户端/服务器模型,其中每个请求'启动一个工作脚本,该脚本连接到服务器进程并通过网络套接字转发数据。这避免了对锁定文件的需求;根据您正在谈论的数据量,它可能能够将其全部保存在服务器进程的内存中,或者服务器可能需要将其序列化到磁盘并以此方式将其传递给数据库。

WSGI服务器示例:

from Queue import Queue
q=Queue()
def flushQueue():
    with open(path,'w') as f:
       while q.qsize():
           f.write(q.get())

def application(env, start_response):
   q.put("Hello World!")
   if q.qsize() > 999:
       flushQueue()
   start_response('200 OK', [('Content-Type', 'text/html')])
   return ["Hello!"]

答案 1 :(得分:4)

我们使用了日志记录模块:

var mission = "";
setInterval( function() { 
    mission = " some string ";
    $("#mission").html(mission);
}, 250);
$("#mission").html(mission);

答案 2 :(得分:1)

我创建了一个简单的编写器,它使用threadingQueue,可以在多个线程中正常工作。优点:teoreticaly它可以从多个进程中获取数据而不会阻塞它们,并在其他线程中编写asynconiosly。缺点:写作的额外线程消耗资源;在CPython中threading没有提供真正的多线程。

from Queue import Queue, Empty
from threading import Thread

class SafeWriter:
    def __init__(self, *args):
        self.filewriter = open(*args)
        self.queue = Queue()
        self.finished = False
        Thread(name = "SafeWriter", target=self.internal_writer).start()  

    def write(self, data):
        self.queue.put(data)

    def internal_writer(self):
        while not self.finished:
            try:
                data = self.queue.get(True, 1)
            except Empty:
                continue    
            self.filewriter.write(data)
            self.queue.task_done()

    def close(self):
        self.queue.join()
        self.finished = True
        self.filewriter.close()

#use it like ordinary open like this:
w = SimpleWriter("filename", "w")
w.write("can be used among multiple threads")
w.close() #it is really important to close or the program would not end