首页 > 解决方案 > 将文件上传到某个驱动器时发生错误时,有没有办法实现重试功能?

问题描述

我正在从事一个项目,负责每天将文件从数据库上传到 OneDrive 中的驱动器。当您上传一半文件时,出于一个奇怪的原因,它会突然失败。我想知道是否有一种方法可以实现用python编写的“重试”函数,当文件上传过程失败时,它会执行并重试三次,如果在三次结束后失败并显示“上传过程”之类的消息今天失败了”。欢迎任何形式的帮助。Python版本**3.8.3

执行整个上传过程的代码如下

if __name__ == '__main__':
    reg_manager = RegistryManager()
    keys = reg_manager.get_keys()
    try:
        tables = BCPManager.load_tables()

        dir_name = datetime.today().strftime('%Y-%m-%d')
        dir_path = f'./files/{dir_name}'
        final_file = 'tables.zip'

        FileManager.create_folder(dir_path)

        for table in tables:
            table_columns = BCPManager.get_table_columns(table, dir_path)
            table_data = BCPManager.get_table_data(table, dir_path, 3)
            table_path = f'{dir_path}/{table}.csv'

            FileManager.merge_table_files(table_path, table_columns, table_data)

        dir_files = FileManager.get_directory_files(dir_path)

        with ZipFile(
                f'{dir_path}/{final_file}',
                'w',
                compression=ZIP_DEFLATED,
                compresslevel=9
        ) as zip_file:
            for dir_file in dir_files:
                if dir_file.name == final_file:
                    continue

                print(f'zipping file {dir_file.path}')

                zip_file.write(dir_file.path, arcname=dir_file.name)
                FileManager.remove_file(dir_file.path)

        file_size = os.path.getsize(f'{dir_path}/{final_file}')

        uploader = OneDriveUploader(
            'drives/{DriveID}/items/{ChildreID}',
            {
                'client_id': keys['client_id'],
                'client_secret': keys['client_secret']
            }
        )

        uploader.create_folder(dir_name)
        print('uploading file')
        with open(f'{dir_path}/{final_file}', 'rb') as open_file:
            print('getting file chunks')
            chunks = FileManager.get_file_chunks(open_file)
            index = 0
            offset = 0
            headers = dict()
            upload_url = uploader.get_upload_link(dir_name, final_file)

            for chunk in chunks:
                offset = index + len(chunk)

                headers['Content-Type'] = 'application/octet-stream'
                headers['Content-Length'] = str(file_size)
                headers['Content-Range'] = f'bytes {index}-{offset - 1}' \
                                           f'/{file_size} '

                uploader.upload_file_chunk(upload_url, chunk, headers)

                index = offset
        print('removing file')
        FileManager.remove_file(f'{dir_path}/{final_file}')

    except Exception as uploader_exception:
        print('There was an error while uploading files')
        print(uploader_exception)
        message = Mail(
            from_email='test@outlook.com',
            to_emails=['test@gmail.com'],
            subject='OneDrive upload failed',
            html_content='Something went wrong while uploading files to '
                         'onedrive')
        try:
            sg = SendGridAPIClient(keys['sendgrid_api_key'])
            response = sg.send(message)
            print(response.status_code)
            print(response.body)
            print(response.headers)
        except Exception as e:
            print(e)

上传一半文件后,会引发以下错误:

<Response [202]> {'expirationDateTime': '2021-08-14T12:01:08.341Z', 'nextExpectedRanges': ['11141120-109593649']}
<Response [202]> {'expirationDateTime': '2021-08-14T12:01:08.341Z', 'nextExpectedRanges': ['11468800-109593649']}
<Response [202]> {'expirationDateTime': '2021-08-14T12:01:08.341Z', 'nextExpectedRanges': ['11796480-109593649']}
There was an error while uploading files
Expecting value: line 1 column 1 (char 0)
202
b''
Server: nginx
Date: Mon, 09 Aug 2021 12:01:33 GMT
Content-Length: 0
Connection: close
X-Message-Id: cMEuH6TtSHCmiKMKUzV1Dg
Access-Control-Allow-Origin: https://sendgrid.api-docs.io
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-acl
Access-Control-Max-Age: 600
X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html
Strict-Transport-Security: max-age=600; includeSubDomains

对此有些好奇的是,它不会一周中的每一天都失败,它每周偶尔会失败一次,这就是为什么要实现一个负责重试文件上传的函数的想法,如果失败了 3 次尝试过,没有任何反应,因为还有 6 天。

标签: pythonpython-3.xretry-logic

解决方案


好吧,使用递归非常简单。这是我的实现:

def upload(runs):
    try:
        if runs != 0:
            "UPLOAD FILES HERE"
    except Exception as uploader_exception:
        print("UPLOAD FAILED {} times, trying again".format(4-runs))
        upload(runs-1)

upload(3)

推荐阅读