diff --git a/birdy/client/base.py b/birdy/client/base.py
index ba82dbb..20bbe60 100644
--- a/birdy/client/base.py
+++ b/birdy/client/base.py
@@ -1,5 +1,6 @@
 import types
 from collections import OrderedDict
+from collections import namedtuple
 from copy import copy
 from textwrap import dedent
 import threading
@@ -12,7 +13,8 @@ from owslib.wps import WPS_DEFAULT_VERSION, WebProcessingService, SYNC, ASYNC
 from birdy.exceptions import UnauthorizedException
 from birdy.client import utils
 from birdy.client.converters import default_converters
-from collections import namedtuple
+from birdy.utils import sanitize, delist
+
 import logging
 
 
@@ -214,8 +216,8 @@ class WPSClient(object):
             raise
 
         # Output type conversion
-        output = namedtuple(pid, [o.identifier for o in resp.processOutputs])
-        return output(**{o.identifier: self._process_output(o, pid) for o in resp.processOutputs})
+        Output = namedtuple('Output', [sanitize(o.identifier) for o in resp.processOutputs])
+        return Output._make([self._process_output(o, pid) for o in resp.processOutputs])
 
     def _notebook_monitor(self, execution, sleep=3):
         """Monitor the execution of a process using a notebook progress bar widget.
@@ -329,7 +331,7 @@ class WPSClient(object):
             if data_type is None:
                 data_type = self._outputs[pid][output.identifier].dataType
             data = [utils.convert_output_value(d, data_type) for d in output.data]
-            return utils.delist(data)
+            return delist(data)
 
         if self._convert_objects:
             # Try to convert the bytes to an object.
diff --git a/birdy/client/utils.py b/birdy/client/utils.py
index 3df6319..af09bfa 100644
--- a/birdy/client/utils.py
+++ b/birdy/client/utils.py
@@ -119,16 +119,6 @@ def convert_output_value(value, data_type):
     return value
 
 
-def delist(data):
-    """If data is a sequence with a single element, returns this element, otherwise return a namedtuple."""
-    from collections import Iterable
-
-    if (isinstance(data, Iterable) and not isinstance(data, six.string_types) and len(data) == 1):
-        return data[0]
-
-    return data
-
-
 def is_notebook():
     """Return whether or not this function is executed in a notebook environment."""
     try:
diff --git a/birdy/utils.py b/birdy/utils.py
index d9964a0..f12002d 100644
--- a/birdy/utils.py
+++ b/birdy/utils.py
@@ -1,3 +1,7 @@
+import re
+import collections
+
+import six
 from six.moves.urllib.parse import urlparse
 
 
@@ -9,3 +13,17 @@ def is_url(url):
         return False
     else:
         return True
+
+
+def sanitize(name):
+    """Lower-case name and replace all non-ascii chars by `_`."""
+    return re.sub(r'\W|^(?=\d)', '_', name.lower())
+
+
+def delist(data):
+    """If data is a sequence with a single element, returns this element, otherwise return the sequence."""
+    if (
+        isinstance(data, collections.Iterable) and not isinstance(data, six.string_types) and len(data) == 1
+    ):
+        return data[0]
+    return data
diff --git a/requirements_extra.txt b/requirements_extra.txt
index cb4981f..912a4c4 100644
--- a/requirements_extra.txt
+++ b/requirements_extra.txt
@@ -1,3 +1,3 @@
 netCDF4
 ipywidgets
-ipython
\ No newline at end of file
+ipython

native client: how to return multiple values?
## Description

In the current *native* client implementation we either return a single value or a list of values. I would find it more descriptive to return a dictionary with: 
```
key=parameter identifier
value=parameter value
```

@huard @davidcaron 
What do you think?

Here a link from a quick google search:
https://stackoverflow.com/questions/354883/how-do-you-return-multiple-values-in-python

## Environment


## Steps to Reproduce



## Additional Information



diff --git a/tests/test_client.py b/tests/test_client.py
index 2fa5a26..6df4a4a 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -53,7 +53,7 @@ def test_interactive(capsys):
     assert m.hello("david").output == "Hello david"
     captured = capsys.readouterr()
     assert captured.out.startswith(str(datetime.date.today()))
-    assert m.binaryoperatorfornumbers() == 5
+    assert m.binaryoperatorfornumbers()[0] == 5
 
 
 @pytest.mark.skip(reason="Complex Output is not working.")
diff --git a/tests/test_utils.py b/tests/test_utils.py
index a120e18..f86b260 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -5,3 +5,14 @@ def test_is_url():
     assert utils.is_url("http://localhost:5000/wps")
     assert utils.is_url("file:///path/to/my/file.txt")
     assert not utils.is_url("myfile.txt")
+
+
+def test_sanitize():
+    assert utils.sanitize('output') == 'output'
+    assert utils.sanitize('My Output 1') == 'my_output_1'
+
+
+def test_delist():
+    assert utils.delist(['one', 'two']) == ['one', 'two']
+    assert utils.delist(['one', ]) == 'one'
+    assert utils.delist('one') == 'one'

environment.yml
pip install -e .[dev]
parse_log_pytest
environment.yml
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster @ file:///home/conda/feedstock_root/build_artifacts/alabaster_1704848697227/work
argcomplete==3.6.1
astroid==3.3.9
babel @ file:///home/conda/feedstock_root/build_artifacts/babel_1738490167835/work
-e git+https://github.com/bird-house/birdy.git@a8b1f071bc316d9cc3453257b0430a644b3f9a7e#egg=birdhouse_birdy
boltons @ file:///home/conda/feedstock_root/build_artifacts/boltons_1733827268945/work
Brotli @ file:///home/conda/feedstock_root/build_artifacts/brotli-split_1725267488082/work
certifi @ file:///home/conda/feedstock_root/build_artifacts/certifi_1739515848642/work/certifi
cffi @ file:///home/conda/feedstock_root/build_artifacts/cffi_1725571112467/work
cftime @ file:///home/conda/feedstock_root/build_artifacts/cftime_1725400455427/work
charset-normalizer @ file:///home/conda/feedstock_root/build_artifacts/charset-normalizer_1735929714516/work
click @ file:///home/conda/feedstock_root/build_artifacts/click_1734858813237/work
colorama @ file:///home/conda/feedstock_root/build_artifacts/colorama_1733218098505/work
dataclasses @ file:///home/conda/feedstock_root/build_artifacts/dataclasses_1628958434797/work
docutils @ file:///home/conda/feedstock_root/build_artifacts/docutils_1733217766141/work
exceptiongroup @ file:///home/conda/feedstock_root/build_artifacts/exceptiongroup_1733208806608/work
flake8 @ file:///home/conda/feedstock_root/build_artifacts/flake8_1739898391164/work
funcsigs @ file:///home/conda/feedstock_root/build_artifacts/funcsigs_1735229959141/work
h2 @ file:///home/conda/feedstock_root/build_artifacts/h2_1738578511449/work
hpack @ file:///home/conda/feedstock_root/build_artifacts/hpack_1737618293087/work
hyperframe @ file:///home/conda/feedstock_root/build_artifacts/hyperframe_1737618333194/work
idna @ file:///home/conda/feedstock_root/build_artifacts/idna_1733211830134/work
imagesize @ file:///home/conda/feedstock_root/build_artifacts/imagesize_1656939531508/work
importlib_metadata @ file:///home/conda/feedstock_root/build_artifacts/importlib-metadata_1737420181517/work
iniconfig @ file:///home/conda/feedstock_root/build_artifacts/iniconfig_1733223141826/work
Jinja2 @ file:///home/conda/feedstock_root/build_artifacts/jinja2_1741263328855/work
lxml @ file:///home/conda/feedstock_root/build_artifacts/lxml_1739211551675/work
MarkupSafe @ file:///home/conda/feedstock_root/build_artifacts/markupsafe_1733219680183/work
mccabe @ file:///home/conda/feedstock_root/build_artifacts/mccabe_1733216466933/work
netCDF4 @ file:///home/conda/feedstock_root/build_artifacts/netcdf4_1733253078561/work
numpy @ file:///home/conda/feedstock_root/build_artifacts/numpy_1732314280888/work/dist/numpy-2.0.2-cp39-cp39-linux_x86_64.whl#sha256=62d98eb3da9f13e6b227c430d01026b7427f341b3fdcb838430f2a9e520417b1
OWSLib @ file:///home/conda/feedstock_root/build_artifacts/owslib_1715612110326/work
packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1733203243479/work
pluggy @ file:///home/conda/feedstock_root/build_artifacts/pluggy_1733222765875/work
pycodestyle @ file:///home/conda/feedstock_root/build_artifacts/pycodestyle_1733216196861/work
pycparser @ file:///home/conda/feedstock_root/build_artifacts/bld/rattler-build_pycparser_1733195786/work
pyflakes @ file:///home/conda/feedstock_root/build_artifacts/pyflakes_1733216066937/work
Pygments @ file:///home/conda/feedstock_root/build_artifacts/pygments_1736243443484/work
PySocks @ file:///home/conda/feedstock_root/build_artifacts/pysocks_1733217236728/work
pytest @ file:///home/conda/feedstock_root/build_artifacts/pytest_1740946542080/work
python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1733215673016/work
pytz @ file:///home/conda/feedstock_root/build_artifacts/pytz_1742920838005/work
PyYAML @ file:///home/conda/feedstock_root/build_artifacts/pyyaml_1737454647378/work
requests @ file:///home/conda/feedstock_root/build_artifacts/requests_1733217035951/work
six @ file:///home/conda/feedstock_root/build_artifacts/six_1733380938961/work
snowballstemmer @ file:///home/conda/feedstock_root/build_artifacts/snowballstemmer_1637143057757/work
Sphinx @ file:///home/conda/feedstock_root/build_artifacts/sphinx_1721487534232/work
sphinx-autoapi==3.6.0
sphinxcontrib-applehelp @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-applehelp_1733754101641/work
sphinxcontrib-devhelp @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-devhelp_1733754113405/work
sphinxcontrib-htmlhelp @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-htmlhelp_1733754280555/work
sphinxcontrib-jsmath @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-jsmath_1733753744933/work
sphinxcontrib-qthelp @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-qthelp_1733753408017/work
sphinxcontrib-serializinghtml @ file:///home/conda/feedstock_root/build_artifacts/sphinxcontrib-serializinghtml_1733750479108/work
stdlib-list==0.11.1
tomli @ file:///home/conda/feedstock_root/build_artifacts/tomli_1733256695513/work
typing_extensions==4.13.0
urllib3 @ file:///home/conda/feedstock_root/build_artifacts/urllib3_1734859416348/work
wrapt @ file:///home/conda/feedstock_root/build_artifacts/wrapt_1736869460534/work
zipp @ file:///home/conda/feedstock_root/build_artifacts/zipp_1732827521216/work
zstandard==0.23.0

name: birdy
channels:
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=conda_forge
  - _openmp_mutex=4.5=2_gnu
  - alabaster=0.7.16=pyhd8ed1ab_0
  - babel=2.17.0=pyhd8ed1ab_0
  - blosc=1.21.6=he440d0b_1
  - boltons=24.0.0=pyhd8ed1ab_1
  - brotli-python=1.1.0=py39hf88036b_2
  - bzip2=1.0.8=h4bc722e_7
  - c-ares=1.34.4=hb9d3cd8_0
  - ca-certificates=2025.1.31=hbcca054_0
  - certifi=2025.1.31=pyhd8ed1ab_0
  - cffi=1.17.1=py39h15c3d72_0
  - cftime=1.6.4=py39hf3d9206_1
  - charset-normalizer=3.4.1=pyhd8ed1ab_0
  - click=8.1.8=pyh707e725_0
  - colorama=0.4.6=pyhd8ed1ab_1
  - dataclasses=0.8=pyhc8e2a94_3
  - docutils=0.21.2=pyhd8ed1ab_1
  - exceptiongroup=1.2.2=pyhd8ed1ab_1
  - flake8=7.1.2=pyhd8ed1ab_0
  - funcsigs=1.0.2=pyhd8ed1ab_4
  - h2=4.2.0=pyhd8ed1ab_0
  - hdf4=4.2.15=h2a13503_7
  - hdf5=1.14.4=nompi_h2d575fe_105
  - hpack=4.1.0=pyhd8ed1ab_0
  - hyperframe=6.1.0=pyhd8ed1ab_0
  - idna=3.10=pyhd8ed1ab_1
  - imagesize=1.4.1=pyhd8ed1ab_0
  - importlib-metadata=8.6.1=pyha770c72_0
  - iniconfig=2.0.0=pyhd8ed1ab_1
  - jinja2=3.1.6=pyhd8ed1ab_0
  - keyutils=1.6.1=h166bdaf_0
  - krb5=1.21.3=h659f571_0
  - ld_impl_linux-64=2.43=h712a8e2_4
  - libaec=1.1.3=h59595ed_0
  - libblas=3.9.0=31_h59b9bed_openblas
  - libcblas=3.9.0=31_he106b2a_openblas
  - libcurl=8.12.1=h332b0f4_0
  - libedit=3.1.20250104=pl5321h7949ede_0
  - libev=4.33=hd590300_2
  - libffi=3.4.6=h2dba641_1
  - libgcc=14.2.0=h767d61c_2
  - libgcc-ng=14.2.0=h69a702a_2
  - libgfortran=14.2.0=h69a702a_2
  - libgfortran5=14.2.0=hf1ad2bd_2
  - libgomp=14.2.0=h767d61c_2
  - libiconv=1.18=h4ce23a2_1
  - libjpeg-turbo=3.0.0=hd590300_1
  - liblapack=3.9.0=31_h7ac8fdf_openblas
  - liblzma=5.6.4=hb9d3cd8_0
  - libnetcdf=4.9.2=nompi_h5ddbaa4_116
  - libnghttp2=1.64.0=h161d5f1_0
  - libnsl=2.0.1=hd590300_0
  - libopenblas=0.3.29=pthreads_h94d23a6_0
  - libsqlite=3.49.1=hee588c1_2
  - libssh2=1.11.1=hf672d98_0
  - libstdcxx=14.2.0=h8f9b012_2
  - libstdcxx-ng=14.2.0=h4852527_2
  - libuuid=2.38.1=h0b41bf4_0
  - libxcrypt=4.4.36=hd590300_1
  - libxml2=2.13.7=h0d44e9d_0
  - libxslt=1.1.39=h76b75d6_0
  - libzip=1.11.2=h6991a6a_0
  - libzlib=1.3.1=hb9d3cd8_2
  - lxml=5.3.1=py39ha9b3668_0
  - lz4-c=1.10.0=h5888daf_1
  - markupsafe=3.0.2=py39h9399b63_1
  - mccabe=0.7.0=pyhd8ed1ab_1
  - ncurses=6.5=h2d0b736_3
  - netcdf4=1.7.2=nompi_py39h1defa26_101
  - numpy=2.0.2=py39h9cb892a_1
  - openssl=3.4.1=h7b32b05_0
  - owslib=0.31.0=pyhd8ed1ab_0
  - packaging=24.2=pyhd8ed1ab_2
  - pip=25.0.1=pyh8b19718_0
  - pluggy=1.5.0=pyhd8ed1ab_1
  - pycodestyle=2.12.1=pyhd8ed1ab_1
  - pycparser=2.22=pyh29332c3_1
  - pyflakes=3.2.0=pyhd8ed1ab_1
  - pygments=2.19.1=pyhd8ed1ab_0
  - pysocks=1.7.1=pyha55dd90_7
  - pytest=8.3.5=pyhd8ed1ab_0
  - python=3.9.21=h9c0c6dc_1_cpython
  - python-dateutil=2.9.0.post0=pyhff2d567_1
  - python_abi=3.9=5_cp39
  - pytz=2025.2=pyhd8ed1ab_0
  - pyyaml=6.0.2=py39h9399b63_2
  - readline=8.2=h8c095d6_2
  - requests=2.32.3=pyhd8ed1ab_1
  - setuptools=75.8.2=pyhff2d567_0
  - six=1.17.0=pyhd8ed1ab_0
  - snappy=1.2.1=h8bd8927_1
  - snowballstemmer=2.2.0=pyhd8ed1ab_0
  - sphinx=7.4.7=pyhd8ed1ab_0
  - sphinxcontrib-applehelp=2.0.0=pyhd8ed1ab_1
  - sphinxcontrib-devhelp=2.0.0=pyhd8ed1ab_1
  - sphinxcontrib-htmlhelp=2.1.0=pyhd8ed1ab_1
  - sphinxcontrib-jsmath=1.0.1=pyhd8ed1ab_1
  - sphinxcontrib-qthelp=2.0.0=pyhd8ed1ab_1
  - sphinxcontrib-serializinghtml=1.1.10=pyhd8ed1ab_1
  - tk=8.6.13=noxft_h4845f30_101
  - tomli=2.2.1=pyhd8ed1ab_1
  - tzdata=2025b=h78e105d_0
  - urllib3=2.3.0=pyhd8ed1ab_0
  - wheel=0.45.1=pyhd8ed1ab_1
  - wrapt=1.17.2=py39h8cd3c5a_0
  - yaml=0.2.5=h7f98852_2
  - zipp=3.21.0=pyhd8ed1ab_1
  - zlib=1.3.1=hb9d3cd8_2
  - zstandard=0.23.0=py39h8cd3c5a_1
  - zstd=1.5.7=hb8e6e7a_2
  - pip:
      - argcomplete==3.6.1
      - astroid==3.3.9
      - sphinx-autoapi==3.6.0
      - stdlib-list==0.11.1
      - typing-extensions==4.13.0
prefix: /opt/conda/envs/birdy

tests/test_utils.py::test_sanitize tests/test_utils.py::test_delist
tests/test_client.py::test_wps_client_backward_compability tests/test_client.py::test_interactive tests/test_client.py::test_process_subset_only_one tests/test_client.py::test_process_subset_names
tests/test_client.py::test_converter tests/test_client.py::test_jsonconverter tests/test_utils.py::test_is_url
birdy/utils.py birdy/client/utils.py birdy/client/base.py requirements_extra.txt
birdy/utils.py birdy/client/utils.py birdy/client/base.py requirements_extra.txt