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

基于Uniprot REST API批量URL请求的Python代码提速方案咨询

可行!并行请求Uniprot API完全能提速,你的ThreadPoolExecutor用法有优化空间

首先明确:网络IO密集型任务(比如API请求)本来就是ThreadPoolExecutor的强项,GIL在这类场景下几乎不会影响性能——因为线程大部分时间都在等待网络响应,而非占用CPU。你觉得提速效果差,大概率是代码里的并发策略、数据格式选择这些细节拖了后腿。

核心优化方向

  • 别拆分请求子集:你现在把链接分成8个子集逐个处理,等于人为限制了并发数,直接一次性提交所有请求到线程池才能最大化并行效率。
  • 换掉Excel格式:Uniprot返回的Excel解析成本极高,换成TSV或JSON格式,解析速度能提升数倍。
  • 调优线程数:默认线程数是CPU核心数的5倍,网络任务可以拉到20-50(注意别超过Uniprot的API请求限制,避免被限流)。
  • 加重试和超时:网络波动会导致请求失败,加重试逻辑能减少无效跳过,超时设置能避免线程一直挂起。
  • 线程安全处理共享变量:skipped_genes是多线程共享列表,需要加锁避免数据混乱。
  • 优化DataFrame拼接:别用已过时的append,用pd.concat一次性合并所有结果,效率更高。

修改后的代码

import pandas as pd
import requests as req
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import warnings
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
import time
import datetime
import threading

# 警告屏蔽
warnings.filterwarnings("ignore", message="Workbook contains no default style")

# 初始化带重试的requests会话,复用连接+自动重试
session = req.Session()
retry_strategy = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[429, 500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)

# 读取原始文件
file_path = 'FindAllMarkers.xlsx'
raw_df = pd.read_excel(file_path)
print(raw_df.head(10))
print(f"Number of clusters: {raw_df['cluster'].nunique()} (including 0)")

# 提取唯一基因
unique_genes = raw_df['gene'].unique()
skipped_genes = []
lock = threading.Lock()  # 线程锁保护共享列表,避免多线程写入混乱

# 生成Uniprot查询链接(改用TSV格式,解析更快;size设为1,只请求首个结果)
def get_UniPQuery_link(gene_name, tax_id='9606', file_format='tsv'):
    url = (f"https://rest.uniprot.org/uniprotkb/stream?fields=accession%2Creviewed%2Cid%2Cprotein_name%2Cgene_names%2Corganism_name%2Clength%2Cft_intramem%2Ccc_subcellular_location%2Cft_topo_dom%2Cft_transmem%2Ccc_function%2Clit_doi_id%2Clit_pubmed_id"
           f"&format={file_format}&size=1&query=%28%28gene%3A{gene_name}%29+AND+%28taxonomy_id%3A{tax_id}%29%29")
    return url

UP_links = [get_UniPQuery_link(gene) for gene in unique_genes]

# 单链接处理函数
def process_link(link):
    try:
        # 设置超时时间,避免线程长时间挂起
        response = session.get(link, timeout=10)
        response.raise_for_status()  # 触发HTTP错误异常
        
        # 解析TSV格式,比Excel快很多
        raw_file_df = pd.read_csv(req.utils.urlopen(link), sep='\t')
        if raw_file_df.empty:
            with lock:
                skipped_genes.append(link)
            return None
        return raw_file_df.iloc[[0]]
    except Exception as e:
        with lock:
            skipped_genes.append(link)
        print(f"Failed to process link {link}: {str(e)}")
        return None

# 批量处理所有链接
start_time = time.time()
start_date_time = datetime.datetime.now()

processed_data = []
# 设置线程数为30,可根据网络情况和API限制调整
with ThreadPoolExecutor(max_workers=30) as executor:
    # 用tqdm跟踪处理进度
    for result in tqdm(executor.map(process_link, UP_links), total=len(UP_links)):
        if result is not None:
            processed_data.append(result)

# 一次性合并所有结果,替代低效的append
final_dataframe = pd.concat(processed_data, ignore_index=True)
final_dataframe.to_excel('./gene_info.xlsx', index=False, engine='openpyxl')

# 输出统计信息
end_date_time = datetime.datetime.now()
elapsed_time = end_time - start_time
hours = int(elapsed_time // 3600)
minutes = int((elapsed_time % 3600) // 60)
seconds = int(elapsed_time % 60)

print(f"Start Date and Time: {start_date_time}")
print(f"End Date and Time: {end_date_time}")
print(f"Execution time: {hours} hours, {minutes} minutes, {seconds} seconds")
print(f"Skipped genes count: {len(skipped_genes)}")
print(f"Skipped genes: {skipped_genes}")

额外说明

  • 把size=500改成size=1:你只需要首个结果,没必要请求冗余数据,减少传输量和解析时间。
  • 用requests.Session复用连接:避免每次请求都建立新TCP连接,大幅提升请求效率。
  • 全面异常捕获:覆盖网络超时、HTTP错误等多种场景,减少不必要的基因跳过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:11:00