2017-01-24 8 views
1

Я пытаюсь загрузить текстовый файл с S3 с помощью boto3.Отслеживание загрузки файла S3 с использованием boto3 и обратных вызовов

Вот что я написал.

class ProgressPercentage(object): 
    def __init__(self, filename): 
     self._filename = filename 
     self._size = float(os.path.getsize(filename)) 
     self._seen_so_far = 0 
     self._lock = threading.Lock() 

    def __call__(self, bytes_amount): 
     # To simplify we'll assume this is hooked up 
     # to a single filename. 
     with self._lock: 
      self._seen_so_far += bytes_amount 
      percentage = round((self._seen_so_far/self._size) * 100,2) 
      LoggingFile('{} is the file name. {} out of {} done. The percentage completed is {} %'.format(str(self._filename), str(self._seen_so_far), str(self._size),str(percentage))) 
      sys.stdout.flush() 

и я называю его с помощью

transfer.download_file(BUCKET_NAME,FILE_NAME,'{}{}'.format(LOCAL_PATH_TEMP , FILE_NAME),callback = ProgressPercentage(LOCAL_PATH_TEMP + FILE_NAME)) 

это дает мне ошибку, что файл не присутствует в папке. Видимо, когда у меня уже есть файл с этим именем в той же папке, он работает, но когда я загружаю новый файл, он ошибается.

Что такое коррекция, которую мне нужно сделать?

ответ

2

callback = ProgressPercentage(LOCAL_PATH_TEMP + FILE_NAME)) создает ProgressPercentage объект, запускает свой метод __init__ и передает объект как callback к методу download_file. Это означает, что запущен __init__доdownload_file.

В методе __init__ вы пытаетесь прочитать размер загружаемого локального файла, который генерирует исключение, поскольку файл не существует, так как загрузка еще не началась. Если вы уже загрузили файл, тогда нет никакой проблемы, поскольку существует локальная копия и ее размер может быть прочитан.

Конечно, это просто причина исключения, которое вы видите. Вы используете свойство _size как максимальное значение для загрузки. Однако вы пытаетесь использовать размер локального файла. Пока файл не будет полностью загружен, локальная файловая система не знает, насколько велик файл, он знает, сколько места занимает сейчас. Это означает, что при загрузке файл будет постепенно увеличиваться, пока он не достигнет своего полного размера. Таким образом, на самом деле не имеет смысла рассматривать размер локального файла как максимальный размер загрузки. Он может работать в том случае, если вы уже загрузили файл, но это не очень полезно.

Решение проблемы заключается в проверке размера файла, который вы собираетесь загрузить, вместо размера локальной копии. Это гарантирует, что вы получаете фактический размер того, что вы загружаете, и что файл существует (поскольку вы не могли его загрузить, если это не так). Вы можете сделать это, получая размер удаленного файла с head_object следующего

class ProgressPercentage(object): 
    def __init__(self, client, bucket, filename): 
     # ... everything else the same 
     self._size = client.head_object(Bucket=bucket, Key=filename).ContentLength 

    # ... 

# If you still have the client object you could pass that directly 
# instead of transfer._manager._client 
progress = ProgressPercentage(transfer._manager._client, BUCKET_NAME, FILE_NAME) 
transfer.download_file(..., callback=progress) 

В качестве последней ноты, хотя вы получили код из Boto3 documentation, это не сработало, потому что она была предназначена для загрузки файлов. В этом случае локальный файл является источником и его существование гарантировано.

2

Объект client.head_object(Bucket=bucket, Key=filename) является диктофоном. Доступ к размеру файла можно получить с помощью ['ContentLength'].

Поэтому код:
self._size = client.head_object(Bucket=bucket, Key=filename).ContentLength
должны стать:
self._size = float(client.head_object(Bucket=bucket, Key=filename)['ContentLength'])

Затем он работает. Благодаря!