<commit_before>---
id: functions-api
title: The Pulsar Functions API
sidebar_label: API
---

[Pulsar Functions](functions-overview.md) provides an easy-to-use API that developers can use to create and manage processing logic for the Apache Pulsar messaging system. With Pulsar Functions, you can write functions of any level of complexity in [Java](#functions-for-java) or [Python](#functions-for-python) and run them in conjunction with a Pulsar cluster without needing to run a separate stream processing engine.

> For a more in-depth overview of the Pulsar Functions feature, see the [Pulsar Functions overview](functions-overview.md).

## Core programming model

Pulsar Functions provide a wide range of functionality but are based on a very simple programming model. You can think of Pulsar Functions as lightweight processes that

* consume messages from one or more Pulsar topics and then
* apply some user-defined processing logic to each incoming message. That processing logic could be just about anything you want, including
  * producing the resulting, processed message on another Pulsar topic, or
  * doing something else with the message, such as writing results to an external database.

You could use Pulsar Functions, for example, to set up the following processing chain:

* A [Python](#functions-for-python) function listens on the `raw-sentences` topic and "[sanitizes](#example-function)" incoming strings (removing extraneous whitespace and converting all characters to lower case) and then publishes the results to a `sanitized-sentences` topic
* A [Java](#functions-for-java) function listens on the `sanitized-sentences` topic, counts the number of times each word appears within a specified time window, and publishes the results to a `results` topic
* Finally, a Python function listens on the `results` topic and writes the results to a MySQL table

### Example function

Here's an example "input sanitizer" function written in Python and stored in a `sanitizer.py` file:

```python
def clean_string(s):
    return s.strip().lower()

def process(input):
    return clean_string(input)
```

Some things to note about this Pulsar Function:

* There is no client, producer, or consumer object involved. All message "plumbing" is already taken care of for you, enabling you to worry only about processing logic.
* No topics, subscription types, tenants, or namespaces are specified in the function logic itself. Instead, topics are specified upon [deployment](#example-deployment). This means that you can use and re-use Pulsar Functions across topics, tenants, and namespaces without needing to hard-code those attributes.

### Example deployment

Deploying Pulsar Functions is handled by the [`pulsar-admin`](reference-pulsar-admin.md) CLI tool, in particular the [`functions`](reference-pulsar-admin.md#functions) command. Here's an example command that would run our [sanitizer](#example-function) function from above in [local run](functions-deploying.md#local-run-mode) mode:

```bash
$ bin/pulsar-admin functions localrun \
  --py sanitizer.py \          # The Python file with the function's code
  --classname sanitizer \      # The class or function holding the processing logic
  --tenant public \            # The function's tenant (derived from the topic name by default)
  --namespace default \        # The function's namespace (derived from the topic name by default)
  --name sanitizer-function \  # The name of the function (the class name by default)
  --inputs dirty-strings-in \  # The input topic(s) for the function
  --output clean-strings-out \ # The output topic for the function
  --log-topic sanitizer-logs   # The topic to which all functions logs are published
```

For instructions on running functions in your Pulsar cluster, see the [Deploying Pulsar Functions](functions-deploying.md) guide.

### Available APIs

In both Java and Python, you have two options for writing Pulsar Functions:

Interface | Description | Use cases
:---------|:------------|:---------
Language-native interface | No Pulsar-specific libraries or special dependencies required (only core libraries from Java/Python) | Functions that don't require access to the function's [context](#context)
Pulsar Function SDK for Java/Python | Pulsar-specific libraries that provide a range of functionality not provided by "native" interfaces | Functions that require access to the function's [context](#context)

In Python, for example, this language-native function, which adds an exclamation point to all incoming strings and publishes the resulting string to a topic, would have no external dependencies:

```python
def process(input):
    return "{}!".format(input)<commit_msg>[docs] Refine description of two examples in "Functions API" doc (#4827)<commit_after>---
id: functions-api
title: The Pulsar Functions API
sidebar_label: API
---

[Pulsar Functions](functions-overview.md) provides an easy-to-use API that developers can use to create and manage processing logic for the Apache Pulsar messaging system. With Pulsar Functions, you can write functions of any level of complexity in [Java](#functions-for-java) or [Python](#functions-for-python) and run them in conjunction with a Pulsar cluster without needing to run a separate stream processing engine.

> For a more in-depth overview of the Pulsar Functions feature, see the [Pulsar Functions overview](functions-overview.md).

## Core programming model

Pulsar Functions provide a wide range of functionality but are based on a very simple programming model. You can think of Pulsar Functions as lightweight processes that

* consume messages from one or more Pulsar topics and then
* apply some user-defined processing logic to each incoming message. That processing logic could be just about anything you want, including
  * producing the resulting, processed message on another Pulsar topic, or
  * doing something else with the message, such as writing results to an external database.

You could use Pulsar Functions, for example, to set up the following processing chain:

* A [Python](#functions-for-python) function listens on the `raw-sentences` topic and "[sanitizes](#example-function)" incoming strings (removing extraneous whitespace and converting all characters to lower case) and then publishes the results to a `sanitized-sentences` topic
* A [Java](#functions-for-java) function listens on the `sanitized-sentences` topic, counts the number of times each word appears within a specified time window, and publishes the results to a `results` topic
* Finally, a Python function listens on the `results` topic and writes the results to a MySQL table

### Function example

The following "input sanitizer" function is written in Python and stored in a `sanitizer.py` file.

```python
def clean_string(s):
    return s.strip().lower()

def process(input):
    return clean_string(input)
```

**Note**

* In the example, no client, producer, or consumer object is involved. All message "plumbing" are already done, so you only need to deal with processing logic.
* No topics, subscription types, tenants, or namespaces are specified in the function logic. Instead, topics are specified upon [deployment](#example-deployment). This means that you can use and re-use Pulsar Functions across topics, tenants, and namespaces without needing to hard-code those attributes.

### Example deployment

Deploying Pulsar Functions is handled by the [`pulsar-admin`](reference-pulsar-admin.md) CLI tool, in particular the [`functions`](reference-pulsar-admin.md#functions) command. The following example runs [sanitizer](#example-function) function in [local run](functions-deploying.md#local-run-mode) mode:

```bash
$ bin/pulsar-admin functions localrun \
  --py sanitizer.py \          # The Python file with the function's code
  --classname sanitizer \      # The class or function holding the processing logic
  --tenant public \            # The function's tenant (derived from the topic name by default)
  --namespace default \        # The function's namespace (derived from the topic name by default)
  --name sanitizer-function \  # The name of the function (the class name by default)
  --inputs dirty-strings-in \  # The input topic(s) for the function
  --output clean-strings-out \ # The output topic for the function
  --log-topic sanitizer-logs   # The topic to which all functions logs are published
```

For instructions on running functions in your Pulsar cluster, see the [Deploying Pulsar Functions](functions-deploying.md) guide.

### Available APIs

In both Java and Python, you have two options for writing Pulsar Functions:

Interface | Description | Use cases
:---------|:------------|:---------
Language-native interface | No Pulsar-specific libraries or special dependencies required (only core libraries from Java/Python) | Functions that don't require access to the function's [context](#context)
Pulsar Function SDK for Java/Python | Pulsar-specific libraries that provide a range of functionality not provided by "native" interfaces | Functions that require access to the function's [context](#context)

In Python, for example, this language-native function, which adds an exclamation point to all incoming strings and publishes the resulting string to a topic, would have no external dependencies:

```python
def process(input):
    return "{}!".format(input)
{'fraction_non_alphanumeric': 0.07834150500959283, 'fraction_numerical': 0.00042634832658281814, 'mean_word_length': 4.496777973052138, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4411396', 'n_tokens_mistral': 2409, 'n_tokens_neox': 2272, 'n_words': 1182}