multiprocess.Process并发执行时golang输出CSV文件相互覆盖问题求助
方案1:按间隔启动进程(临时解决方案)
你只需要在启动每个进程后加入1-2秒的休眠即可,修改dispatch_jobs函数的启动逻辑,同时导入time模块:
import multiprocessing import subprocess import time # 新增导入 def chunks(l, n): # split a list into evenly sized chunks return [l[i:i+n] for i in range(0, len(l), n)] def run_golang(job_id, data_slice): ''' Takes a string of ids, feeds it into a golang API script and returns a csv file of output data ''' str_slice = ','.join(str(i) for i in data_slice) p = subprocess.Popen('./golang --ids={}'.format(str_slice) , shell=True , stdout=subprocess.PIPE , stderr=subprocess.STDOUT) # 其余原有逻辑保持不变 def dispatch_jobs(data, job_number): total = len(data) chunk_size = total / job_number slices = chunks(data, int(chunk_size)) # 原变量名slice是Python内置函数,建议改名避免冲突 jobs = [] for i, s in enumerate(slices): j = multiprocessing.Process(target=run_golang, args=(i, s)) jobs.append(j) for j in jobs: j.start() time.sleep(2) # 启动后等待2秒再启动下一个进程 if __name__ == "__main__": data = [12, 34, 56, 78, 910, 1112] dispatch_jobs(data, 2)
这个方案可以快速解决你当前的文件名冲突问题,但是有两个潜在问题:
- 如果进程启动后golang脚本执行延迟,仍有可能出现同秒生成文件导致覆盖
- 进程数量多的时候,总启动等待时间会很长,牺牲了多进程的并发效率
方案2:从根源避免文件名冲突(推荐方案)
文件名冲突的核心原因是golang脚本仅用时分秒作为唯一标识,并发场景下必然会出现重名。建议调整调用逻辑,给每个进程的输出文件指定唯一名称:
- 改造golang脚本,新增
--output参数支持传入自定义输出文件路径 - 在
run_golang函数中传入带job_id的唯一文件名,示例修改如下:
def run_golang(job_id, data_slice): str_slice = ','.join(str(i) for i in data_slice) # 生成唯一文件名,带上job_id完全避免重名 output_filename = f"filename_job{job_id}.csv" p = subprocess.Popen( # 新增--output参数传给golang脚本 f'./golang --ids={str_slice} --output={output_filename}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) # 其余原有逻辑保持不变
这个方案不需要调整进程启动间隔,完全保留多进程的并发效率,也不会出现文件覆盖的问题。
额外优化建议
- 拆分分片时如果总长度不能被进程数整除,最后一个分片的长度会比其他分片小,如果需要均匀分配可以调整分片逻辑
- 尽量避免使用
shell=True参数,可以把命令拆分为列表形式传入Popen,避免潜在的命令注入风险
内容的提问来源于stack exchange,提问作者dyao
相关产品推荐
相关产品推荐

