Python to Tableau Hyper publishing

Using Python, you can automate the publishing of new (or updated) data to Tableau Server or Tableau Cloud.  A lot of my clients use Tableau Cloud, and recently Tableau has started enforcing the MFA security policies and along with that you can no longer use username/password combinations to login and publish the new data.

Now you need a Personal Access Token (PAT) in order to authenticate your session and publish the data source properly.

Tableau’s suite of APIs let you do a lot of other tasks programmatically, but if you want to learn how to publish a data source here’s how:

				
					from tableauhyperapi import *
import pandas as pd
import tableauserverclient as TSC

POD_NAME = 'https://prod-what-is-your-pod.online.tableau.com'
SITE_NAME = 'site-name'
project_name = 'project-name'
hyper_name = 'name_of_your_published_data_source.hyper'

PAT_NAME = 'create-your-PAT'
PAT_SECRET = 'PAT-secret'

data = {
    'col1': [1, 2, 3],
    'col2': ['a', 'b', 'c'],
    'col3': [True, False, True],
    'col4': [1.0, 2.5, 3.8],
    'col5': pd.date_range(start='2022-01-01', periods=3),
}

df = pd.DataFrame(data)

# Set up a connection to a new Hyper file
with HyperProcess(telemetry=Telemetry.DO_NOT_SEND_USAGE_DATA_TO_TABLEAU) as hyper:
    with Connection(hyper.endpoint, hyper_name, CreateMode.CREATE_AND_REPLACE) as connection:
        connection.catalog.create_schema('Extract')

        # Define the table schema
        table_definition = TableDefinition(
            table_name='Testing',
            columns=[
                TableDefinition.Column('col1', SqlType.int()),
                TableDefinition.Column('col2', SqlType.text()),
                TableDefinition.Column('col3', SqlType.bool()),
                TableDefinition.Column('col4', SqlType.double()),
                TableDefinition.Column('col5', SqlType.date())
            ]
        )

        connection.catalog.create_table(table_definition)

        with Inserter(connection, table_definition) as inserter:
            for index, row in df.iterrows():
                inserter.add_row(row)
            inserter.execute()

# Sign in to server
tableau_auth = TSC.PersonalAccessTokenAuth(PAT_NAME, PAT_SECRET, SITE_NAME)

server = TSC.Server(POD_NAME, use_server_version=True)

server.auth.sign_in(tableau_auth)

# Define publish mode - Overwrite, Append, or CreateNew
publish_mode = TSC.Server.PublishMode.Overwrite

# Get project_id from project_name
all_projects, pagination_item = server.projects.get()
for project in TSC.Pager(server.projects):
    if project.name == project_name:
        project_id = project.id

# Create the datasource object with the project_id
datasource = TSC.DatasourceItem(project_id)

print(f"Publishing {hyper_name} to {project_name}...")
# Publish datasource
datasource = server.datasources.publish(datasource, hyper_name, publish_mode)
print("Datasource published. Datasource ID: {0}".format(datasource.id))

server.auth.sign_out()
				
			

So how do you use this?

Copy the code and then change:

Line 5 / POD_NAME : your pod name, pretty obvious

Line 6 / SITE_NAME : still part of the URL, but you must use this (even if you’re using Tableau Server)

Line 7 / project_name : Make sure it’s unique in the site, but you will see the code that converts the project_name into project_id (lines 57-61)

Line 8 / hyper_name : the local filename, that also becomes the name of your published data source

Line 10 / PAT_NAME : the name of the PAT you have created.  At the time of writing, if you use Tableau Cloud these can disappear without notice.

Line 11 / PAT_SECRET : make sure you copy this when you see it, you will never get access again.

Learn how to create a PAT here

As with any coding, there is multiple ways to achieve the same result.  Please change the code to match your requirements and let me know what you’ve done.

Leave a Reply

Your email address will not be published. Required fields are marked *