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'