google-api-python-client icon indicating copy to clipboard operation
google-api-python-client copied to clipboard

Batch call to PlaylistItems: insert produces intermittent HttpError 500

Open thompcha opened this issue 3 years ago • 1 comments

Environment details

  • OS type and version: Windows 11 Pro (22H2)
  • Python version: 3.10.9
  • pip version: 22.0.2
  • google-api-python-client version: 2.70.0

Code example

# -*- coding: utf-8 -*-

import os
import pickle

import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors

# YouTube API variables
scopes = ["https://www.googleapis.com/auth/youtube.force-ssl"]
client_secrets_file = "client_secret.json"
api_service_name = "youtube"
api_version = "v3"

def main():
    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    # os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
    # Get credentials and create an API client
    flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
        client_secrets_file, scopes)
    youtube = get_authenticated_service()
    batch = youtube.new_batch_http_request(callback=insert_callback)

    playlistId = "PL2iXsIOEmdYXFsP-Clp8w1Pf5chGN0i1S"
    video_ids   = [ 
                   "d7ypnPjz81I",
                   "vZv9-TWdBJM",
                   "7uG6E6bVKU0",
                   "8EzfBYFU8Q0" 
                 ]

    # Create a list of playlist items, one for each video ID
    playlist_items = []
    for video_id in video_ids:
        batch.add(youtube.playlistItems().insert(
            part="snippet",
            body={
              "snippet": {
                "playlistId": playlistId, #an actual playlistid
                #"position": 0,
                "resourceId": {
                  "kind": "youtube#video",
                  "videoId": video_id
                }
              }
            }
          )
        )

    # Use the batch method to add the playlist items to the playlist in a single API call
    response = batch.execute()

    print(response)

def insert_callback(request_id, response, exception):
    if exception is not None:
        print(exception)
    else:
        print(response)

# Check for pickled credentials. If found, use these to make API calls,
# otherwise perform full authentication process
def get_authenticated_service():
    if os.path.exists("CREDENTIALS_PICKLE_FILE"):
        with open("CREDENTIALS_PICKLE_FILE", 'rb') as f:
            credentials = pickle.load(f)
    else:
        flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(client_secrets_file, scopes)
        credentials = flow.run_console()
        with open("CREDENTIALS_PICKLE_FILE", 'wb') as f:
            pickle.dump(credentials, f)
    return googleapiclient.discovery.build(
        api_service_name, api_version, credentials=credentials)

if __name__ == "__main__":
    main()

Expected Result

The videos are added to the playlist

Actual Result

Some videos are added, others produce the following reponse:

<HttpError 500 when requesting https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&alt=json returned "Internal error encountered.". Details: "[{'message': 'Internal error encountered.', 'domain': 'global', 'reason': 'backendError'}]">

There is no pattern to which videos are added and which ones cause the error. A video that is added on one run can sometimes error out the next time the script is run.

thompcha avatar Dec 20 '22 20:12 thompcha

The Google API team suggested that I implement a delay between API calls. Can this be done using the Python client library?

thompcha avatar Dec 22 '22 21:12 thompcha