You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将字典传递给concurrent.futures执行器,解决多进程下全局字典无写入问题

问题根本原因

你使用的ProcessPoolExecutor是多进程实现,每个子进程拥有独立的内存地址空间,主进程定义的全局data字典和子进程里的data是完全独立的两份拷贝,子进程对字典的修改只会作用在子进程自身的内存中,不会同步到主进程,所以最终主进程打印的data是空的。

解决方案

不需要用全局变量传递结果,改为让任务函数返回计算结果,主进程收集所有返回值后组装成字典即可,修改逻辑如下:

  • 调整shan函数,删除修改全局data的逻辑,改为返回文件名和对应的计算结果
  • 将子进程需要用到的samples变量作为参数传入shan函数(原代码中子进程无法直接读取主进程的samples全局变量,会触发未定义报错)
  • 主进程遍历所有执行完成的future,取出返回值写入主进程的data字典
修改后的可运行代码示例
import collections
import gzip
import sys
import glob
import concurrent.futures
from scipy.stats import entropy
from Bio import SeqIO

# 原熵计算函数无需修改
def estimate_shannon_entropy(dna_sequence):
    bases = collections.Counter([tmp_base for tmp_base in dna_sequence])
    dist = [x/sum(bases.values()) for x in bases.values()]
    entropy_value = entropy(dist, base=2)
    return entropy_value

# 修改shan函数:新增samples参数,返回键值对而非修改全局变量
def shan(i, samples):
    name1 = i.split("/")[-1]
    ext1 = name1.split(".")[-1]
    print(name1)
    
    if ext1 == "gz":
        f = gzip.open(i, 'rt')
        k = name1.split(".")[-2]
    else:
        f = open(i, 'r')
        # 修复原代码ext未定义的问题
        k = ext1
    
    if k[-1] == "a":
        fmt = "fasta"
    if k[-1] == "q":
        fmt = "fastq"
    
    c = 0
    shannon_total = 0
    for x in SeqIO.parse(f, fmt):
        c += 1
        if c <= samples:
            shannon = estimate_shannon_entropy(str(x.seq))
            shannon_total += shannon
        
    ans = float(shannon_total / samples)
    return name1, ans

if __name__ == "__main__":
    folder = sys.argv[1] 
    filelist = glob.glob(folder)
    # 保留你原有的tokenize排序逻辑即可
    filelist.sort(key=tokenize)
    
    samples = int(sys.argv[2])
    threads = int(sys.argv[3])
    data = {}

    executor = concurrent.futures.ProcessPoolExecutor(threads)
    # 提交任务时显式传入samples参数
    futures = [executor.submit(shan, i, samples) for i in filelist]
    concurrent.futures.wait(futures)
    
    # 收集所有子进程返回的结果,写入主进程的data字典
    for future in futures:
        name, res = future.result()
        data[name] = res
    
    print(data)
额外注意事项
  • 多进程代码的入口必须加if __name__ == "__main__":防护,否则Windows系统下会无限递归启动进程报错
  • 不要在多进程场景下依赖全局变量传递状态/结果,所有子进程需要的参数都应该显式传入,结果都应该显式返回

内容的提问来源于stack exchange,提问作者suze1992

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 21:45:05