跳到主要内容

动态参数

组件开发中,某些情况下要求组件能够支持任意数量的输入或输出,或者某个输入或输出能同时支持多种类型,这样的需求下我们需要使用组件的动态参数功能,即组件的输入输出类型和数量由组件右面板配置动态决定,而不是在组件代码中写死。

从节点配置获取参数

使用 app.loadNodeArgs 装饰器能够方便的获得组件的输入、输出和参数,不需要使用其他接口。

!!! info "提示"

app.loadNodeArgs 在 sdk 0.17.7 之后支持
  1. 在右面板配置需要的“输入桩”、”输出桩“和”参数“数量和类型

  2. 组件代码实现:

    import suanpan
    from suanpan.app import app
    from suanpan.log import logger


    @app.afterInit
    def init(context):
    # 组件初始化,从 args 可以得到组件配置的参数
    args = context.args
    logger.info(f'init with {args}')


    @app.loadNodeArgs
    def HelloWorld(context):
    # 组件事件处理,args 包含输入和参数
    args = context.args
    logger.info(f'HelloWorld {args}')

    # 输出结果,会根据输出桩配置自动转换
    return "Hello World!", "Suanpan"


    if __name__ == "__main__":
    suanpan.run(app)

    装饰器 @app.loadNodeArgs 会自动处理组件右面板配置的各项参数,加载到组件中。组件运行时输入会被正确的解析,放到 HelloWorldcontext.args 中,输出被正确的正确的发送到不同端口。

  3. 运行结果

    组件正确解析到了传入的参数,并成功像两个输出桩输出消息。

底层接口

如果使用的 sdk 是 0.17.7 之前的版本,或者只是想动态地获取输入或输出,可以参考下面的方式。

动态配置输入

  1. 右面板增加任意多个“输入桩”

  2. 配置每个“输入桩”的“具体类型”

  3. 在程序中按名称“加载”输入。

    import suanpan
    from suanpan.app import app
    from suanpan.node import node
    from suanpan.app.arguments import String, Json
    from suanpan.log import logger


    @app.output(Json(key="outputData1"))
    def onInput(context):
    args = context.args
    try:
    inargs = app.load(node.inargs) # 根据右面板配置的“具体类型”加载输入数据
    except:
    # 如果输入的字符串无法解析为配置的具体类型,将会发生异常。
    # 比如“具体类型”配置为“JSON”,但输入的字符串是一个非法的Json字符串。
    logger.info(f"输入具体类型解析异常")
    return
    in1 = inargs.get("in1") # in1 是第一个输入端子
    logger.info(f"in1: {in1}")
    in2 = inargs.get("in2") # in2 是第二个输入端子
    logger.info(f"in2: {in2}")
    return in1


    @app.afterInit
    def onInitialSetup(context):
    args = context.args


    if __name__ == "__main__":
    suanpan.run(app)

输入字符串“4e”测试两个输入桩的解析效果,输入桩2异常,因为这个字符串是非法Json字符串。

因为节点配置为“异步接收”任意输入端子有输入会进入一次消息处理函数,因此此节点输入入口函数会被调用两次。

又如输入字符串为“{"x":3}”,两个端子都会正常解析。(异步输入,call了两次)

动态配置输出

  1. 右面板增加任意多个“输出桩”

  2. 配置每个“输出桩”的“具体类型”

  3. 在程序中按名称“加载”输出类型。

  4. send 函数给任意输出端子提供输出数据。

    import suanpan
    from suanpan.app import app
    from suanpan.node import node
    from suanpan.app.arguments import String, Json, File
    from suanpan.log import logger


    @app.param(String(key="param1", default="1"))
    def onInput(context):
    args = context.args
    try:
    inargs = app.load(node.inargs) # 根据右面板配置的“具体类型”加载输入数据
    except:
    logger.info(f"输入具体类型解析异常")
    return
    in1 = inargs.get("in1") # in1 是第一个输出端子
    logger.info(f"in1: {in1}")

    # 创建一个文件用于测试输出端子3
    fname = "newFile.txt"
    with open(fname, "w") as f:
    f.write("Hello")
    f.write("\n")

    app.send({"out1": in1, "out2": {"myValue": in1}, "out3": fname}, args=node.outargs)
    # 您也可以只输出“部分”端子,如
    app.send({"out1": "Hi, "+ in1, "out2": {"myValue": in1}}, args=node.outargs)


    @app.afterInit
    def onInitialSetup(context):
    args = context.args
    outargs = node.outargs # “加载”输出类型
    print(outargs)
    # 打印每个输出端子输出类型
    for i, outarg in enumerate(outargs):
    print(f"out{i+1} is a {outarg.__class__.__name__}")


    if __name__ == "__main__":
    suanpan.run(app)

测试输入输出,

输出3:

  • 注意File类型的输出字符串需要是一个文件路径(相对/绝对路径),
  • 输出时文件会自动上传 并被删除(因此如果是需要持久化的文件,开发者需要注意备份该输出文件)