13 Replies Latest reply on Sep 5, 2019 2:21 AM by mingxin rong

    Publish tableau workbooks using python

    Sabari A

      Hi,

       

      I am trying to publish multiple tableau workbooks using python. I have many workbooks that are present in a folder and I want to publish it to tableau server using a python code that will upload the workbooks overnight one after other. I have successfully achieved it for a different set of workbooks, but for this set I am getting an error as "Could not obtain lock on ' " .

       

      My code works for a different set of workbooks but fails for the other set. I am not sure what this error means and why my python code is failing.

       

      Looking forward for suggestions. Thanks in advance for the great help.

       

      Thanks

        • 1. Re: Publish tableau workbooks using python

          Hi Sabari A,

           

          Could you please first try to refresh your extract in the workbook?

          Let me know how it goes

           

          ----------

          Lénaïc RIÉDINGER, Global Community Engineer Tableau

          Tableau Community Forums | Knowledge Base

          If you see a Helpful or Correct response, please mark it thanks to the buttons below the targeted post!

           

          • 2. Re: Publish tableau workbooks using python
            Sabari A

            Hi Lenaic,

             

            I tried refreshing the extracts and I am still getting the same error. The problem here is some workbooks get published when I run the same code for the second time but this time a different set of workbooks gets failed to publish.

             

            Thanks

            • 3. Re: Publish tableau workbooks using python
              Israel Curiel

              I'm trying to synchronize our workbooks from our production environment to our Business Continuity Plan server (BCP). I'm able to download my production workbooks and loop through all the connections. When the code is run I receive no error but the workbooks are not published. Can you share the code you used? Below is the function I'm using.

               

              def SyncWorkbooksAcrossServers(source_server_name, destination_server_name, username, logging_level):
                  #This function currently downloads all the workbooks from the server and project
                  #The example of this program was derived from https://github.com/tableau/server-client-python/blob/master/samples/move_workbook_projects.py
                  #I also used this page for publishing the workbook https://github.com/tableau/server-client-python/blob/master/samples/publish_workbook.py
                 
                  #password = getpass.getpass("Password: ")
                  logging_level = logging_level.upper()
                  
                  # Set logging level based on user input, or error by default
                  logging.basicConfig(level=logging_level)
                   
                  # Step 1: Sign in to both sites on server
                  tableau_auth = TSC.TableauAuth(username, password)
                  source_server = TSC.Server(source_server_name)
                  source_server.add_http_options({'verify': False})
                 
                  dest_server = TSC.Server(destination_server_name)
                  dest_server.add_http_options({'verify': False})
                  dest_server.auth.sign_in(tableau_auth)
                  default_project_ID = "b2d621ae-0d5c-48cc-a1de"
                 
                  overwrite_true = TSC.Server.PublishMode.Overwrite
                    
                  # Step 2: Create directory to download all the report files to.
                  tmpdir = tempfile.mkdtemp()
                  print(tmpdir)
                 
                 
                  with source_server.auth.sign_in(tableau_auth):
                      src_site_id = source_server.site_id
                     
                      # Step 2: Query workbook to move
                      req_option = TSC.RequestOptions()
                      #req_option.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
                      #                                 TSC.RequestOptions.Operator.Equals, workbook_name))     
                      #all_workbooks, pagination_item = source_server.workbooks.get(req_option)
                     
                      all_workbooks, pagination_item = source_server.workbooks.get()
                     
                      # Step 3: Download workbook to a temp directory

                      if len(all_workbooks) == 0:
                          print('No workbook named {} found.'.format(workbook_name))
                      else:

                          try:
                             
                              #Loop through all workbooks
                              for workbook in all_workbooks:
                                                    
                                  if(workbook.project_name == 'Corporate Dashboards' and workbook.name == "Performance Workbook"):
                                      print("Name: " + workbook.name + " Project: " + workbook.project_name + " WorkbookID: " + str(workbook.id) )
                                      workbook_path = source_server.workbooks.download(workbook.id, tmpdir)
                                      print(workbook_path)
                                     
                                      #wb_dict_ = dir(workbook)
                                      #print(wb_dict_)
                                     
                                      source_server.workbooks.populate_connections(workbook)
                                      print("Total Connections: " + str(len(workbook.connections)))
                                     
                                      #Create a container for all connections
                                      all_connections = list()
                                         
                                      for conn in workbook.connections:           
                                          #Replace all the production connections with BCP connections.
                                          #if (conn.connection_type == "teradata") and (conn.server_address == "myprodserver.com"):
                                          #    conn.server_address = "mybcpserver.com"
                                          #    workbook.connections.update(conn)

                                          newConnection = ConnectionItem()
                                          newConnection.server_address = conn.server_address
                                          newConnection.connection_credentials = ConnectionCredentials(conn.username, conn.password, True)
                                          all_connections.append(newConnection)
                     
                                          #conn_dict_ = dir(conn)
                                          #print(conn_dict_)
                                          #conn_cred = conn.connection_credentials
                                          #cc = dir(conn_cred)
                                          #print(cc)
                                         
                                      new_workbook = TSC.WorkbookItem(default_project_ID)
                                      new_workbook = dest_server.workbooks.publish(new_workbook, workbook_path, overwrite_true, connections=all_connections, as_job=0)

                                      print("-Workbook published Name: ",workbook.name, " -Workbook ID: ",workbook.id)

                             
                          finally:
                             
                              print("All Done")                  
                              os.system(tmpdir.replace('\\', '/'))
                              return "Added Workbook: " + workbook.name

              • 4. Re: Publish tableau workbooks using python
                mingxin rong

                Hi ISRAEL ,

                 

                Your function is very useful. Do you know why I am having such problem as below? Code as last part

                 

                1. endpoint.py:153: UserWarning: 'connections' not available in 2.3, it will be ignored. Added in 2.8

                          warnings.warn(error).

                 

                1. 403007: Forbidden Sample failed to establish a connection to your datasource.

                ________________

                Many thanks.

                Soldier

                 

                ————————————————————————————————

                with server.auth.sign_in(tableau_auth):

                 

                   # Step 2: Get all the projects on server, then look for the default one.
                   all_projects, pagination_item = server.projects.get()

                 

                  all_workbooks, pagination_item2 = server.workbooks.get()

                  default_project = next((project for project in all_projects if project.is_default()), None)

                 

                   print([workbook.name for workbook in all_projects])

                   print("\n")


                   connection2 = ConnectionItem()

                  connection2.server_address = "XXXX"
                   connection2.server_port = "54568"
                   connection2.connection_credentials = ConnectionCredentials("USERNAME", "PASSWORD", True)

                  # the username and password have been blocked

                  all_connections = list()

                  all_connections.append(connection2)

                   print(all_connections)

                   if default_project is not None:

                  wb_item = TSC.WorkbookItem(name='Sample', project_id='18552078-f77a-446e-819f-416270d8a2e1')


                   wb_item = server.workbooks.publish(wb_item, r'C:\Users\ASNPIBZ\Desktop\Publish tableau using python\Book1.twb','Overwrite', connections=all_connections)

                 

                   else:

                  error = "The default project could not be found."
                   raise LookupError(error)

                • 5. Re: Publish tableau workbooks using python
                  Ross Helenius

                  sounds like a versioning issue with what you are trying to call Versions-Tableau Server REST API - Tableau

                   

                  what version of server are you running?

                  1 of 1 people found this helpful
                  • 6. Re: Publish tableau workbooks using python
                    mingxin rong

                    Hi Ross  ,

                     

                    Thanks for you view.

                    My server is  2018.3 &Linux.

                     

                    How can i check what's the root issue cause it.

                     

                    Many thanks.

                    • 7. Re: Publish tableau workbooks using python
                      mingxin rong

                      Hi Ross ,

                       

                      As your advise ,i have added  the version as below:

                       

                      Partial code :

                      # Step 1: Sign in to server.
                      tableau_auth = TSC.TableauAuth(args.username, password)

                      server = TSC.Server(args.server)

                      server.version = '3.2'

                      with server.auth.sign_in(tableau_auth):

                       

                      # Step 2: Get all the projects on server, then look for the default one

                      .

                      .

                      .

                       

                       

                      error as below :

                      [<ConnectionItem#None embed=None type=None username=None>]

                      Traceback (most recent call last):

                        File "test.py", line 94, in <module>

                          wb_item = server.workbooks.publish(wb_item, r'C:\Users\ASNPIBZ\Desktop\Publish tableau using python\Book1.twb','Overwrite', connections=all_connections)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 116, in wrapper

                          return func(self, *args, **kwargs)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 154, in wrapper

                          return func(self, *args, **kwargs)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 154, in wrapper

                          return func(self, *args, **kwargs)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\workbooks_endpoint.py", line 281, in publish

                          server_response = self.post_request(url, xml_request, content_type)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 91, in post_request

                          content_type=content_type)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 54, in _make_request

                          self._check_status(server_response)

                        File "C:\Users\ASNPIBZ\Desktop\PUBLIS~1\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py", line 68, in _check_status

                          raise ServerResponseError.from_response(server_response.content, self.parent_srv.namespace)

                      tableauserverclient.server.endpoint.exceptions.ServerResponseError:

                       

                       

                              403007: Forbidden

                                      Sample failed to establish a connection to your datasource.

                      • 8. Re: Publish tableau workbooks using python
                        Ross Helenius

                        Looks like an authentication issue to your datasource, if you connect via desktop and publish manually does it work using the supplied credentials?

                        • 9. Re: Publish tableau workbooks using python
                          mingxin rong

                          Yes ,when i publish this datasource in the tableau Desktop ,it's ok

                          • 10. Re: Publish tableau workbooks using python
                            Ross Helenius
                            import tableauserverclient as TSC
                            from tableauserverclient import ConnectionCredentials, ConnectionItem
                            
                            
                            # Step 1: Sign in
                            tableau_auth = TSC.TableauAuth('user', 'pw')
                            server = TSC.Server('serveraddress')
                            server.add_http_options({'verify': False})
                            
                            
                            overwrite_true = TSC.Server.PublishMode.Overwrite
                            
                            
                            with server.auth.sign_in(tableau_auth): 
                                # Step 2: Get all the projects on server, then look for the default one.
                                all_projects, pagination_item = server.projects.get()
                                
                                all_workbooks, pagination_item2 = server.workbooks.get()
                                
                                default_project = next((project for project in all_projects if project.is_default()), None)
                                
                                print([project.name for project in all_projects])
                                print("\n")
                                 
                                connection1 = ConnectionItem()    
                                connection1.server_address = "address"
                                connection1.server_port = "port"
                                connection1.connection_credentials = ConnectionCredentials("un here", "pw here", True)
                                
                                all_connections = list()
                                all_connections.append(connection1)
                                
                                print(vars(connection1))
                                
                                if default_project is not None:
                                    wb_item = TSC.WorkbookItem(default_project.id)
                                    wb_item = server.workbooks.publish(wb_item, r'C:\Book1.twb',overwrite_true, connections=all_connections)
                                
                                else:
                                    error = "The default project could not be found."
                                    raise LookupError(error)
                            

                             

                            This worked fine for me.

                            • 11. Re: Publish tableau workbooks using python
                              mingxin rong

                              Thanks Ross.

                               

                              I think my script is almost the same as yours, but i also exist such error :

                               

                              ['Default', 'Tableau Samples', 'Healthy Improvement', 'test']

                              C:\Users\ASNPIBZ\Desktop\Publish tableau using python\venv\lib\site-packages\tableauserverclient\server\endpoint\endpoint.py:153: UserWarning: 'connections' not available in 2.3, it will be ignored. Added in 2.8

                                warnings.warn(error)

                              {'_datasource_id': None, '_datasource_name': None, '_id': None, '_connection_type': None, 'embed_password': None, 'password': None, 'server_address': 'ttttttt', 'server_port': '34356', 'username': None, 'connection_credentials':

                               

                              1. code:

                              import tableauserverclient as TSC

                              from tableauserverclient import ConnectionCredentials, ConnectionItem

                               

                              # Step 1: Sign in to server.

                              tableau_auth = TSC.TableauAuth('tt', 'l8QFq')

                              server = TSC.Server('xxxxx')

                              server.add_http_options({'verify': False})

                              overwrite_true = TSC.Server.PublishMode.Overwrite

                               

                              with server.auth.sign_in(tableau_auth):

                                  # Step 2: Get all the projects on server, then look for the default one.

                                  all_projects, pagination_item = server.projects.get()

                               

                                  all_workbooks, pagination_item2 = server.workbooks.get()

                                  default_project = next((project for project in all_projects if project.is_default()), None)

                                  print([project.name for project in all_projects])

                                  print("\n")

                               

                                  connection2 = ConnectionItem()

                                  connection2.server_address = "xxxx"

                                  connection2.server_port = "xxxx"

                                  connection2.connection_credentials = ConnectionCredentials("xxx", "xxxx", True)

                               

                                  all_connections = list()

                                  all_connections.append(connection2)

                               

                                  print(vars(connection2))

                               

                                  if default_project is not None:

                                      wb_item = TSC.WorkbookItem(default_project.id)

                                      wb_item = server.workbooks.publish(wb_item, r'C:\Users\xxx\Desktop\Publish tableau using python\Book1.twb',overwrite_true, connections=all_connections)

                               

                                  else:

                                      error = "The default project could not be found."

                                      raise LookupError(error)

                               

                              1. The package on this project:

                              • 12. Re: Publish tableau workbooks using python
                                mingxin rong

                                another error :

                                 

                                tableauserverclient.server.endpoint.exceptions.ServerResponseError:

                                400011: Bad Request

                                There was a problem publishing the file 'Book1.twb'.

                                • 13. Re: Publish tableau workbooks using python
                                  mingxin rong

                                  Hi Ross ,

                                   

                                  Actually ,we need to enter multiple password when we publish a report with multiple data sources(e.g. tableau server & oracle DB),It’s very troublesome to do this.

                                   

                                  So ,i want to publish such workbook by python.