
# 代码
代码节点是工作流中用于执行自定义代码逻辑的节点。当工作流中需要进行**数据处理、格式转换、数学计算、逻辑判断**等操作，而这些操作用其他节点难以实现或用大模型处理不够准确时，可以通过代码节点编写代码来完成。代码执行的结果是确定的，相同的输入必然得到相同的输出。对于计算、格式转换等任务，代码比大模型更准确、更快、且不消耗Token。
代码节点的典型使用场景如下：
表1代码节点使用场景 
| 场景     | 示例                                 |
|:---|:---|
| 数据格式转换 | 将上游节点返回的JSON数据提取、重组为下游节点需要的格式。     |
| 数学计算   | 价格计算、折扣计算、数据汇总统计等。                 |
| 文本处理   | 正则匹配、字符串拼接、内容截取、编码转换等。             |
| 逻辑判断   | 复杂的条件判断、数据校验、规则匹配等。                |
| 数据清洗   | 去重、过滤、排序、字段映射等。                    |
| 调用外部接口 | 需要自定义请求逻辑的HTTP调用（FunctionGraph模式）。 |
   
#### 配置代码节点
代码节点的配置参数说明如下：
表2代码节点配置参数 
| 参数       | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
|:---|:---|
| 执行方式     | FunctionGraph：由华为云FunctionGraph函数工作流提供代码执行环境，除了进行数据转换、简单计算、文本处理任务外，还具备依赖包管理、网络访问等高级功能。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| 绑定函数     | 新建代码函数或选择已创建的函数。支持Python 3.9和Node.js 14.18两种语言。详细代码要求请参考[Python 3.9代码要求]、[Node.js 14.18代码要求]。 代码编辑完成后，必须进行调试验证，可单击![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538544142.png)图标进行验证。检查代码是否有执行报错、是否有输出结果、结果是否符合预期。若无输出结果检查输入、输出参数是否设置正确。 图1编辑函数 ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002569423867.png) 图2测试代码节点 ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538384210.png) 同时平台支持AI智能优化代码功能。 图3智能优化代码 ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002569423799.png) |
| 输入参数     | 输入参数用于声明代码中所适用的输入变量，每个输入参数需要和代码中定义的参数保持一致。 参数值可以直接填写一个固定的值，也可以选择引用工作流中上游节点的输出和全局配置的记忆变量。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| 输出参数     | 输出参数用于定义代码执行完成后向下游传递哪些数据，输出参数的名称和类型必须与代码中返回的键值对严格对应。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| 委托授权（可选） | FunctionGraph支持与多种华为云服务对接。在编写代码节点的函数时，如果涉及其他业务的代码逻辑，并希望使用FunctionGraph来控制这些服务的使用权限，可以参考[FunctionGraph权限介绍](https://support.huaweicloud.com/productdesc-functiongraph/functiongraph_01_0160.html)、[授权使用FunctionGraph](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0215.html)进行配置。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| 依赖包（可选）  | 支持选择公共依赖包，或者用户上传私有依赖包，用于引入第三方库。私有依赖包上传方法请参见[私有依赖包上传示例]。 一个函数最多添加**20个** 依赖包。平台支持的公共依赖包由华为云FunctionGraph函数工作流提供，公共依赖包清单请参考[FunctionGraph公共依赖包说明](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0502.html)。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| 异常处理     | 支持对节点的异常（如超时、调用失败等情况）进行处理，包括超时时间、重试次数、异常处理方式。 "超时时间"：支持用户配置超时时间，取值范围0.1\~900，默认900s。 "重试次数"：支持配置重试次数（不重试、重试1次、重试2次、重试3次），系统默认不重试。 "异常处理方式"：配置异常处理方式。 - 中断流程：节点发生异常后，直接中断流程，不再运行后续节点。  - 返回设定内容：节点发生异常后，工作运行不会中断，用户可自定义设置需要返回的输出字段内容，必须是输出参数中已定义的字段，且格式为合法的JSON格式。  - 执行异常流程：节点发生异常后，工作流不会中断，而是会执行异常处理流程。用户可以在该运行异常的节点前新增节点，并为新增的异常分支配置相应的处理流程。                                                                     |
   
 #### Python 3.9代码要求
支持Python 3.9版本及其标准库，并支持如下的非标准库，可直接在Python函数代码中声明使用。
表3Python运行时集成的非标准库 
| 模块        | 功能         | 版本号    |
|:---|:---|:---|
| dateutil  | 日期/时间处理    | 2.6.0  |
| requests  | http库      | 2.7.0  |
| httplib2  | httpclient | 0.10.3 |
| numpy     | 数学计算       | 1.13.1 |
| redis     | redis客户端   | 2.10.5 |
| obsclient | OBS客户端     | -      |
| smnsdk    | 访问SMN服务    | 1.0.1  |
   
示例如下：
```
def main(args: dict) -> dict:
    """
    运行代码节点会调用此函数，请勿对下面的函数名做修改
    :param args: 输入固定为args字典类型，kv为输入参数键值对
    :return: 输出参数为字典类型，kv为输出参数键值对
    """
    ret = {
        "key0": args.get('input', 'default'),
        "key1": "hi"
    }
    return ret
```
- 平台通过固定的main函数触发代码执行，函数名不可修改。
- 输入参数args是一个字典（dict），包含了在代码节点界面配置的所有输入参数，以参数名为key、参数值为value的键值对形式传入。通过args.get('参数名', '默认值') 读取，建议始终设置默认值，避免参数缺失时报错。
- 返回值是一个字典（dict），直接return即可，无需做JSON转换。返回字典中的key必须与代码节点界面配置的"输出参数"名称完全一致（区分大小写），否则下游节点将无法获取到对应的值。
- 在代码节点界面的"输出参数"区域配置的参数名，必须与代码return字典中的key对应。
- 编写约束：
  ```
  入口函数名必须是main，接收一个dict参数，返回一个dict
  直接返回字典即可，无需json.dumps()转换
  即使只有一个输出字段，也必须以字典形式返回
   ×  return "hello"
   √  return {"message": "hello"}
  ```
  
 #### Node.js 14.18代码要求
支持Nodejs 14.18版本及其标准库，并支持如下的非标准库，可直接在Node.js函数代码中声明使用。
表4Nodejs运行时集成的非标准库 
| 名称              | 功能                                                                  | 版本号     |
|:---|:---|:---|
| q               | 异步方法封装。                                                             | 1.5.1   |
| co              | 异步流程控制。                                                             | 4.6.0   |
| lodash          | 常用工具方法库。                                                            | 4.17.10 |
| esdk-obs-nodejs | OBS SDK。                                                            | 2.1.5   |
| express         | 极简web开发框架。                                                          | 4.16.4  |
| fgs-express     | 在FunctionGraph和API Gateway之上使用现有的Node.js应用程序框架运行无服务器应用程序和REST API 。 | 1.0.1   |
| request         | 简化HTTP调用，支持HTTPS并默认遵循重定向                                            | 2.88.0  |
   
示例如下
```
/**
 * 运行代码节点会调用此函数，请勿对下面的函数名做修改
 * @param {Object} args - 输入固定为args对象类型，kv为输入参数键值对
 * @returns {Promise<Object>} 输出参数为Promise包裹的对象类型，kv为输出参数键值对
   */
   exports.main = async (args) => {
   const ret = {
       "key0": args?.input ?? 'default',
       "key1": "hi"
   };
   return ret;
   }
```
- 平台通过固定的exports.main函数触发代码执行，函数名不可修改。
- 输入参数args是一个对象（Object），包含了在代码节点界面配置的所有输入参数，以参数名为key、参数值为value的键值对形式传入。通过args?.参数名 ?? '默认值' 读取，其中?. 是可选链操作符，当args为null或undefined 时不会报错而是返回undefined；??是空值合并操作符，当左侧值为null或undefined时返回右侧的默认值。建议始终设置默认值，避免参数缺失时报错。
- 返回值是一个对象（Object），直接return即可，无需做JSON.stringify()转换。由于入口函数声明为async，返回值会自动包裹为Promise\<Object\>，平台会自动处理Promise的解析，开发者无需手动调用.then()。返回对象中的key必须与代码节点界面配置的"输出参数"名称完全一致（区分大小写），否则下游节点将无法获取到对应的值。
- 在代码节点界面的"输出参数"区域配置的参数名，必须与代码return对象中的key对应。
- 编写约束：
  ```
  入口函数必须是exports.main，声明为async异步函数，接收一个Object参数，返回一个Object
  直接返回对象即可，无需JSON.stringify()转换
  即使只有一个输出字段，也必须以对象形式返回
   ×  return "hello"  
   √  return {"message": "hello"}
  ```
  
 #### 私有依赖包上传示例
本实例制作Python的beautifulsoup4依赖包，其余依赖包制作方式相同。
1. **制作Python的beautifulsoup4依赖包。**
   
   1. 准备一台Huawei Cloud EulerOS 2.0环境的服务器。 **制作函数依赖包推荐在Huawei Cloud EulerOS 2.0环境中进行**。 使用其他系统打包可能会因为底层依赖库的原因，运行出问题，比如找不到动态链接库。
      本示例中创建一台EulerOS镜像的[弹性云服务器](https://console.huaweicloud.com/ecm/#/ecs/manager/vmList)进行后续操作的演示（创建一台按需计费、最低规格1u1g、EulerOS镜像的服务器，使用完成即可删除释放）。
      
   
   2. 创建完成后，远程登录至该服务器（可使用弹性云服务器默认的CloudShell方式登录）。
   
   3. 依次执行以下命令，下载Python的beautifulsoup4依赖包，并将其压缩为zip包。
      ```
      # 1. 创建临时目录，用于存放beautifulsoup4依赖包，该依赖包缩写为bs4，创建相同名称的目录
      mkdir -p /tmp/bs4
      # 2. 安装依赖（自动包含soupsieve）
      pip install beautifulsoup4 --root /tmp/bs4
      # 进入临时目录
      cd /tmp/bs4
      # 查找 site-packages 路径（Linux 下通用命令）
      find . -name "site-packages"
      # 示例输出：./usr/local/lib/python3.9/site-packages
      # 进入找到的 site-packages 目录（替换为上面步骤中查询的实际路径）
      cd ./usr/local/lib/python3.9/site-packages
      # -r：递归打包（包含 bs4、soupsieve 等所有文件）；-q：静默模式
      # 将包生成到 /tmp 目录，方便后续下载
      zip -rq /tmp/bs4.zip *
      ```
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538544044.png)
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538384114.png)
      
   
   4. 打包完成后即可在tmp路径下查询到bs4.zip文件，下载该依赖包。
      图4下载依赖包   
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538544058.png) 
   
   
   
   
2. **上传依赖包。**
   
   1. 在代码节点中单击"添加依赖包"，按照页面提示前往FunctionGraph创建依赖包。
      图5前往FunctionGraph创建依赖包   
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538544084.png) 
   
   2. 在代码节点中单击"添加依赖包"，按照页面提示前往FunctionGraph创建依赖包。
      图6前往FunctionGraph创建依赖包   
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002569343827.png) 
   
   3. 在FunctionGraph页面，单击"创建依赖包"。
      图7创建依赖包   
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002569423877.png) 
   
   4. 在创建依赖包页面填写依赖包名称、选择运行时为Python 3.9，并选择ZIP上传方式。 **代码节点支持Python3.9、Node.js14.18版本的代码，因此运行时也需要选择对应的版本。**ZIP上传方式较为便捷，推荐使用。创建依赖包后会自动生成对应的版本号。
      图8创建依赖包   
      ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538384150.png) 
   
   
   
   
   
3. **工作流中代码节点使用依赖包。**
   
   单击代码节点的"添加依赖包"，选择"私有依赖包"，刷新依赖包清单，选择已经创建的依赖包及其版本。
   图9代码节点使用依赖包   
   ![](https://support.huaweicloud.com/usermanual-agentarts0/zh-cn_image_0000002538544118.png)
   
   
 
#### 常见问题
- **代码执行后报SyntaxError**
  Python代码的常见语法问题包括：缩进不统一（混用了空格和Tab）、括号或引号未成对闭合、中英文符号混用（如使用了中文冒号 ： 或中文括号 （））。
  
- **import第三方库报ModuleNotFoundError**
  默认情况下仅支持内置标准库，不支持安装和使用第三方库。如果需要第三方库，请单独上传依赖包。
  
- **使用requests等库发起HTTP请求失败**
  应使用平台内置的common模块发起HTTP请求，而非自行导入requests等第三方库。用法如下：
  ```
  // Python示例
  import common
  data = common.httpRequest("https://api.example.com/data", headers, body, "POST")
  if data.get("code") < 300:
      return data.get("body")
  ```
  
- **下游节点获取不到代码节点的输出值**
  最常见的原因是输出区域配置的参数名与代码return中的key不一致。两者必须完全匹配，包括大小写。例如代码返回了totalPrice，输出区域配置成totalprice就会取不到值。
  
- **下游节点获取到的值类型与预期不符**
  检查输出区域配置的参数类型是否与代码实际返回的数据类型一致。例如代码返回了数字100，但输出参数类型配置为String，下游节点拿到的就是字符串"100"而非数字。
  
 
