Panda3D中argparse参数未传入时为何被识别为NoneType?
问题
完成Panda3D基础功能开发后,尝试通过argparse添加自定义命令行参数:
--no-rotate参数可停止相机旋转,功能正常;- 添加
--scale参数用于调整熊猫角色缩放比例,执行python walking_panda.py --scale 5时程序正常,熊猫可缩放至5倍;但不传入该参数时,程序提示scale变量为NoneType,尽管已在WalkingPanda类的__init__方法中将scale的默认值设为1。
相关代码如下:
Panda核心逻辑代码
from math import pi, sin, cos from direct.showbase.ShowBase import ShowBase from direct.task import Task from direct.actor.Actor import Actor class WalkingPanda(ShowBase): def __init__(self, no_rotate=False, scale=1): ShowBase.__init__(self) # 加载场景模型 self.scene = self.loader.loadModel("models/environment") self.scene.reparentTo(self.render) self.scene.setScale(0.25, 0.25, 0.25) self.scene.setPos(-8, 42, 0) if not no_rotate: # 添加相机旋转任务 self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") # 加载并设置熊猫角色 self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005*scale, 0.005*scale, 0.005*scale) self.pandaActor.reparentTo(self.render) self.pandaActor.loop("walk") # 相机旋转任务 def spinCameraTask(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) self.camera.setHpr(angleDegrees, 0, 0) return Task.cont
CLI参数处理代码
from . import panda import argparse def cli(): parser = argparse.ArgumentParser(prog="walking_panda") parser.add_argument("--no-rotate",help="停止相机旋转", action="store_true") parser.add_argument("--scale", type=int) args = parser.parse_args() walking = panda.WalkingPanda(**vars(args)) walking.run()
入口文件代码
from walking_panda.cli import cli if __name__ == '__main__': cli()
解决方案
问题根源
当未传入--scale参数时,argparse会将args.scale设为None。而通过**vars(args)将参数传递给WalkingPanda的__init__时,scale=None会覆盖方法定义中的默认值scale=1,导致后续计算0.005*scale时出现NoneType错误。
两种修复方式
方式1:在argparse中设置默认值
直接给--scale参数指定default=1,这样未传参时args.scale会取1,而非None:
parser.add_argument("--scale", type=int, default=1)
方式2:过滤None值参数
保留WalkingPanda类的默认值,在调用时过滤掉值为None的参数,只传递有效的参数:
args = parser.parse_args() # 过滤掉值为None的参数 kwargs = {key: value for key, value in vars(args).items() if value is not None} walking = panda.WalkingPanda(**kwargs)
两种方式对比
- 方式1:将默认值统一放在CLI层,适合需要在命令行帮助信息中展示默认值的场景;
- 方式2:保留类定义的默认值,适合默认值由业务逻辑决定,不想在CLI层硬编码的场景。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

