2

Я изучал многопроцессорное программирование в python и различия, которые он имел с многопоточным процессом, и сомнение, которое у меня было, касалось записи в файл. Итак, вот что я нашел, для следующего кода ничего не записывается в файл, что, я думаю, связано с тем, что обработчик открытого файла не разделяется между процессами.Запись в файл на 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() 

Мое сомнение в этом. Является ли «открытый» вызов здесь блокирующим и уже защищенным, или мне нужно реализовать блокировку вокруг вызова «write_to_file»? По сути, будет «открытый» блок вызовов для одного процесса, в то время как файл записывается другим процессом?

ответ

1

Хотя можно скоординировать пишет из нескольких процессов в файл, который одновременно открыл среди них, через замок, возможно, влекущий за собой диапазон блокировки, возможно, влекущим за собой Fsync() и искать() ... в то время как это возможно в большинстве операционных систем и при некоторых условиях ... он также, вероятно, будет подвержен ошибкам, ненадежен и подвержен некоторым нечетным угловым случаям (особенно для файлов, общих в сети, таких как NFS или SMB).

Я предположил бы, что это идеальный случай для использования multiprocessing.Queue класса. Имейте процесс, действуя как потребитель, записывая файл, и все остальные выступают в качестве продюсеров, записывающих в очередь, а не в файл. Это, скорее всего, превзойдет любую стратегию блокировки, которую вы пытаетесь собрать вместе для себя, и это почти наверняка будет намного более надежным.

Смежные вопросы