pythongcloudgoogle-cloud-ml

How to set the request timeout in google ml api python client?


I'm running online predictions on google cloud machine learning API using the google api python client and a model hosted for me at google cloud. When I predict sending one image, the server, including all traffic, is taking about 40 seconds. When I send two images, after some time, I receive the message:

timeout: The read operation timed out

I would like to set the timeout to other value, but I didn't find how.

This is my code:

import base64
import io
import time
from PIL import Image    

from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient import discovery

SCOPES = ['https://www.googleapis.com/auth/cloud-platform']
SERVICE_ACCOUNT_FILE = 'mycredentialsfile.json'

credentials = ServiceAccountCredentials.from_json_keyfile_name(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

ml = discovery.build('ml', 'v1', credentials=credentials)

projectID = 'projects/{}'.format('projectID') + '/models/{}'.format('modelID')

width = 640
height = 480

instances = []

for image in ["image5.jpg", "image6.jpg"]:
    img = Image.open(image)
    img = img.resize((width, height), Image.ANTIALIAS)
    output_str = io.BytesIO()
    img.save(output_str, "JPEG")
    instance = {"b64": base64.b64encode(output_str.getvalue()).decode("utf-8") }
    output_str.close()
    instances.append(instance)  

input_json = {"instances": instances }

request = ml.projects().predict(body=input_json, name=projectID)

print("Starting prediction")
start_time = time.time()
response = request.execute()

print("%s seconds" % (time.time() - start_time))

Solution

  • [update] please see @Sylver11 and @Shohei's answers for the explanation of the full implication of this solution.

    It took me a while to find a simple resolution. You only need to add the following to the code

    import socket
    timeout_in_sec = 60*3 # 3 minutes timeout limit
    socket.setdefaulttimeout(timeout_in_sec)
    
    # then you could create your ML service object as usually, and it will have the extended timeout limit.
    ml_service = discovery.build('ml', 'v1')
    
    #however, this is a hacky solution because this a low level setting could also impact other http clients. so, please set it back
    socket.setdefaulttimeout(None)