> ## 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} 便可以在任何可以編寫 ArcScript 的地方讀取和執行 Python 程式碼。這包括 [Script](../connectors/script) 端口、[事件](./scripting#event-scripting)、[XML Map](../connectors/xml-map/xml-map) 端口中的程式碼指令碼等等。

要讓 {siteNameShort} 的指令碼引擎使用 Python 而不是 ArcScript，必須將 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 編寫的使用者能夠使用類似的語法與指令碼中的訊息和上下文進行互動。

還可以在同一個指令碼中使用 ArcScript 和 Python。當已經編寫了 ArcScript 程式碼，但需要使用 Python 實現一些額外邏輯時，這非常有用。您可以使用 Python 直接存取用 ArcScript 編寫的項，如下例所示：

```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 實現中使用了兩個主要介面。它們包含並提供對以下列出的內建變數的存取：

* [ArcScriptContext](#scriptcontext)
* [ArcScriptItem](#scriptitem)

### ArcScriptContext

這表示 {siteNameShort} 中 Python 指令碼的主要指令碼上下文物件。它提供類似字典的項存取方式，幷包含日誌記錄功能。此介面提供對 `_ctx` 變數的存取，您可以使用該變數存取上下文。

可用的方法如下：

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

### ArcScriptItem

這表示 {siteNameShort} 指令碼環境中的單個資料項。它提供類似字典的屬性存取方式，並維護值清單。以下變數是自動可用的 ArcScriptItem 例項：

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

可用的方法有：

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

從高層次來看，`_ctx` 提供對指令碼上下文的存取，而 `_input`、`output` 和 `_message` 是預先例項化的 ArcScriptItem 物件。使用語法 `_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 端口目標節點的指令碼中，它從頂部宣告的 ArcScript 項中讀取來源檔案的 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` 項。

在本例中，在 ArcScriptContext 中建立了一個新的項 `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)` 傳回 ArcScriptItem 上指定屬性的值。此方法提供了一種透過名稱存取項屬性的程式設計方式。其功能相當於直接使用點符號存取屬性（例如 `_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()` 清除呼叫該方法的 ArcScriptItem。該項保持不變，只是為空。

```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: `{}`
