Click Path 指定云路径类型,S3 地址仍报不存在
Click 8.5.0 的 path_type 只转换返回类型,存在性与权限检查仍针对本地文件。云对象应使用独立参数类型和存储客户端校验,不能靠关闭 exists 冒充验证通过。
click.Path(exists=True, path_type=AnyPath) 接收 s3://bucket/key,云端对象明明存在,命令却报告路径不存在。这里先确认你交给 Click 的是云对象地址,而不是已挂载到本机的文件。
Click 8.5.0 的 path_type 控制最终返回什么类型。Path.convert() 仍先对原值执行 os.stat(),再按配置检查本地文件类型和访问权限,最后才转换返回值。给它换一个支持 S3 的路径类,并不会把前面的检查转交给 S3。
把云对象与本地路径的校验分开
纯本地输入可以继续使用 click.Path。云对象参数则宜先作为字符串接收,由应用自己的存储层解析并查询;不要让本地 resolve_path=True 提前改写 URI。
下面只展示参数边界,resolve_cloud_input 是应用已有的云存储解析函数,须由项目实现和导入,不是 Click 内置接口:
import click
@click.command()
@click.argument("source", type=str)
def cli(source):
cloud_object = resolve_cloud_input(source)
process(cloud_object)
process 同样代表应用原有处理逻辑。云存储层应区分地址格式错误、对象不存在、无访问权限和网络失败,并只接受业务允许的协议与存储位置;这些情况不应统统改成“文件不存在”。读取权限也不能按本机的 os.access() 判断。
如果多个命令复用同一规则,可以建立独立的 click.ParamType,在 convert(value, param, ctx) 中调用这套云存储逻辑,并用 self.fail() 报告已确认的用户输入错误。不要为方便把所有异常都吞掉,尤其不要把凭据或完整敏感对象地址写进错误消息。
关闭 exists 不等于验证成功
把 exists=False 后,Click 可能在本地查找失败时直接进入类型转换,看起来能够得到 AnyPath 对象。但这只说明转换完成,并没有证实云对象存在或能够读取。本来要求输入必须存在的命令,不能在这里悄悄放弃检查。
也不宜先把 URI 下载到本地,再把下载成功当作路径解析的一部分:这会引入额外流量、缓存及清理行为,可能在普通参数解析或补全阶段触发。确实要下载时,把它作为命令执行阶段的明确动作,保留原有权限和大小限制。
修改后分别检查本地路径、合法云地址、缺失对象、拒绝访问和网络故障。正确结果应是每类输入由对应存储语义处理;不能只验证命令不再报错,而忽略它实际上从未检查远端对象。


