在Windows上Boto文件上传到S3失败 [errno: 10054]
我在用boto把文件上传到S3的时候,遇到了一个错误,提示是:[Errno 10054] 远程主机强制关闭了一个现有的连接
我用来和S3交互的代码大致是这样的:
from boto.s3.connection import S3Connection
from boto.s3.key import Key
conn = S3Connection(Access_Key_ID, Secret_Key)
bucket = conn.lookup(bucket_name)
k = Key(bucket)
k.key = 'akeynameformyfile'
k.set_contents_from_filename(source_path_of_file_to_upload)
在同一台机器上,我用AWS CLI执行以下命令上传文件时,一切正常:
aws s3 cp filename.exe s3://bucketname/ttt
我上传的文件大约有200MB。
我的操作系统是Windows 7,Python通过Anaconda运行,所有的包都是最新的。boto的版本是2.25。
在同一个网络下,CentOS系统上运行这段代码也没有问题。那么这是不是Windows的问题呢?
如果有人能帮忙解决这个问题,我将非常感激,谢谢!
调试输出如下
发送: 'HEAD / HTTP/1.1\r\nHost: ACCESS_KEY_ID.test7.s3.amazonaws.com\r\nAccept-Encoding: identity\r\nDate: Wed, 14 May 2014 22:44:31 GMT\r\nContent-Length: 0\r\nAuthorization: AWS ACCESS_KEY_ID:SOME_STUFF=\r\nUser-Agent: Boto/2.25.0 Python/2.7.5 Windows/7\r\n\r\n'
回复: 'HTTP/1.1 307 Temporary Redirect\r\n'
头部: x-amz-request-id: 8A3D34FB0E0FD8E4
头部: x-amz-id-2: PwG9yzOVwxy21LmcpQ0jAaMchG0baCrfEhAU9fstlPUI307Qxth32uNAOVv72B2
头部: 位置: https://ACCESS_KEY_ID.test7.s3-ap-southeast-2.amazonaws.com/
头部: Content-Type: application/xml
头部: Transfer-Encoding: chunked
头部: 日期: Wed, 14 May 2014 22:44:31 GMT
头部: 服务器: AmazonS3
发送: 'HEAD / HTTP/1.1\r\nHost: ACCESS_KEY_ID.test7.s3-ap-southeast-2.amazonaws.com\r\nAccept-Encoding: identity\r\nDate: Wed, 14 May 2014 22:44:31 GMT\r\nContent-Length: 0\r\nAuthorization: AWS ACCESS_KEY_ID:SOME_STUFF=\r\nUser-Agent: Boto/2.25.0 Python/2.7.5 Windows/7\r\n\r\n'
回复: 'HTTP/1.1 200 OK\r\n'
头部: x-amz-id-2: erataRIpbOrEwOU72VUAqU9AGJ4/kX5z1/UD7rJQy9laKDgOyTyVKABMab8f6wGN
头部: x-amz-request-id: 2A7BECC45C9BAE7A
头部: 日期: Wed, 14 May 2014 22:44:33 GMT
头部: Content-Type: application/xml
头部: Transfer-Encoding: chunked
头部: 服务器: AmazonS3
发送: 'PUT /akeynameformyfile HTTP/1.1\r\nHost: ACCESS_KEY_ID.test7.s3.amazonaws.com\r\nAccept-Encoding: identity\r\nContent-Length: 242642944\r\nContent-MD5: xYOiNcyFKGY1Y/HsYwHQeg==\r\nExpect: 100-Continue\r\nDate: Wed, 14 May 2014 22:44:33 GMT\r\nUser-Agent: Boto/2.25.0 Python/2.7.5 Windows/7\r\nContent-Type: application/octet-stream\r\nAuthorization: AWS ACCESS_KEY_ID:pWs3KwRv9Q5wDnz4dHD3JwvCy/w=\r\n\r\n'--------------------------------------------------------------------------- 错误 回溯(最近的调用在最前)
在 ()12 k = Key(bucket) 13 k.key = 'akeynameformyfile'
---> 14 k.set_contents_from_filename(full_path_of_file_to_upload)
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\s3\key.pyc 在 set_contents_from_filename(self, filename, headers, replace, cb, num_cb, policy, md5, reduced_redundancy, encrypt_key)
1313 num_cb, policy, md5, 1314
reduced_redundancy,-> 1315 encrypt_key=encrypt_key)
1316
1317 def set_contents_from_string(self, string_data, headers=None, replace=True,
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\s3\key.pyc 在 set_contents_from_file(self, fp, headers, replace, cb, num_cb, policy, md5, reduced_redundancy, query_args, encrypt_key, size, rewind) 1244
self.send_file(fp, headers=headers, cb=cb, num_cb=num_cb,
1245 query_args=query_args,-> 1246 chunked_transfer=chunked_transfer, size=size) 1247
返回写入的字节数. 1248 return self.size
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\s3\key.pyc
在 send_file(self, fp, headers, cb, num_cb, query_args, chunked_transfer, size)
723 self._send_file_internal(fp, headers=headers, cb=cb, num_cb=num_cb, 724 query_args=query_args,
--> 725 chunked_transfer=chunked_transfer, size=size)
726 727 def _send_file_internal(self, fp, headers=None, cb=None, num_cb=10, C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\s3\key.pyc
在 _send_file_internal(self, fp, headers, cb, num_cb, query_args, chunked_transfer, size, hash_algs)
912 headers, 913 sender=sender,
--> 914 query_args=query_args
915 )
916 self.handle_version_headers(resp, force=True)
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\s3\connection.pyc 在 make_request(self, method, bucket, key, headers, data, query_args, sender, override_num_retries, retry_handler)631 data, host, auth_path, sender, 632 override_num_retries=override_num_retries,
--> 633 retry_handler=retry_handler
634 )
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\connection.pyc 在 make_request(self, method, path, headers, data, host, auth_path, sender, override_num_retries, params, retry_handler)
1028 params, headers, data, host)
1029 return self._mexe(http_request, sender, override_num_retries,-> 1030 retry_handler=retry_handler) 1031
1032 def close(self):C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\connection.pyc
在 _mexe(self, request, sender, override_num_retries, retry_handler)
905 if callable(sender): 906 response = sender(connection, request.method, request.path,
--> 907 request.body, request.headers)
908 else: 909 connection.request(request.method, request.path, C:\Users\username\AppData\Local\Continuum\Anaconda\lib\site-packages\boto\s3\key.pyc
在 sender(http_conn, method, path, data, headers)
813 http_conn.send('\r\n') 814 else:
--> 815 http_conn.send(chunk)
816 for alg in digesters:
817 digesters[alg].update(chunk)
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\httplib.pyc 在 send(self, data)
803 datablock = data.read(blocksize)
804 else:
--> 805 self.sock.sendall(data)
806
807 def _output(self, s):
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\ssl.pyc 在 sendall(self, data, flags)
227 count = 0
228 while (count < amount):
--> 229 v = self.send(data[count:])
230 count += v
231 return amount
C:\Users\username\AppData\Local\Continuum\Anaconda\lib\ssl.pyc 在 send(self, data, flags)
196 while True:
197 try:
--> 198 v = self._sslobj.write(data)
199 except SSLError, x:
200 if x.args[0] == SSL_ERROR_WANT_READ:
错误: [Errno 10054] 远程主机强制关闭了一个现有的连接
3 个回答
以上的回答都提供了一些技术解决方案,但我第一次遇到这个问题时,感觉更像是个 环境 问题。
我的代码基本上和最初提问的代码一样。我第一次运行的时候没有任何问题,但昨晚又遇到了同样的错误信息。我找到了这个答案和很多其他的,但我觉得既然我的代码第一次运行得很好(上传了超过2万文件),那可能是我电脑的问题,或者是AWS(亚马逊云服务)出问题了,或者是两者之间的某个环节出了问题。
我关掉了电脑,回家了,今天早上重新启动后,原来的代码又正常运行了。
让我得出这个结论的一个观察是,在我寻找答案的时候,我注意到很多关于这个问题的帖子似乎都是在差不多同一时间出现的。这让我想到,可能是AWS出现了问题。不过,我不能确定是我的电脑、AWS服务器,还是中间的某个网络环节出了问题,但今天早上我再次尝试时,原来的代码运行得很好。
这是我现在使用的代码(可以看到和最初提问的代码非常相似)
import boto
import glob
AWS_KEY = "mykey"
AWS_SECRET = "mySecret"
bucket_name = "myBucket"
numbers = [x for x in range(0,20000,500)]
to_upload = glob.glob('E:\MTurkTablesSelected\\*.htm')
s3 = boto.connect_s3(aws_access_key_id = AWS_KEY, aws_secret_access_key = AWS_SECRET)
bucket = s3.get_bucket(bucket_name)
for n, file_path in enumerate(to_upload):
upload_key = file_path.split('\\')[-1]
key = bucket.new_key(upload_key)
key.set_contents_from_filename(file_path)
key.set_acl('public-read')
if n in numbers:
print n
现在我已经上传了超过1万文件,没遇到任何问题。
set_contents_from_filename这个函数需要一个字符串,作为你在S3上文件的来源。你现在想上传一个已经存在的文件。你可以试试使用set_contents_from_file,这样可以指定一个已经存在的文件来上传。否则,你需要把文件的内容读出来,然后以字符串的形式传给set_contents_from_filename。
@garnaat 在上面的评论中给出了一个建议,解决了我的问题。谢谢!!
出于某种原因,直接连接到通用端点后再尝试上传到 ap-southeast-2
的 S3 端点会失败。但是如果我们使用 connect_to_region
函数来启动连接,并指定我们想要的端点,一切就都正常了!再次感谢,下面是一个工作示例。
from boto.s3 import connect_to_region
from boto.s3.connection import Location
from boto.s3.key import Key
conn = connect_to_region(Location.APSoutheast2,
aws_access_key_id=conf.Access_Key_ID,
aws_secret_access_key=conf.Secret_Key)
bucket = conn.lookup(bucket_name) # bucket is located in Location.APSoutheast2
k = Key(bucket)
k.key = 'akeynameformyfile'
k.set_contents_from_filename(source_path_of_file_to_upload)