Python3 argparse参数处理报错:Args.__new__()缺失必填位置参数'dell'
Python3 argparse参数处理报错:Args.new()缺失必填位置参数'dell'
看起来你遇到的问题根源在于NamedTuple的定义和参数处理逻辑不匹配,咱们一步步拆解问题并修复:
问题分析
- NamedTuple字段定义错误:你定义的
Args类包含三个必填字段rna、ins、dell,但你的需求里ins和dell是可选参数,必须给这两个字段设置默认值,否则实例化Args时必须传入所有三个参数,哪怕用户没指定部分可选参数。 - get_args()分支逻辑遗漏场景:当用户同时传入
--ins和--dell时,你的代码没有对应的分支处理,会进入某个不完整的分支(比如elif args.rna and args.ins),只传递rna和ins,导致缺少dell参数引发报错。 - argparse的--ins参数配置错误:
type=list在argparse中无法正确解析你传入的'4 T',因为type是用来转换单个参数的类型,你需要用nargs='+'来接收多个参数值。
解决方案与修复后的代码
下面是修复后的完整代码,我标注了关键修改点:
#!/usr/bin/env python3 import argparse from typing import NamedTuple, Dict, List, Optional import csv # 1. 给可选字段设置默认值为Optional类型的None class Args(NamedTuple): rna: str ins: Optional[List] = None # 可选参数,默认None dell: Optional[int] = None # 可选参数,默认None def get_args() -> Args: parser = argparse.ArgumentParser(description='translating mRNA', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('rna', metavar='RNA seq', type=str) # 2. 修正--ins的配置,用nargs='+'接收多个参数,type=str(因为要接收位置和碱基) parser.add_argument('--ins', '-i', nargs='+', help='add the insertion position and the base to test its frameshift effect', default=None) parser.add_argument('--dell', '-d', type=int, help='add the position of the deleted base to test its frameshift effect', default=None) args = parser.parse_args() # 3. 简化逻辑,直接返回Args实例,因为所有可选参数都有默认值 return Args( rna=args.rna, ins=args.ins, dell=args.dell ) def main(): args = get_args() codons = codon_dict() rna = args.rna ins = args.ins dell = args.dell protein = translator(rna) print(f'protein_original:\n{protein}') if ins and not dell: # 注意:这里ins[0]是字符串,需要转成int ins_pos = int(ins[0]) ins_mut_rna = list(rna) ins_mut_rna.insert(ins_pos + 1, ins[1]) ins_mut_protein = translator(''.join(ins_mut_rna)) # 转成字符串传给translator print(f'frameshift protein\n{ins_mut_protein}') elif dell and not ins: dell_mut_rna = list(rna) dell_mut_rna.pop(dell + 1) dell_mut_protein = translator(''.join(dell_mut_rna)) print(f'frameshift\n{dell_mut_protein}') elif ins and dell: ins_pos = int(ins[0]) if ins_pos > dell: ins_dell_rna = list(rna) ins_dell_rna.insert(ins_pos + 1, ins[1]) ins_dell_rna.pop(dell + 1) final_prot = translator(''.join(ins_dell_rna)) else: dell_ins_rna = list(rna) dell_ins_rna.pop(dell + 1) dell_ins_rna.insert(ins_pos + 1, ins[1]) final_prot = translator(''.join(dell_ins_rna)) print(f'frameshift protein\n{final_prot}') def translator(rna: str) -> str: prot = [] codons = codon_dict() steps = [i for i in range(0, len(rna), 3)] rna_codons = [] for step in steps: rna_codons.append(rna[step:step + 3]) # 处理找不到AUG的情况,避免ValueError if 'AUG' not in rna_codons: return "No start codon (AUG) found" start = rna_codons.index('AUG') rna_codons = rna_codons[int(start):] for codon in rna_codons: if len(codon) < 3: # 处理最后一个不完整的密码子 break if codon in codons: if codons[codon] == 'Stop': break prot.append(codons[codon]) return ''.join(prot) def codon_dict() -> Dict: mydict = {} with open('codon_table.csv', mode='r') as infile: reader = csv.reader(infile) next(reader) # 跳过表头(如果你的csv有表头的话) for rows in reader: k = rows[0] v = rows[2] mydict[k] = v return mydict if __name__ == '__main__': main()
关键修改说明
- NamedTuple默认值:给
ins和dell设置Optional类型和默认值None,这样创建Args实例时可以只传rna,或者传任意组合的可选参数。 - argparse的--ins参数:用
nargs='+'让它接收多个参数(比如4 T),这样args.ins会是一个列表['4', 'T'],之后需要把位置转成整数。 - 简化get_args()逻辑:不需要复杂的分支判断,直接把所有参数传入
Args实例即可,因为可选参数都有默认值。 - translator函数修复:添加了找不到AUG的处理,以及最后一个不完整密码子的处理,避免报错。
- main函数的变量统一:同时处理ins和dell时,统一用
final_prot变量,避免原代码中变量名不一致导致的报错。
测试命令
现在你可以用以下命令测试:
python3 prot.py AUGUUUAUG -d 4 -i 4 T
注意不需要给4 T加引号,nargs='+'会自动把它们解析成列表。
备注:内容来源于stack exchange,提问作者Younes Abuelayyan
相关产品推荐
相关产品推荐

