Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用python将线程安全写入文件_Python - Fatal编程技术网

用python将线程安全写入文件

用python将线程安全写入文件,python,Python,如何将数据写入Python线程安全的文件? 我想为每个请求和每个小时将一些变量保存到一个文件中,我想进行一些分组并将其写入mysql 在Java中,我现在将它放入一个缓存的数组中,当数组已满时,它将被写入一个文件中 如何在Python中实现这一点?有许多并发请求,因此它必须是线程安全的 编辑: 我们最终使用了工作正常的日志模块。看看队列类,它是线程安全的 from Queue import Queue writeQueue = Queue() 在线程中 writeQueue.put(repr(

如何将数据写入Python线程安全的文件? 我想为每个请求和每个小时将一些变量保存到一个文件中,我想进行一些分组并将其写入mysql

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

如何在Python中实现这一点?有许多并发请求,因此它必须是线程安全的

编辑:


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

看看
队列
类,它是线程安全的

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、列表、数字和dict,并且比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!"]

我们使用了日志模块:

import logging

logpath = "/tmp/log.log"
logger = logging.getLogger('log')
logger.setLevel(logging.INFO)
ch = logging.FileHandler(logpath)
ch.setFormatter(logging.Formatter('%(message)s'))
logger.addHandler(ch)


def application(env, start_response):
   logger.info("%s %s".format("hello","world!"))
   start_response('200 OK', [('Content-Type', 'text/html')])
   return ["Hello!"]

我制作了一个简单的编写器,它使用
线程
队列
,可以很好地处理多个线程。优点:实际上,它可以从多个进程接收数据而不阻塞它们,并在其他线程中异步写入。缺点:额外的线程写入会消耗资源;在CPython
中,线程化不能提供真正的多线程

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 = SafeWriter("filename", "w")
w.write("can be used among multiple threads")
w.close() #it is really important to close or the program would not end 

你的意思是“线程安全”吗?为什么不在运行时将行写入MySQL,让它的并发性处理这些行,然后聚合这些行,然后执行必要的操作呢?锁定、排队和各种操作都是可能的,但更容易将它们扔到服务器上,聚合到那里,或者在cronjob或类似的操作中,在服务器中聚合并插入聚合,或者从客户端拉回数据、聚合并插入…日志记录模块是线程安全的。您可以使用它从不同的线程写入文件。@JonClements写入mysql是我想要阻止的。这需要大量的资源,因为它每秒会收到大约300个请求。感谢这个例子,但是,队列如何仍然存在于不同的请求上呢?我认为每当python脚本(或任何脚本语言)完成时,都不可能使用来自上一个请求的任何对象/变量等?好的,这取决于请求的确切含义。当解释器退出时,它使用的所有东西都将得到GCed,因此有两个选项来处理这个问题。首先,是不让解释器退出,如果您谈论的是线程安全,大多数人会认为您有某种持续运行的守护进程,可以在请求之间保持状态。如果您的意思是需要多个进程(解释器的副本)并行运行,并且需要避免混合写入,那么OS级别的锁文件就是解决方案。我也将用它来扩展我的示例。对于线程安全,我指的是混合写入。顺便说一句,我正在使用Linux。我认为锁定和解锁文件的时间/资源太多了。我们在Java中所做的是在每次请求后将字符串写入内存中的数组,当数组已满时,将创建一个新数组,并将旧数组写入文件。根据请求的数量,我们可以增加/减少数组的大小(默认值为1000)。Java会遇到与python在JVM退出时对数组进行GCed相同的问题,因此它必须在请求之间保持不变。我建议对python也这样做,并使用队列。如果每次生成请求时都必须启动新的解释器,则使用第二个进程并通过lo接口将数据传递给解释器。请求是如何生成的?你在使用什么框架?我们不使用任何框架。我想使用nginx+gunicorn。我只编写了单个.py脚本文件。您能否给出一个示例代码,当队列为1000大时,“hello world”被放入队列并写入文件?+1用于滥用
日志记录
以线程方式安全地将行写入文件,我有时会这样做。有一些必需的样板文件和对日志如何工作的理解,但不重新发明轮子是很好的。