Skip to content

Latest commit

 

History

History
648 lines (483 loc) · 32.5 KB

File metadata and controls

648 lines (483 loc) · 32.5 KB
title Publish and Consume Python Code| Microsoft Docs
ms.custom
ms.date 04/14/2017
ms.prod sql-server-2016
ms.reviewer
ms.suite
ms.technology
r-services
ms.tgt_pltfrm
ms.topic article
author jeannt
ms.author jeannt
manager jhubbard

Publish and consume Python web services

Applies to: SQL Server vNext CTP 2.0 (Public Preview)

You can deploy a working Python solution to a web service by using the operationalization feature in Microsoft Machine Learning Server.

This topic describes the steps to follow, to successfully publish and then run your solution.

The target audience for this article is data scientists who want to learn how to publish Python code or models as web services hosted in Microsoft Machine Learning Server. The article also explains how applications can consume the the code or models. This article assumes that you are proficient in Python.

Important

Python web services are available only with Python-enabled installs of SQL Server vNext CTP 2.0 (Public Preview). Availability of this feature will be expanded in future releases.

Overview of workflow

The workflow from publishing to consuming a Python web service can be summarized as follows:

  1. Fulfill the prerequisite of generating the Python client library from the core API Swagger document.
  2. Add authentication and header logic to your Python script.
  3. Create a Python session, prepare the environment, and create a snapshot to preserve the environment.
  4. Publish the web service and embed this snapshot.
  5. Try out the web service by consuming it in your session.
  6. Manage these services.

Swagger workflow

This article discusses each step of the workflow, and includes sample Python code using the iris dataset.

Sample Code

This sample code assumes you have satisfied the prerequisites to generate a Python client library from that Swagger file and that you've used Autorest.

After the code block, you'll find a step-by-step walkthrough with more detailed description of each steo in the process.

Important

This example uses the local admin account for authentication. However, you should substitute the credentials and authentication method configured by your administrator.

##################################################
##       IMPORT GENERATED CLIENT LIBRARY        ##
##################################################

# Import the generated client library. 
import deployrclient

##################################################
##              AUTHENTICATION                  ##
##################################################

#Using client library generated from Autorest
#Create client instance and point it at an R Server. 
#In this case, R Server is local.
client = deployrclient.DeployRClient("http://localhost:12800")

#Define the login request and provide credentials 
#Update values with the connection parameters from your admin
login_request = deployrclient.models.LoginRequest("<<your-username>>","<<your-password>>")

#Make a call to the /login API. 
#Store the returned an access token in a variable.
token_response = client.login(login_request)

#Add the returned access token to the headers variable.
headers = {"Authorization": "Bearer {0}".format(token_response.access_token)}

#Verify that the server is running.
#Remember to include `headers` in every request!
status_response = client.status(headers) 
print(status_response.status_code)


##################################################
##        CREATE SESSION, MODEL, SNAPSHOT       ##
##################################################

#Since already logged in, create a Python session.
#Define session using name (`Session 1`) and `runtime_type="Python"`.
#Remember to specify the Python runtime type.
create_session_request = deployrclient.models.CreateSessionRequest("Session 1", runtime_type="Python")

#Make the call to start the session. 
#Remember to include headers in every method call to the server.
#Returns a session ID.
response = client.create_session(create_session_request, headers) 
   
#Store the session ID in a variable called `session_id` 
#to be able to identify it later at execution time.
session_id = response.session_id

#Create model - Import SVM and datasets from the SciKit-Learn library
execute_request = deployrclient.models.ExecuteRequest("from sklearn import svm\nfrom sklearn import datasets")
execute_response = client.execute_code(session_id,execute_request, headers)
#Report if it was a success
execute_response.success
   
#Define the untrained Support Vector Classifier (SVC) object
#and the dataset to be preloaded.
execute_request = deployrclient.models.ExecuteRequest("clf=svm.SVC()\niris=datasets.load_iris()\nnames={0:'I. setosa',1:'I. versicolor',2:'I. virginica'}")
#Now, go create the object and preload Iris Dataset in R Server
execute_response = client.execute_code(session_id,execute_request, headers)
#Report if it was a success
execute_response.success
   
#Define two rows from the Iris Dataset as a sample for scoring
workspace_object = deployrclient.models.WorkspaceObject("species_1",[7,3.2,4.7,1.4])
workspace_object_2 = deployrclient.models.WorkspaceObject("species_2",[3,2.6,3,2.5])

#Define how to train the classifier model; what to predict; what to return
execute_request = deployrclient.models.ExecuteRequest(
    "clf.fit(iris.data, iris.target)\n"+
    "result=clf.predict(species_1)\n"+
    "other_result=clf.predict(species_2)",
    [workspace_object,workspace_object_2], #Input
    ["result", "other_result"]) #Output

#Now, go train that model on the Iris Dataset in R Server
execute_response = client.execute_code(session_id,execute_request, headers)

#If successful, print name and result of each output parameter. Else, print error.
if(execute_response.success):
    for result in execute_response.output_parameters:
        print("{0}: {1}".format(result.name,result.value))
else:
    print (execute_response.error_message)

#Create a snapshot of the current session
response = client.create_snapshot(session_id, deployrclient.models.CreateSnapshotRequest("Iris Snapshot"), headers)
#Return the snapshot ID for reference when you publish later.
response.snapshot_id
#If you forget the ID, list every snapshot to get the ID again.
for snapshot in client.list_snapshots(headers):
    print(snapshot)

##################################################
##        PUBLISH AS A SERVICE IN PYTHON        ##
##################################################

#Define a web service that determines the iris species by scoring 
#a vector of sepal length and width, petal length and width

#Set `flower_data` for the sepal and petal length and width
flower_data = deployrclient.models.ParameterDefinition(name = "flower_data", type = "vector")
#Set `iris_species` for the species of iris
iris_species = deployrclient.models.ParameterDefinition(name = "iris_species", type = "vector")

#Define the publish request for the web service and its arguments.
#Specify the code, inputs, outputs, and snapshot.
#Don't forget to set runtime_type="Python"`.
publish_request = deployrclient.models.PublishWebServiceRequest(
       code = "iris_species = [names[x] for x in clf.predict(flower_data)]", 
       input_parameter_definitions = [flower_data], 
       output_parameter_definitions = [iris_species],
       runtime_type = "Python",
       snapshot_id = response.snapshot_id)

#Publish the service using the specified name (iris), version (V1.0)
client.publish_web_service_version("Iris", "V1.0", publish_request, headers)

##################################################
##           CONSUME SERVICE IN PYTHON          ##
##################################################

# Inspect holdings and metadata for service Iris V1.0.
for service in client.get_web_service_version("Iris","V1.0", headers):
    #print service metadata (description, who published,...)
    print(service)
    #Print input and output parameters as defined in service definition object
    print("Input Parameters: {0}".format([str(parameter) for parameter in service.input_parameter_definitions]))
    print("Output Parameters: {0}".format([str(parameter) for parameter in service.output_parameter_definitions]))

#Import the requests library to make requests on the server
import requests
#Import the JSON library to use for pretty printing of json responses
import json

#Create a requests `Session` object.
s = requests.Session()

#Record the R Server endpoint URL hosting the web services you created before
url = "http://localhost:12800"

#Give the request.Session object the authentication headers 
#so you don't have to repeat it with each request.
s.headers = headers

#Retrieve the service-specific swagger file using the requests library.
swagger_resp = s.get(url+"/api/Iris/V1.0/swagger.json")

#Either, download service-specific swagger file using the json library.
with open('iris_swagger.json','w') as f:
   (json.dump(client.get_web_service_swagger("Iris","V1.0",headers),f, indent = 1))

#Or, print just what you need from the Swagger file, 
#such as the routing paths for the endpoints to be consumed.
print(json.dumps(swagger_resp.json()["paths"], indent = 1, sort_keys = True))

#Or, print input and output parameters as defined in the Swagger.io format
print("Input")
print(json.dumps(swagger_resp.json()["definitions"]["InputParameters"], indent = 1, sort_keys = True))
print("Output")
print(json.dumps(swagger_resp.json()["definitions"]["WebServiceResult"], indent = 1, sort_keys = True))

#Make the request to consume the service using these flower_data inputs
resp = s.post(url+"/api/Iris/V1.0",json={"flower_data":[7,3.2,4.7,1.4]})
#Print the output
print(json.dumps(resp.json(), indent = 1, sort_keys = True))

#Use input from another Iris species.
resp = s.post(url+"/api/Iris/V1.0",json={"flower_data":[3,2.6,3,2.5]})
print(json.dumps(resp.json(), indent = 1, sort_keys = True))

#Use input from another Iris species.
resp = s.post(url+"/api/Iris/V1.0",json={"flower_data":[5.1,3.5,1.4,.2]})
print(json.dumps(resp.json(), indent = 1, sort_keys = True))

##################################################
##          MANAGE SERVICES IN PYTHON           ##
##################################################

#Define what needs to be updated. Here we add a description.
#Be sure to specify the runtime_type again.
update_request = deployrclient.models.PublishWebServiceRequest(
    description = "Determines iris species using length and width of sepal and petal", runtime_type = "Python")
#Now update it by specifying the service name and version number
client.patch_web_service_version("Iris", "V1.0", update_request, headers)

#Or, publish another version of the web service, but this time 
#the service returns the species as a string instead of list of strings.
flower_data = deployrclient.models.ParameterDefinition(name = "flower_data", type = "vector")
iris_species = deployrclient.models.ParameterDefinition(name = "iris_species", type = "string")
 
#Define the publish request for the service and its arguments.
#Specify the changed code, inputs, outputs, and snapshot.
#Don't forget to set runtime_type="Python"`.
publish_request = deployrclient.models.PublishWebServiceRequest(
    code = "iris_species = [names[x] for x in clf.predict(flower_data)][0]",
    description = "Determines the species of iris, based on Sepal Length, Sepal Width, Petal Length and Petal Width",
    input_parameter_definitions = [flower_data],
    output_parameter_definitions = [iris_species],
    runtime_type = "Python",
    snapshot_id = response.snapshot_id)
 
#Now, publish the service with version (V2.0)
client.publish_web_service_version("Iris", "V2.0", publish_request, headers)
 
#Make request to consume service using these flower_data inputs; print output
resp = s.post(url+"/api/Iris/V2.0",json={"flower_data":[5.1,3.5,1.4,.2]})
print(json.dumps(resp.json(), indent = 1, sort_keys = True))

#Return the list of all existing web services.
for service in client.get_all_web_services(headers):
    #print the service information
    print(service)
    #Print each input and output parameter
    print("Input Parameters: {0}".format([str(parameter) for parameter in service.input_parameter_definitions]))
    print("Output Parameters: {0}".format([str(parameter) for parameter in service.output_parameter_definitions]))

#Delete the second version we just published.
client.delete_web_service_version("Iris","V2.0",headers)

Walkthrough

This section describes how the code works in more detail.

Step 1. Create prerequisite client libraries

Before you can start publishing your Python code and models thorugh Microsoft Machine Learning Server, you must generate a client library using the Swagger document provided for this release.

  1. Install a Swagger code generator on your local machine and familiarize yourself with it. You will use it to generate the API client libraries in Python. Popular tools include Azure AutoRest (requires Node.js) and Swagger Codegen.

  2. Download the Swagger file containing the core APIs for your version of Machine Learning Server. This file contains a Swagger template defining the list of REST resources and the operations that can be called on those resources. You can find this file under https://microsoft.github.io/deployr-api-docs/swagger/<version>/rserver-swagger-<version>.json, where <version> is the 3-digit R Server version number.

    For example, for R Server 9.1 you would download from: https://microsoft.github.io/deployr-api-docs/9.1.0/swagger/rserver-swagger-9.1.0.json

  3. Generate the statically-generated client library by passing the rserver-swagger-<version>.json file to the Swagger code generator and specifying the language you want. In this case, you should specify Python.

    For example, if you use AutoRest to generate a Python client library, it might look like this, where the 3-digit number represents the R Server version number:

    AutoRest.exe -Input rserver-swagger-9.1.0.json -CodeGenerator Python -OutputDirectory C:\Users\rserver-user\Documents\Python

    You can now provide some custom headers and make other changes before using the generated client library stub. See the Command Line Interface documentation on GitHub for details regarding different configuration options and preferences, such as renaming the namespace.

  4. Explore the core client library to see the various API calls you can make.

    In our example, Autorest generated some directories and files for the Python client library on your local system. By default, the namespace (and directory) is deployrclient and might look like this:

    Autorest output path

    For this default namespace, the client library itself is called deploy_rclient.py. If you open this file in your IDE such as Visual Studio, you will see something like this:

    Python client library

Step 2. Add authentication and header logic

Keep in mind that all APIs require authentication; therefore, all users must authenticate when making an API call using the POST /login API or through Azure Active Directory (AAD).

To simplify this process, bearer access tokens are issued so that users need not provide their credentials for every single call. This bearer token is a lightweight security token that grants the “bearer” access to a protected resource: in this case, the Machine Learning Server's APIs. After a user has been authenticated, the application must validate the user’s bearer token to ensure that authentication was successful for the intended parties. To learn more about managing these tokens, see Security Access Tokens.

Before you interact with the core APIs, first authenticate, get the bearer access token using the authentication method configured by your administrator, and then include it in each header for each subsequent request:

  1. Get started by importing the client library to make it accessible from your preferred Python code editor, such as Jupyter, Visual Studio, VS Code, or iPython.

    Specify the parent directory of the client library. In our example, the Autorest generated client library is under C:\Users\rserver-user\Documents\Python\deployrclient:

    # Import the generated client library
    import deployrclient
  2. Add the authentication logic to your application to define a connection from your local machine to Machine Learning Server, provide credentials, capture the access token, add that token to the header, and use that header for all subsequent requests. Use the authentication method defined by your administrator: basic admin account, Active Directory/LDAP (AD/LDAP), or Azure Active Directory (AAD).

    AD/LDAP or admin account authentication

    You must call the POST /login API in order to authenticate. You'll need to pass in the username and password for the local administrator, or if Active Directory is enabled, pass the LDAP account information. In turn, Machine Learning Server will issue you a bearer/access token. After authenticated, the user will not need to provide credentials again as long as the token is still valid, and a header is submitted with every request. If you do not know your connection settings, please contact your administrator.

    #Using client library generated from Autorest
    #Create client instance and point it at an R Server. 
    #In this case, R Server is local.
    client = deployrclient.DeployRClient("http://localhost:12800")
    
    #Define the login request and provide credentials. 
    #Update values with the connection parameters from your admin.
    login_request = deployrclient.models.LoginRequest("<<your-username>>","<<your-password>>")
    #Make a call to the /login API. 
    #Store the returned an access token in a variable.
    token_response = client.login(login_request)

    Azure Active Directory (AAD) authentication

    You must pass the AAD credentials, authority, and client ID. In turn, AAD will issue the Bearer access token. After authenticated, the user will not need to provide credentials again as long as the token is still valid, and a header is submitted with every request. If you do not know your connection settings, please contact your administrator.

    #Import the AAD authentication library
    import adal
    
    #Define the login request and provide credentials. 
    #Use the AAD connection parameters provided by your admin.
    url = "http://localhost:12800"
    authuri = https://login.windows.net,
    tenantid = "<<AAD_DOMAIN>>", 
    clientid = "<<NATIVE_APP_CLIENT_ID>>", 
    resource = "<<WEB_APP_CLIENT_ID>>", 
    
    #Acquire authentication token using AAD Device Code Login
    context = adal.AuthenticationContext(authuri+'/'+tenantid, api_version=None)
    code = context.acquire_user_code(resource, clientid)
    print(code['message'])
    token = context.acquire_token_with_device_code(resource, code, clientid)
    #The authentication code returned must be entered at https://aka.ms/devicelogin 
  3. Add the Bearer access token and check that Machine Learning Server is currently running. This token was returned during authentication and must be included in every subsequent request header. This example uses a client library generated by Autorest.

    [!IMPORTANT] Every API call must be authenticated. Therefore, remember to include headers with tokens to every single request.

    #Add the returned access token to the headers variable.
    headers = {"Authorization": "Bearer {0}".format(token_response.access_token)}
    
    #Verify that the server is running.
    #Remember to include `headers` in every request!
    status_response = client.status(headers) 
    print(status_response.status_code)

Step 3. Prepare session and code

After authentication, you can start a Python session and create a model you'll publish later. You can include any Python code or models in a web service. Once you've set up your session environment, you can even save it as a snapshot so you can reload your session as you had it before.

Important

Remember to include headers in every request.

  1. Create a Python session on R Server. You must specify a name and the Python language (runtime_type="Python"). If you don't set the runtime type to Python, it defaults to R.

    This is a continuation of the example using the client library generated by Autorest:

    #Since already logged in, create a Python session.
    #Define session using name (`Session 1`) and `runtime_type="Python"`.
    #Remember to specify the Python runtime type.
    create_session_request = deployrclient.models.CreateSessionRequest("Session 1", runtime_type="Python")
    
    #Make the call to start the session. 
    #Remember to include headers in every method call to the server.
    #Returns a session ID.
    response = client.create_session(create_session_request, headers) 
    
    #Store the session ID in a variable called `session_id` 
    #to be able to identify it later at execution time.
    session_id = response.session_id
  2. Create or call a model in Python that you'll publish as a web service

    In this example, we train a SciKit-Learn support vector machines (SVM) model on the Iris Dataset on a remote instance of Machine Learning Server. This dataset is available from the scikit-learn site.

    #Import SVM and datasets from the SciKit-Learn library
    execute_request = deployrclient.models.ExecuteRequest("from sklearn import svm\nfrom sklearn import datasets")
    execute_response = client.execute_code(session_id,execute_request, headers)
    #Report if it was a success
    execute_response.success
    
    #Define the untrained Support Vector Classifier (SVC) object
    #and the dataset to be preloaded.
    execute_request = deployrclient.models.ExecuteRequest("clf=svm.SVC()\niris=datasets.load_iris()\nnames={0:'I. setosa',1:'I. versicolor',2:'I. virginica'}")
    #Now, go create the object and preload Iris Dataset in R Server
    execute_response = client.execute_code(session_id,execute_request, headers)
    #Report if it was a success
    execute_response.success
    
    #Define two rows from the Iris Dataset as a sample for scoring
    workspace_object = deployrclient.models.WorkspaceObject("species_1",[7,3.2,4.7,1.4])
    workspace_object_2 = deployrclient.models.WorkspaceObject("species_2",[3,2.6,3,2.5])
    
    #Define how to train the classifier model; what to predict; what to return
    execute_request = deployrclient.models.ExecuteRequest(
        "clf.fit(iris.data, iris.target)\n"+
        "result=clf.predict(species_1)\n"+
        "other_result=clf.predict(species_2)",
        [workspace_object,workspace_object_2], #Input
        ["result", "other_result"]) #Output
    
    #Now, go train that model on the Iris Dataset in R Server
    execute_response = client.execute_code(session_id,execute_request, headers)
    
    #If successful, print name and result of each output parameter. Else, print error.
    if(execute_response.success):
        for result in execute_response.output_parameters:
            print("{0}: {1}".format(result.name,result.value))
    else:
        print (execute_response.error_message)
  3. Create a snapshot of this Python session so this environment can be saved in the web service and reproduced at consume time. Snapshots are very useful when you need a prepared environment that includes certain libraries, objects, models, files and artifacts. Snapshots save the whole workspace and working directory. However, when publishing, you can use only snapshots that you've created.

    [!NOTE] While snapshots can also be used when publishing a web service for environment dependencies, it may have an impact on the performance of the consumption time. For optimal performance, consider the size of the snapshot carefully and ensure that you keep only those workspace objects you need and purge the rest. In a session, you can use the Python del function or the deleteWorkspaceObject API request to remove unnecessary objects.

    #Create a snapshot of the current session.
    response = client.create_snapshot(session_id, deployrclient.models.CreateSnapshotRequest("Iris Snapshot"), headers)
    
    #Return the snapshot ID for reference when you publish later.
    response.snapshot_id
    
    #If you forget the ID, list every snapshot to get the ID again.
    for snapshot in client.list_snapshots(headers):
        print(snapshot)

Step 4. Publish the model

After your client library has been generated and you've built the authentication logic into your application, you can interact with the core APIs to create a Python session, create a model, and then publish a web service using that model.

Note

Remember that you must be authenticated before you make any API calls. Therefore, include headers in every request.

  • Publish this SVM model as a Python web service in Machine Learning Server. This web service will score a vector that gets passed to it.

Important

To ensure that the web service is registered as a Python service, be sure to specify runtime_type="Python". If you don't set the runtime type to Python, it defaults to R.

   #Define a web service that determines the iris species by scoring 
   #a vector of sepal length and width, petal length and width
   
   #Set `flower_data` for the sepal and petal length and width
   flower_data = deployrclient.models.ParameterDefinition(name = "flower_data", type = "vector")
   #Set `iris_species` for the species of iris
   iris_species = deployrclient.models.ParameterDefinition(name = "iris_species", type = "vector")
   
   #Define the publish request for the web service and its arguments.
   #Specify the code, inputs, outputs, and snapshot.
   #Don't forget to set runtime_type="Python"`.
   publish_request = deployrclient.models.PublishWebServiceRequest(
       code = "iris_species = [names[x] for x in clf.predict(flower_data)]", 
       input_parameter_definitions = [flower_data], 
       output_parameter_definitions = [iris_species],
       runtime_type = "Python",
       snapshot_id = response.snapshot_id)

   #Publish the service using the specified name (iris), version (V1.0)
   client.publish_web_service_version("Iris", "V1.0", publish_request, headers)

Step 5. Consume the web service

This section demonstrates how to consume the service in the same session where it was created.

  1. In the same session, get service holdings and metadata for the service.

    # Inspect holdings and metadata for service Iris V1.0.
    for service in client.get_web_service_version("Iris","V1.0", headers):
        #print service metadata (description, who published,...)
        print(service)
        #Print input and output parameters as defined in service definition object
        print("Input Parameters: {0}".format([str(parameter) for parameter in service.input_parameter_definitions]))
        print("Output Parameters: {0}".format([str(parameter) for parameter in service.output_parameter_definitions]))
  2. Examine the service holdings and prepare to consume.

    #Import the requests library to make requests on the server
    import requests
    #Import the JSON library to use for pretty printing of json responses
    import json
    
    #Create a requests `Session` object.
    s = requests.Session()
    
    #Record the R Server endpoint URL hosting the web services you created
    url = "http://localhost:12800"
    
    #Give the request.Session object the authentication headers 
    #so you don't have to repeat it with each request.
    s.headers = headers
    
    # Retrieve the service-specific swagger file using the requests library.
    swagger_resp = s.get(url+"/api/Iris/V1.0/swagger.json")
    
    #Either download service-specific swagger file using the json library.
    with open('iris_swagger.json','w') as f:
       (json.dump(client.get_web_service_swagger("Iris","V1.0",headers),f, indent = 1))
    
    #Or print just what you need from the Swagger file, 
    #such as the routing paths for the endpoints to be consumed.
    print(json.dumps(swagger_resp.json()["paths"], indent = 1, sort_keys = True))
    
    #Or, print input and output parameters as defined in the Swagger.io format
    print("Input")
    print(json.dumps(swagger_resp.json()["definitions"]["InputParameters"], indent = 1, sort_keys = True))
    print("Output")
    print(json.dumps(swagger_resp.json()["definitions"]["WebServiceResult"], indent = 1, sort_keys = True))
  3. Consume the service by supplying some input and getting the Iris species.

    #Make the request to consume the service using these flower_data inputs
    resp = s.post(url+"/api/Iris/V1.0",json={"flower_data":[7,3.2,4.7,1.4]})
    #Print the output
    print(json.dumps(resp.json(), indent = 1, sort_keys = True))
    
    ##Use input from another Iris species.
    resp = s.post(url+"/api/Iris/V1.0",json={"flower_data":[3,2.6,3,2.5]})
    print(json.dumps(resp.json(), indent = 1, sort_keys = True))
    
    ##Use input from another Iris species.
    resp = s.post(url+"/api/Iris/V1.0",json={"flower_data":[5.1,3.5,1.4,.2]})
    print(json.dumps(resp.json(), indent = 1, sort_keys = True))

Managing the Services

Now that you've created a web service, you can update, delete, or republish that service. You can also list all the web services that are hosted using Microsoft Machine Learning Server.

Update a web service

You can update a web service to change the code, model, description, inputs, outputs and more. In this example, we update the service to add a description useful to people who might consume this service.

#Define what needs to be updated. Here we add a description.
#Be sure to specify the runtime_type again.
update_request = deployrclient.models.PublishWebServiceRequest(
    description = "Determines iris species using length and width of sepal and petal", runtime_type = "Python")
#Now update it by specifying the service name and version number
client.patch_web_service_version("Iris", "V1.0", update_request, headers)

Publish another version

You can also publish another version of the web service. In this example, the service will now return the Iris species as a string instead of as a list of strings.

#Publish another version of the web service, but this time 
#the service returns the species as a string instead of list of strings.
flower_data = deployrclient.models.ParameterDefinition(name = "flower_data", type = "vector")
iris_species = deployrclient.models.ParameterDefinition(name = "iris_species", type = "string")
 
#Define the publish request for the service and its arguments.
#Specify the changed code, inputs, outputs, and snapshot.
#Don't forget to set runtime_type="Python"`.
publish_request = deployrclient.models.PublishWebServiceRequest(
    code = "iris_species = [names[x] for x in clf.predict(flower_data)][0]",
    description = "Determines the species of iris, based on Sepal Length, Sepal Width, Petal Length and Petal Width",
    input_parameter_definitions = [flower_data],
    output_parameter_definitions = [iris_species],
    runtime_type = "Python",
    snapshot_id = response.snapshot_id)
 
#Now, publish the service with version (V2.0)
client.publish_web_service_version("Iris", "V2.0", publish_request, headers)
 
#Make request to consume service using these flower_data inputs; print output
resp = s.post(url+"/api/Iris/V2.0",json={"flower_data":[5.1,3.5,1.4,.2]})
print(json.dumps(resp.json(), indent = 1, sort_keys = True))

List services

Get a list of all web services, including those created by other users or in different languages.

#Return the list of all existing web services.
for service in client.get_all_web_services(headers):
    #print the service information
    print(service)
    #Print each input and output parameter
    print("Input Parameters: {0}".format([str(parameter) for parameter in service.input_parameter_definitions]))
    print("Output Parameters: {0}".format([str(parameter) for parameter in service.output_parameter_definitions]))

Delete services

You can delete services you've created. You can also delete the services of others if you are assigned to a role that has the appropriate permissions.

In this example, we delete the second web service version we just published.

#Delete the second version we just published.
client.delete_web_service_version("Iris","V2.0",headers)