> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kasoftware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 编写 Python

> 如何在知行之桥中编写和执行 Python 脚本，包括内置变量、上下文对象和实用示例。

export const siteNameShort = "知行之桥";

完成 [先决条件](./python-prerequisites) 后，{siteNameShort} 便可以在任何可以编写 {siteNameShort}Script 的地方读取和执行 Python 代码。这包括 [Script](../connectors/script) 端口、[事件](./scripting#event-scripting)、[XML Map](../connectors/xml-map/xml-map) 端口中的代码脚本等等。

要让 {siteNameShort} 的脚本引擎使用 Python 而不是 {siteNameShort}Script，必须将 Python 定义为所使用的语言。这可以通过在 [arc:script](./keyword-reference/op-arc-script) 关键字上设置 `language` 属性来实现，如下所示：

```xml theme={null}
<arc:script language="python">
# Python code goes here
</arc:script>
```

Python 直接嵌入到 {siteNameShort} 的脚本引擎中，这使熟悉 Python 编写的用户能够使用类似的语法与脚本中的消息和上下文进行交互。

还可以在同一个脚本中使用 {siteNameShort}Script 和 Python。当已经编写了 {siteNameShort}Script 代码，但需要使用 Python 实现一些额外逻辑时，这非常有用。您可以使用 Python 直接访问用 {siteNameShort}Script 编写的项，如下例所示：

```xml theme={null}
<arc:set attr="CustomerA.OrderID" value="123456" />
<arc:script language="python">
print("The OrderId for CustomerA is", _ctx.CustomerA.OrderID)
</arc:script>
```

许多 Python 方法和变量专门用于 {siteNameShort} 中的消息、项和属性上下文。

## 内置对象接口

{siteNameShort} 的 Python 实现中使用了两个主要接口。它们包含并提供对以下列出的内置变量的访问：

* [{siteNameShort}ScriptContext](#scriptcontext)
* [{siteNameShort}ScriptItem](#scriptitem)

### {siteNameShort}ScriptContext

这表示 {siteNameShort} 中 Python 脚本的主要脚本上下文对象。它提供类似字典的项访问方式，并包含日志记录功能。此接口提供对 `_ctx` 变量的访问，您可以使用该变量访问上下文。

可用的方法如下：

* [push](#push)
* [log](#log)

### {siteNameShort}ScriptItem

这表示 {siteNameShort} 脚本环境中的单个数据项。它提供类似字典的属性访问方式，并维护值列表。以下变量是自动可用的 {siteNameShort}ScriptItem 实例：

* [\_input](#_input)
* [output](#output)
* [\_message](#_message)
* [result](#result)

可用的方法有：

* [get](#get)
* [clear](#clear)

从高层次来看，`_ctx` 提供对脚本上下文的访问，而 `_input`、`output` 和 `_message` 是预先实例化的 {siteNameShort}ScriptItem 对象。使用语法 `_ctx.itemname` 可以动态创建或访问自定义项。有关更多信息，请参阅[内置变量](#内置变量)和[运算器](#运算器)。

## 内置变量

这些变量用于访问脚本环境中消息上下文的核心。您可以使用它们与脚本引擎中的可用项进行交互。

### \_ctx

访问脚本环境的主要变量。它提供：

* 访问脚本中所有可用的项
* 创建新项、推送项以及记录到应用程序日志的功能

在以下示例中，调用 `_ctx` 变量的 `log` 方法，使用 `INFO` 日志级别将信息记录到[应用程序日志](../getting-started/administration/activity#application-logs)：

```xml theme={null}
<arc:script language="python">
...
_ctx.log('INFO', 'Successfully analyzed all data!')
...
</arc:script>
```

### \_input

脚本引擎的只读输入项。可用属性根据您编写脚本的上下文（例如端口的[操作类型](../connectors/script#actions)）而有所不同。例如，在设置为 *Transform* 操作的 [Script](../connectors/script) 端口中，可以使用以下属性：

* ConnectorId
* WorkspaceId
* MessageId
* FilePath
* FileName
* Attachment#
* Header:\*

但是，如果将 Script 端口设置为不向端口提供输入的 *Trigger* 操作，则只有 ConnectorId 和 WorkspaceId 可用。

以下示例将端口的名称打印到当前消息的日志文件中：

```xml theme={null}
<arc:script language="python">
...
print(_input.ConnectorId)
...
</arc:script>
```

此示例获取输入文件，对其进行重命名，记录原始名称，然后使用新名称推送相同的文件：

```xml theme={null}
<arc:script language="python">
originalname = _input.Filename
print("The original filename was ", originalname)
output.Filename = "mynewfile.xml"
output.Filepath = _input.Filepath
</arc:script>
```

此示例检查输入文件的名称，以确定其是否为易腐烂物品列表。然后，它根据文件名设置易腐烂物品的头部和值：

```xml theme={null}
<arc:script language="python">
# Check if it's a perishable product list based on the filename
is_perishable = "perishables" in _input.FileName.lower()
# Set a perishable header and value based on the filename
output['Header:category'] = 'perishable' if is_perishable else 'non-perishable'
</arc:script>
```

### output

内置项，当只需要单个输出时，可作为创建和推送自定义项的替代方案。与需要显式调用 `push()` 将其作为输出发送的自定义项不同，`output` 项会在脚本完成时自动推送。只需修改其属性，脚本执行完成后它就会自动作为输出推送，无需任何额外的 `push()` 调用。

可以直接在项上设置属性，也可以使用 `dict` 定义属性；对自己定义的项也可以执行相同的操作。以下示例推送了一个包含一些数据的输出文件：

```xml theme={null}
<arc:script language="python">
output = {'data': 'This is a test',
          'filename': 'foo.txt'}
</arc:script>
```

此示例获取输入文件，对其进行重命名，记录原始名称，然后使用新名称推送相同的文件：

```xml theme={null}
<arc:script language="python">
originalname = _input.Filename
print("The original filename was ", originalname)
output.Filename = "mynewfile.xml"
output.Filepath = _input.Filepath
</arc:script>
```

### \_message

当上下文中已加载消息时，提供对当前消息的访问。只有在特定场景下（例如，上下文中已加载消息时），端口正在主动处理消息时，此变量才可用。例如，在[操作](../connectors/script#actions)设置为 *Trigger* 的端口中，`_message` 变量不可用，因为在端口完成工作之前，消息不会出现。当此变量不可用时，会出现 `_message is not defined` 异常。

可以使用以下属性：

* Header:Message-Id
* Header:FileName
* Header:\*
* body

下面的示例对消息正文进行一些简单的字符串操作：

```xml theme={null}
<arc:script language="python">
# The message body in this example is plain text of "Example data for Arc."
# Perform string manipulation
transformed = _message.body.replace('a', '@').replace('e', '3')
print("Original:", _message.body)
print("Transformed:", transformed)
...
</arc:script>
```

结果输出被打印到消息日志中：

```
Original: Example data for Arc.
Transformed: 3x@mpl3 d@t@ for Arc.
```

此示例显示如何从 `_message` 项中读取 CustomerID 头部，并将其作为当前消息日志文件中的条目打印。

```xml theme={null}
<arc:script language="python">
...
print("The data is valid for customer", _message["Header:CustomerID"])
...
</arc:script>
```

### result

一个专门用于 [XML Map](../connectors/xml-map/xml-map) 脚本节点的特殊变量。它被视为整个脚本的结果。此变量的值将用作映射中节点的值。不过，它也可以用作 [Script](../connectors/script) 端口中的调试工具。

此示例用于 XML Map 端口目标节点的脚本中，它从顶部声明的 {siteNameShort}Script 项中读取源文件的 address/city xpath，然后使用 Python 将该值修改为前三个字母并全部大写。新值随后作为 `result` 的值发送：

```xml theme={null}
<arc:set attr="source.city" value="[xpath(address/city)]" />
<arc:script language="python">
city_value = _ctx.source.get("city")
# Normalize: extract from list if needed
if isinstance(city_value, list):
    city = city_value[0] if city_value else None
else:
    city = city_value
# Final logic
result = city[:3].upper() if city else ""
</arc:script>
```

在此示例中，`result` 变量用于向 Script 端口的日志文件添加条目：

```xml theme={null}
<arc:script language="python">
result = ["Step 1"]
output = {
  "Filename": "test.txt",
  "Data": "foo"
}
result.append("Step 2")
</arc:script>
```

脚本输出如下所示：

```
[2025-06-12T17:14:36.878-04:00][Info] Output File: test.txt
[2025-06-12T17:14:36.883-04:00][Info] Receiving done.
[2025-06-12T17:14:36.883-04:00][Info] Script output:
["Step 1","Step 2"]
```

## 运算器

### log

`log(level, message)` 是 `_ctx` 变量的一个可用方法，允许将条目直接写入 {siteNameShort} [应用程序日志](../getting-started/administration/activity#application-logs)。可用的日志级别包括 DEBUG、INFO、WARNING 和 ERROR。

```xml theme={null}
<arc:script language="python">
...
_ctx.log('ERROR', f'Data evaluation failed in connector {_input.ConnectorId}!')
...
</arc:script>
```

前面的示例生成以下日志条目：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/python_log_result.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=c5ca77b574e0319596f1521e32a67d69" alt="Python log result in the Activity log" width="700" data-path="public/images/python_log_result.png" />

### push

`push(item)` 将提供的项推送为脚本的输出。如果未指定输出，则推送 `output` 项。

在本例中，在 {siteNameShort}ScriptContext 中创建了一个新的项 `foo`，并为其分配了一些数据和文件名，然后将其推送出去。

```xml theme={null}
<arc:script language="python">
foo = _ctx.foo
foo.Filename = "test2.txt"
foo.Data = "bar"
_ctx.push(foo)
</arc:script>
```

### get

`get(attr)` 返回 {siteNameShort}ScriptItem 上指定属性的值。此方法提供了一种通过名称访问项属性的编程方式。其功能相当于直接使用点符号访问属性（例如 `_input.myattr`）或使用字典式访问（例如 `_input.get('myattr')`）。

以下示例将 `item` 对象上 `tags` 属性的值列表打印到当前脚本的日志文件中。

```xml theme={null}
<arc:script language="python">
item = _ctx.item
item.name = 'Milk'
item.price = '2.99'
item.tags = ['perishable', 'dairy', 'noreturn']
print(item.get('tags'))
</arc:script>
```

### clear

`clear()` 清除调用该方法的 {siteNameShort}ScriptItem。该项保持不变，只是为空。

```xml theme={null}
<arc:script language="python">
product = _ctx.product
product.name = 'Milk'
product.price = '2.99'
product.tags = ['perishable', 'dairy', 'noreturn']
print("Before clear:", product)
# Use the clear() method to remove all items
product.clear()
print("After clear:", product)
</arc:script>
```

前面的示例产生以下输出：

* Before clear: `{"price":"2.99","name":"Milk","tags":["perishable","dairy","noreturn"]}`
* After clear: `{}`
