Sudden AttributeError: module 'boto3' has no attribute 'utils' after script has been working for a few days

85 Views Asked by At

I made a script to import row based attachments from a Smartsheet to an S3 Bucket in AWS. The code was working successfully until today where I receive this peculiar AttributeError: module 'boto3' has no attribute 'utils' error.

# Import required libraries
import os
import smartsheet
import requests
import boto3
from botocore.exceptions import NoCredentialsError

try:
    # Initialize Smartsheet client
    SMARTSHEET_ACCESS_TOKEN = dbutils.secrets.get(scope="smartsheet", key="smartsheetapi")
    smartsheet_client = smartsheet.Smartsheet(SMARTSHEET_ACCESS_TOKEN)

    # Initialize S3 client
    aws_access_key = dbutils.secrets.get(scope="scope_aws", key="aws_access_key")
    aws_secret_key = dbutils.secrets.get(scope="scope_aws", key="aws_secret_key")
    client_s3 = boto3.client('s3', aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)

    # Get Smartsheet attachments and store in DBFS
    SHEET_ID = 354*****************
    sheet = smartsheet_client.Sheets.get_sheet(SHEET_ID)

    # Define the master folder in DBFS FileStore with the name of the Smartsheet
    master_folder = os.path.join('/dbfs/FileStore', sheet.name)
    if not os.path.exists(master_folder):
        os.makedirs(master_folder)

    for row in sheet.rows:
        attachments = smartsheet_client.Attachments.list_row_attachments(SHEET_ID, row.id)
        for attachment in attachments.data:
            response = smartsheet_client.Attachments.get_attachment(SHEET_ID, attachment.id)

            # Create a subfolder for the user who uploaded the attachment
            user_folder = os.path.join(master_folder, attachment.created_by.email)
            if not os.path.exists(user_folder):
                os.makedirs(user_folder)

            # Define the path where the attachment will be saved
            attachment_path = os.path.join(user_folder, attachment.name)

            # Check if the attachment already exists
            if not os.path.exists(attachment_path):
                # Download the attachment
                download = requests.get(response.url, stream=True)
                if download.status_code == 200:
                    # Save the attachment to the user's folder in DBFS
                    with open(attachment_path, 'wb') as file:
                        for chunk in download:
                            file.write(chunk)

                    # Log the user who uploaded the attachment
                    print(f'User {attachment.created_by.email} uploaded the attachment {attachment.name}')
                else:
                    print(f"Failed to download attachment: {attachment.name}")
            else:
                print(f"Attachment {attachment.name} already exists. Skipping download.")

    # Upload files to S3
    for root, dirs, files in os.walk(master_folder):
        for file in files:
            local_file = os.path.join(root, file)
            s3_file = 'Inbox/Smartsheet Attachments/' + local_file.replace(master_folder + os.sep, '', 1)

            try:
                s3.upload_file(local_file, 'example-dev-path, s3_file)
                print(f'Successfully uploaded {s3_file} to S3')
            except NoCredentialsError:
                print("No AWS S3 credentials found")

except smartsheet.exceptions.SmartsheetException as e:
    print(f"Smartsheet error: {e}")
except OSError as e:
    print(f"OS error: {e}")

I have tried changing the version of boto3 (downgrading and upgrading). Additionally, I have tried using a boto3 resource instead of client. This error makes no sense to me. Provided is the error log as well. Thank you!

<command-2441771752375061> in <cell line: 9>()
     15     aws_access_key = dbutils.secrets.get(scope="scope_aws", key="aws_access_key")
     16     aws_secret_key = dbutils.secrets.get(scope="scope_aws", key="aws_secret_key")
---> 17     client_s3 = boto3.client('s3', aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
     18 
     19     # Get Smartsheet attachments and store in DBFS

/databricks/python/lib/python3.9/site-packages/boto3/__init__.py in client(*args, **kwargs)
     90     See :py:meth:`boto3.session.Session.client`.
     91     """
---> 92     return _get_default_session().client(*args, **kwargs)
     93 
     94 

/databricks/python/lib/python3.9/site-packages/boto3/__init__.py in _get_default_session()
     78     """
     79     if DEFAULT_SESSION is None:
---> 80         setup_default_session()
     81     _warn_deprecated_python()
     82 

/databricks/python/lib/python3.9/site-packages/boto3/__init__.py in setup_default_session(**kwargs)
     32     """
     33     global DEFAULT_SESSION
---> 34     DEFAULT_SESSION = Session(**kwargs)
     35 
     36 

/databricks/python/lib/python3.9/site-packages/boto3/session.py in __init__(self, aws_access_key_id, aws_secret_access_key, aws_session_token, region_name, botocore_session, profile_name)
     89         )
     90         self._setup_loader()
---> 91         self._register_default_handlers()
     92 
     93     def __repr__(self):

/databricks/python/lib/python3.9/site-packages/boto3/session.py in _register_default_handlers(self)
    483         self._session.register(
    484             'creating-client-class.s3',
--> 485             boto3.utils.lazy_call(
    486                 'boto3.s3.inject.inject_s3_transfer_methods'
    487             ),

AttributeError: module 'boto3' has no attribute 'utils'

0

There are 0 best solutions below