Python argparse子命令参数赋值报错及配置需求咨询
解决argparse子解析器参数赋值全局变量的问题
你遇到的AttributeError主要有两个原因:一是命令格式和解析器结构不匹配,二是直接访问了不存在的参数属性。下面我会给出两种符合你需求的解决方案,同时解释问题根源。
问题根源分析
- 解析器结构错误:你原本的代码中,
connectmode是主解析器的位置子命令,而-sock是独立的布尔选项(action="store_true"),这导致你输入的-sock connectmode不符合解析逻辑——-sock不需要参数,connectmode会被当成未关联的位置参数,子解析器的-rport参数根本没被正确解析,所以args里自然没有rport属性。 - 未判断参数存在性:即使命令正确,当使用
listenmode子命令时,args也不会包含rport属性,直接赋值会触发报错。
方案一:使用标准子命令格式(推荐)
这种方式符合argparse的设计规范,子命令直接作为主命令的位置参数,同时满足connectmode -h显示子参数、全局变量赋值的需求。
import argparse import sys import socket # 初始化全局变量 global rport, rhost rport = None rhost = None def parser_error(message): print(f"Error: {message}") sys.exit(1) def socketfunc(): # 测试全局变量是否可用 print(f"全局变量 rhost: {rhost}, rport: {rport}") # 在这里编写你的socket逻辑代码 # 创建主解析器 parser = argparse.ArgumentParser(epilog='\tExample: \r\npython ' + sys.argv[0] + ' connectmode -rhost 127.0.0.1 -rport 10000') parser.error = parser_error parser._optionals.title = "OPTIONS" # 添加子解析器,dest='mode'用于区分不同子命令 subparsers = parser.add_subparsers(dest='mode', help='Socket操作模式', required=True) # connectmode子解析器 connect_parser = subparsers.add_parser('connectmode', help='连接到远程TCP主机') connect_parser.add_argument('-rport', '--remoteport', type=int, required=True, help="目标连接端口") connect_parser.add_argument("-rhost", '--destination', required=True, help="目标主机IP地址") connect_parser.set_defaults(func=socketfunc) # listenmode子解析器 listen_parser = subparsers.add_parser('listenmode', help='监听TCP连接') # 可添加listenmode专属参数,比如本地监听端口 listen_parser.add_argument('-lport', '--localport', type=int, required=True, help="本地监听端口") listen_parser.set_defaults(func=socketfunc) # 解析参数 args = parser.parse_args() # 根据子命令赋值全局变量 if args.mode == 'connectmode': rport = args.remoteport rhost = args.destination # 若需要处理listenmode的参数,可添加对应的赋值逻辑 # elif args.mode == 'listenmode': # local_port = args.localport # 调用对应的函数 args.func()
使用示例
- 连接模式命令:
python example.py connectmode -rhost 127.0.0.1 -rport 10000 - 查看连接模式帮助:
python example.py connectmode -h
方案二:实现-sock <mode>的命令格式
如果你坚持要用-sock选项指定模式,可以通过动态解析参数的方式实现:
import argparse import sys import socket # 初始化全局变量 global rport, rhost rport = None rhost = None def parser_error(message): print(f"Error: {message}") sys.exit(1) def socketfunc(): print(f"全局变量 rhost: {rhost}, rport: {rport}") # 主解析器 parser = argparse.ArgumentParser(epilog='\tExample: \r\npython ' + sys.argv[0] + ' -sock connectmode -rhost 127.0.0.1 -rport 10000') parser.error = parser_error parser._optionals.title = "OPTIONS" # 添加-sock选项,指定模式 parser.add_argument('-sock', '--socket', choices=['connectmode', 'listenmode'], required=True, help="TCP socket功能(仅支持IPv4)") # 先解析已知参数,获取当前模式 args, remaining_args = parser.parse_known_args() # 根据模式动态添加对应参数并完成解析 if args.socket == 'connectmode': # 创建继承主解析器的子解析器 sub_parser = argparse.ArgumentParser(parents=[parser], add_help=True) sub_parser.add_argument('-rport', '--remoteport', type=int, required=True, help="目标连接端口") sub_parser.add_argument("-rhost", '--destination', required=True, help="目标主机IP地址") # 合并参数到原args对象 args = sub_parser.parse_args(remaining_args, namespace=args) # 赋值全局变量 rport = args.remoteport rhost = args.destination elif args.socket == 'listenmode': sub_parser = argparse.ArgumentParser(parents=[parser], add_help=True) sub_parser.add_argument('-lport', '--localport', type=int, required=True, help="本地监听端口") args = sub_parser.parse_args(remaining_args, namespace=args) # 调用函数 socketfunc()
使用示例
- 连接模式命令:
python example.py -sock connectmode -rhost 127.0.0.1 -rport 10000 - 查看连接模式帮助:
python example.py -sock connectmode -h
内容的提问来源于stack exchange,提问作者mahmoudadel
相关产品推荐
相关产品推荐

