2017-02-17 4 views
7

S3에 데이터를 업로드하는 스크립트를 작성했습니다. 파일이 5MB 미만인 경우 파일을 하나의 청크로 업로드하지만 파일이 더 큰 경우 다중 부분 업로드를 수행합니다. 임계 값이 현재 작다는 것을 알고 있으며 그 동안 스크립트를 테스트하고 있습니다. 파이썬에서 스크립트를 실행하여 모든 함수를 가져오고 그런 식으로 실행하면 모든 것이 의도 한대로 작동합니다. 코드가 아직 완료되지 않았으므로 정리가 필요하다는 것을 알고 있습니다. 내가 명령 줄에서 스크립트를 실행할 때, 나는이 오류와 함께 인사를하고있다 :업 로더 스크립트를 실행할 때 다른 결과가 발생했습니다.

import sys 
import boto 
from boto.s3.key import Key 
import os 
import math 
from filechunkio import FileChunkIO 


KEY = os.environ['AWS_ACCESS_KEY_ID'] 
SECRET = os.environ['AWS_SECRET_ACCESS_KEY'] 

def start_connection(): 
    key = KEY 
    secret = SECRET 
    return boto.connect_s3(key, secret) 

def get_bucket_key(conn, bucket_name): 
    bucket = conn.get_bucket(bucket_name) 
    k = Key(bucket) 
    return k 

def get_key_name(sub_directory, input_file): 
    full_key_name = os.path.join(sub_directory, os.path.basename(input_file)) 
    return full_key_name 

def get_file_info(input_file): 
    source_size = os.stat(input_file).st_size 
    return source_size 

def multipart_request(conn, input_file, bucket_name, sub_directory): 
    bucket = conn.get_bucket(bucket_name) 
    mp = bucket.initiate_multipart_upload(get_key_name(sub_directory, input_file)) 
    return mp 

def get_chunk_size(mb): 
    chunk_size = mb * 1048576 
    return chunk_size 

def get_chunk_count(input_file, mb): 
    chunk_count = int(math.ceil(get_file_info(input_file)/float(get_chunk_size(mb)))) 
    return chunk_count 

def regular_upload(conn, input_file, bucket_name, sub_directory): 
    k = get_bucket_key(conn, bucket_name) 
    k.key = get_key_name(sub_directory, input_file) 
    k.set_contents_from_filename(input_file) 


def multipart_upload(conn, input_file, mb, bucket_name, sub_directory): 
    chunk_size = get_chunk_size(mb) 
    chunks = get_chunk_count(input_file, mb) 
    source_size = get_file_info(input_file) 
    mp = multipart_request(conn, input_file, bucket_name, sub_directory) 
    for i in range(chunks): 
     offset = chunk_size * i 
     b = min(chunk_size, source_size - offset) 
     with FileChunkIO(input_file, 'r', offset = offset, bytes = b) as fp: 
      mp.upload_part_from_file(fp, part_num = i + 1) 
    mp.complete_upload() 

def check_if_mp_needed(conn, input_file, mb, bucket_name, sub_directory): 
    if get_file_info(input_file) <= 5242880: 
     regular_upload(conn, input_file, bucket_name, sub_directory) 
    else: 
     multipart_upload(conn, input_file, mb, bucket_name, sub_directory) 

def main(): 
    input_file = sys.argv[1] 
    mb = sys.argv[2] 
    bucket_name = sys.argv[3] 
    sub_directory = sys.argv[4] 
    conn = start_connection() 
    check_if_mp_needed(conn, input_file, mb, bucket_name, sub_directory) 

if __name__ == '__main__': 
    main() 

감사 :

여기
Traceback (most recent call last): 
    File "upload_files_to_s3.py", line 106, in <module> 
    main() 
    File "upload_files_to_s3.py", line 103, in main 
    check_if_mp_needed(conn, input_file, mb, bucket_name, sub_directory) 
    File "upload_files_to_s3.py", line 71, in check_if_mp_needed 
    multipart_upload(conn, input_file, mb, bucket_name, sub_directory) 
    File "upload_files_to_s3.py", line 65, in multipart_upload 
    mp.complete_upload() 
    File "/usr/local/lib/python2.7/site-packages/boto/s3/multipart.py", line 304, in complete_upload 
    self.id, xml) 
    File "/usr/local/lib/python2.7/site-packages/boto/s3/bucket.py", line 1571, in complete_multipart_upload 
    response.status, response.reason, body) 
boto.exception.S3ResponseError: S3ResponseError: 400 Bad Request 

>The XML you provided was not well-formed or did not validate against our published schema 

코드입니다!

+1

대부분의 경우 명령 줄에서 수동으로 모든 것을 가져 오는 환경과 다른 환경을 사용하고있을 가능성이 큽니다. 두 경우 모두 무엇을 사용하고 있습니까? –

+0

IPython의'virtualenv'에서 스크립트를 실행하고 있습니다. 커맨드 라인은 단지'virtualenv' –

+0

OK를 통해 실행됩니다 - 그래서 불일치가 있다는 것은 불가능하지 않습니다. 두 경우 모두'boto .__ version__ '을 (를) 확인할 수 있습니까? –

답변

0

두 경우의 버전이 일치하지 않습니다. 이전 버전의 boto를 사용하면 AWS에 잘못된 스키마가 사용되므로 오류가 표시됩니다.

좀 더 자세하게 설명하자면, IPython (virtualenv 사용)에서 버전 2.45.0을 실행 중일 때 명령 행에서 실행할 때 boto 버전 2.8.0이 있습니다. 버전 2.8.0이 2013 년으로 거슬러 올라간다는 사실을 감안할 때 스키마 오류가 발생하는 것은 놀라운 일이 아닙니다.

해결 방법은 pip install -U boto을 실행하여 시스템 버전의 boto (현재 스크립트에서 선택중인)를 업그레이드하거나 가상 환경을 사용하도록 스크립트를 변환하는 것입니다. 후자에 대한 조언은 SO에 대한 다른 답변을 참조하십시오. Running python script from inside virtualenv bin is not working

+0

'pip install -U boto'를했는데 두 버전을 모두 2.46.1로 바 꾸었습니다. 그러나 여전히 같은 오류 메시지가 나타납니다. 내가 이것을 돌았을 때 염두에 두라. 마지막으로'virtualenv'를 사용하지 않았다. –

+0

그리고 여전히 IPython에서 다른 결과가 명령 행에서 실행되는 것을 볼 수 있을까? –

+0

아니요, 둘 다 같은 버전의'2.46.1'을 인쇄합니다. –