使用多进程在Python中写入文件

3

我一直在探索Python中的多处理编程以及它与多线程的区别,我对写入文件有疑问。所以这是我发现的,对于下面的代码,没有任何内容被写入文件,我认为这是因为一个打开的文件处理器不能在进程之间共享。

import multiprocessing
import sys
import datetime
import time


def worker(fd, index):
  fd.write("worker %d %s\n" % (index, datetime.datetime.now()))
  time.sleep(5 - index)
  fd.write("worker %d again %s\n" % (index, datetime.datetime.now()))

if __name__ == '__main__':
  fd = open(sys.argv[1], "w")
  threads = list()
  for i in xrange(5):
    th = multiprocessing.Process(target=worker, args=(fd, i,))
    threads.append(th)
    th.start()

  for each in threads:
    each.join()

  fd.close()

以下代码由于线程之间共享内存而可以正常运行。

import threading
import sys
import datetime


def worker(fd, index):
  fd.write("worker %d %s\n" % (index, datetime.datetime.now()))
  time.sleep(5 - index)
  fd.write("worker %d again %s\n" % (index, datetime.datetime.now()))

if __name__ == '__main__':
  fd = open(sys.argv[1], "w")
  threads = list()
  for i in xrange(5):
    th = threading.Thread(target=worker, args=(fd, i,))
    threads.append(th)
    th.start()

  for each in threads:
    each.join()

  fd.close()

我希望使用多进程而不是线程来写入同一个文件,所以我实现了以下代码。我假设可能需要使用锁来限制不同进程对文件的访问,但是下面的代码似乎可以正常工作而无需使用锁定。
import multiprocessing
import sys
import datetime
import time


def write_to_file(text, file_name):
  fd = open(file_name, "a")
  fd.write(text)
  fd.close()


def worker(file_name, index):
  while True:
    write_to_file("worker %d %s\n" % (index, datetime.datetime.now()), file_name)
    time.sleep(5 - index)
    write_to_file("worker %d %s again\n" % (index, datetime.datetime.now()), file_name)


if __name__ == '__main__':
  file_name = sys.argv[1]
  fd = open(file_name, 'w')
  fd.write("test input\n")
  fd.close()
  jobs = []
  for i in xrange(5):
    process = multiprocessing.Process(target=worker, args=(file_name, i,))
    process.start()
    jobs.append(process)

  for j in jobs:
    j.join()

我的疑问是关于这个的。这里的“open”调用是阻塞且已经受保护,还是我需要在对“write_to_file”的调用周围实现锁定?本质上,当另一个进程正在写入文件时,“open”调用是否会阻塞一个进程?

1个回答

1
虽然在多个进程之间协调对一个同时被打开的文件进行写入是可能的,通过锁定,可能涉及范围锁定,可能涉及fsync()和seek()...虽然这在大多数操作系统下和某些条件下是可能的...但很可能容易出错,不可靠,并且会受到一些奇怪的边缘情况的影响(尤其是对于跨网络共享的文件,如NFS或SMB)。
我建议这是使用multiprocessing.Queue类的完美案例。让一个进程充当消费者,向文件写入内容,而让所有其他进程充当生产者,将内容写入队列而不是文件。这将很可能优于您尝试自己拼凑的任何锁定策略,并且几乎肯定更加健壮。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接