Running TabPy with Python Virtual Environment

In my post How to run TabPy with Anaconda on Linux I showed how to use Anaconda to create isolated Python environments so you can have different versions of Python with different packages installed all on the same machine.

If you can not use Anaconda for any reason there is another way to separate Python environments on a machine with help of Python virtual environment package.

For steps below I am using virtual machine running CentOS:

[ogolovatyi@3250e1583c74401 ~]$ hostnamectl
...
  Operating System: CentOS Linux 7 (Core)
       CPE OS Name: cpe:/o:centos:centos:7
            Kernel: Linux 3.10.0-693.5.2.el7.x86_64
      Architecture: x86-64

All these steps with a little modifications can be used on MacOS or Windows.

To make things more interesting the machine has Python 2.7 on it:

[ogolovatyi@3250e1583c74401 ~]$ python -V
Python 2.7.5

Since TabPy requires Python 3.5 at least let’s first install it (on your Linux distribution you may need use some other package manager instead of yum):

sudo yum install python3

It is recommended to update pip with the latest version. Note that python command still will run Python 2.7. You can change that, but doing so may cause some of other commands and tools work properly. Instead I use python3 command which runs the newly installed Python 3.6.8:

sudo python3 -m pip install --upgrade pip

Now to installing virtualenv package:

python3 -m pip install virtualenv

For a virtual environment it will be created in the folder where the next command is executed:

python3 -m venv TabPy-venv

After the command above succeeds you can see TabPy-venv folder was created. You can create multiple virtual environments with using the command – just make the names unique.

To activate the environment run the following:

[ogolovatyi@3250e1583c74401 ~]$ source TabPy-venv/bin/activate

Note how command line prompt changes after the command above succeeded – now it has virtual environment name in it. Additionally python command now runs Python 3.6.8 I installed before:

(TabPy-venv) [ogolovatyi@3250e1583c74401 ~]$ python -V
Python 3.6.8

All the packages installed in the active virtual environment will be installed in the folder for the environment (TabPy-venv for the shown steps) and won’t affect “system” Python or any other Python versions or environments.

Now let’s update pip (remember it is different pip this time – the one for the virtual environment) and install TabPy:

pip install --upgrade pip
...
pip install tabpy

If you check where the TabPy is installed you’ll see something like this:

(TabPy-venv) [ogolovatyi@3250e1583c74401 ~]$ whereis tabpy
tabpy: /home/....../ogolovatyi/TabPy-venv/bin/tabpy

To start TabPy run the usual tabpy command or specify config for TabPy (more details at TabPy: modifying default configuration).

And to exit virtual environment simply run deactivate command.

Additional information about virtualenv can be found at https://virtualenv.pypa.io/en/stable/.

TabPy: Using Deployed Functions from Deployed Functions

If you don’t know what deployed functions in TabPy are consider reading the following:

With this post I’ll demonstrate with extremely simplified code how to use already deployed functions in other deployed functions.

Assuming TabPy is running on localhost machine and port 9004 in Python session I create and deploy simple function which capitalizes first letter of each string in the input parameter:

def my_func_1(s):
  return [x.capitalize() for x in s]

from tabpy.tabpy_tools.client import Client
client = Client('http://localhost:9004')
client.deploy('MyFunction1', my_func_1, 'Capitalize first letter of each string')

When the above is executed there is a function deployed which is accessible with Tableau SCRIPT_...('return tabpy.query('MyFunction1', _arg1)['response']', ...) expression. But what we are looking for is calling that function from another function.

When a function is deployed it is available in TabPy context for user script meaning you can use function name (the name the function was declared with, not the name given to when deployed). Here is how the function can be called:

def my_func_2(s):
  c = my_func_1(s)
  return ['_' + x + '_' for x in c]

client.deploy('MyFunction2', my_func_2, 'Underscore and capitalize each string')

Things to pay attention in the code sample above:

  1. The first deployed function is called by its Python name my_func_1 and not with the name it deployed with.
  2. Deployed functions (both MyFunction1 and MyFuction2) are used in Tableau calculations with their deployed names:

One caution I need to make here: How deployed functions are presented and accessible in the context of a script running in TabPy is not documented and not guaranteed to work in the future. The recommended way to reuse Python code is to create packages or use standalone modules as explained in How to use Python modules for TabPy scripts in Tableau post.

How to use Python modules for TabPy scripts in Tableau

TabPy supports deployed functions which are recommended way for reusing Python code, creating and sharing models and moving code form SCRIPT_... calculated fields outside of workbooks. However when working or experimenting with code it is not very convenient if you’ll have to deploy new version of a function with every change. And this is why you may have a question if it is possible just to invoke some code from standalone Python file.

And it is possible! Let me show you how.

The files with Python function(s) in them should be on the same machine where your instance of TabPy is running. Let’s create simple file with couple of simple functions in it:

def my_add_lists(list1, list2):
    return [x + y for x, y in zip(list1, list2)]

def my_inc_list_items(list1):
    return [x + 1 for x in list1]

For Python to be able to find the module (my_python_functions.py file) we need to set up environment variable PYTHONPATH. As explained in Python documentation (https://docs.python.org/3/using/cmdline.html#environment-variables) PYTHONPATH augments where Python is looking for modules when they are referenced with import. The variable needs to be set before TabPy is started.

For Windows the variable can be set in command line:

set PYTHONPATH=%PYTHONPATH%;<my-python-functions-folder>

where <my-python-functions-folder> is the path to where your Python module(s) are located, e.g.:

set PYTHONPATH=%PYTHONPATH%;c:\user\ogolovatyi\python\tabpy-experiments

For Linux and Mac the variable can be set similarly:

export PYTHONPATH=$PYTHONPATH:<my-python-functions-folder>

Now in calculated fields you can import the modules and use functions from them. For example:

SCRIPT_INT(
"
from my_python_functions import my_add_lists

return my_add_lists(_arg1, _arg2)
",
SUM([Price]), SUM([Tax])
)

In the example above from my_python_functions import my_add_lists tells Python to load my_python_functions module (which will be my_python_functions.py file in the folder we previously added to PYTHONPATH) and load my_add_lists function from it.

After that the function is used in the calculation.

Hope this simple example is helpful for you when working on Python code to be used in Tableau calculations.

How to run TabPy with Anaconda on Linux

What Anaconda is can be explained in many ways depending on how and what you use is for. In the case of TabPy Anaconda serves as Python environments manager which allows having different Python environments (different versions of Python with a different set of packages) on the same machine. To learn more about Anaconda and where it can be used to start at https://www.anaconda.com/.

First question to ask is why you may need to use Python environments. There are many reasons. Couple of the most important are:

  • Your OS may have old version of “system wide” Python (e.g. Python 2.7) and it is not easy (or not possible at all) to update it without breaking something, and
  • You may want to isolate TabPy environment with packages it needs from your other environment (development, training models, etc.), or
  • You may want to have multiple independent TabPy instances each with their own set of packages awailable.

To manage Python environments Anaconda is not the only option, you can use Python virtualenv tools for example – https://virtualenv.pypa.io/en/latest/. However Anaconda has some advantages like nice UI app to manages environments and packages, saving/restoring/sharing enviroments, support for R environments, etc.

And when for Windows and Mac you can use UI app in many cases for Linux GUI is not an option. In other words you will need to use command line. And this is what rest of this post shows how to do.

After login to a Linux machine, you need to download Anaconda installer from https://www.anaconda.com/distribution/. The following commands assume you are in your home folder (run cd ~ to navigate to your home folder). On the Anaconda distribution page find the link for the latest version for Linux and run the following command:

wget https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh

Now when you have the installer in your home folder run it:

bash Anaconda3-2020.02-Linux-x86_64.sh

When the installer finishes add path to the Anaconda to the environment variable (this assumes bash is your Linux shell):

echo 'export PATH="~/anaconda3/bin:$PATH"' >> ~/.bashrc

In the command above we add anaconda3 subfolder bin from the user home folder to environment variable PATH so anaconda commands can be found regardless of what is the current folder. If you installed Anaconda in a different location the command need to be modified properly.

Now let’s restart shell (or you can unlog and log in again):

source ~/.bashrc

Next let’s update Anaconda:

conda update conda

In the command above conda is the tool which will let us perform different Anaconda operations.

Next step is to create new environment for TabPy:

conda create --name TabPy python=3.7

What happens in the command above is new environment with name TabPy is created and it has Python 3.7 available for it.

You can have as many environments as you need with different or the same Python versions. As all of them are isolated and do not interfere it is possible to have different sets of packages or the same packages of different versions in them.

Now we can activate the environment:

conda activate TabPy

If the command succeeds you’ll the command prompt is updated to have the environment name in it.

And now you can install TabPy and other packages:

python -m pip install --upgrade
pip install tabpy
tabpy

To exit from the environment run deactivate command:

conda deactivate

For how to configure TabPy read https://tabscifi.golovatyi.info/2020/01/tabpy-modifying-default-configuration/.