我正在尝试写入多处理(4 个内核/进程(的结果。由于CPU内核同时工作,我想制作4个文件,0.txt
,1.txt
,2.txt
和3.txt
,并将其保存在multiprocessing.Manager().list()
中。但是我得到了错误,TypeError: cannot serialize '_io.TextIOWrapper' object
.
def run_solver(total, proc_id, result, fouts):
for i in range(10)):
fouts[proc_id].write('hin')
if __name__ == '__main__':
processes = []
fouts = Manager().list((open('0.txt', 'w'), open('1.txt', 'w'), open('2.txt', 'w'), open('3.txt', 'w')))
for proc_id in range(os.cpu_count()):
processes.append(Process(target=run_solver, args=(int(total/os.cpu_count()), proc_id, result, fouts)))
for process in processes:
process.start()
for process in processes:
process.join()
for i in range(len(fouts)):
fouts[i].close()
我也尝试在函数中使用文件句柄填充列表,如下所示。
def run_solver(total, proc_id, result, fouts):
fout[proc_id] = open(str(proc_id)+'.txt', 'w')
for i in range(10)):
fouts[proc_id].write('hin')
fout[proc_id].close()
if __name__ == '__main__':
processes = []
fouts = Manager().list([0]*os.cpu_count())
两者都不起作用,我知道有一些与无法序列化或不可腌制有关的事情。但我不知道如何解决这个问题。有人可以提出解决方案吗?
打开每个进程中的文件。不要在管理器中打开它们,您无法将打开的文件从管理器进程发送到执行程序进程。
def run_solver(total, proc_id, result, fouts):
with open(fouts[proc_id], 'w') as openfile:
for i in range(10)):
openfile.write('hin')
if __name__ == '__main__':
processes = []
with Manager() as manager:
fouts = manager.list(['0.txt', '1.txt', '2.txt', '3.txt'])
for proc_id in range(os.cpu_count()):
processes.append(Process(
target=run_solver, args=(
int(total/os.cpu_count()), proc_id, result, fouts)
))
如果要在进程之间共享文件名,则希望在写入这些文件时防止争用条件,则确实希望对每个文件使用锁定:
def run_solver(total, proc_id, result, fouts, locks):
with open(fouts[proc_id], 'a') as openfile:
for i in range(10)):
with locks[proc_id]:
openfile.write('hin')
openfile.flush()
if __name__ == '__main__':
processes = []
with Manager() as manager:
fouts = manager.list(['0.txt', '1.txt', '2.txt', '3.txt'])
locks = manager.list([Lock() for fout in fouts])
for proc_id in range(os.cpu_count()):
processes.append(Process(
target=run_solver, args=(
int(total/os.cpu_count()), proc_id, result, fouts, locks
)
))
由于文件是用with
打开的,因此它们每次都会自动关闭,并且它们以追加模式打开,因此不同的进程不会相互干扰。您需要记住在再次解锁之前刷新写入缓冲区。
顺便说一句,您可能希望查看进程池,而不是执行自己的手动池。