本文介绍使用OSS Python SDK的常见问题及解决方法。
OSS Python SDK分片上传失败
解决方法如下:
- 先确认是直接上传到OSS,还是通过其他proxy传输到OSS(类似CDN)。如果经过CDN再上传到OSS,需要在OSS中配置跨域的HTTP Header,例如
Access-Control-Allow-Origin
、Access-Control-Allow-Mehtods
、Access-Control-Allow-Headers
等,并暴露ETag。更多信息,请参见PutBucketcors。 - 如果是网络超时导致上传失败,建议使用断点续传来替代普通上传。断点续传支持并行上传以及自定义分片大小。如果捕获到异常,需要详细查看并分析捕获到的SDK异常信息。
- 清理上传失败的碎片文件再重新上传。
如果以上方案仍旧没有解决您的问题,需要将以下信息提供给阿里云:
- SDK返回异常中的requestID。
- 客户端部署tcpdump,然后重新运行代码上传,并保存抓包。
tcpdump -i <网卡出口名称> -s0 host <访问oss的域名> -w faild.pcap
同台机器使用ossutil上传下载很快,而使用Python SDK上传下载很慢
- 错误原因
ossutil工具基于Go SDK进行开发,并发上传的性能较好。如果使用Python SDK上传、下载时性能远不如ossutil,通常是因为没有正确安装crcmod 。
- 解决方法
关于安装crcmod的更多信息,请参见安装Python SDK。如仍未能解决您的问题,请提交工单。
在Centos机器上调用SDK中的分片上传函数正常,但在Ubuntu机器上总是报403错误。
客户端部署tcpdump抓包,然后通过tcp报文排查是否由于Header信息不正确导致计算签名与服务端不匹配。
POST /ttsservice%2Fpasswd?uploadId=D468E486D1D94D90A1AB8885A4E32AE0 HTTP/1.1 Host: rokid.oss-cn-hangzhou.aliyuncs.com Accept-Encoding: identity Accept: text/html Content-Length: 137 date: Sat, 29 Dec 2018 07:32:34 GMT authorization: OSS LTAIknFr:r2KPR0y4E0G5tnU/MYdcvXHP**** Content-Type: application/x-www-form-urlencoded User-Agent: aliyun-sdk-python/2.6.0(Linux/4.4.0-31-generic/x86_64;3.4.3) <CompleteMultipartUpload><Part><PartNumber>1</PartNumber><ETag>"3195544E19D99658706D5****"</ETag></Part></CompleteMultipartUpload>HTTP/1.1 403 Forbidden Server: AliyunOSS Date: Sat, 29 Dec 2018 07:33:43 GMT Content-Type: application/xml Content-Length: 1122 Connection: keep-alive x-oss-request-id: 5C2723573183**** x-oss-server-time: 0 <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> <RequestId> 5C2723573183A12D </RequestId> <HostId>rokid.oss-cn-hangzhou.aliyuncs.com</HostId> <OSSAccessKeyId> LTAXXX </OSSAccessKeyId> <SignatureProvided>r2KPR0y4E0G5tnU/MYdc****</SignatureProvided> <StringToSign>POST application/x-www-form-urlencoded Sat, 29 Dec 2018 07:32:34 GMT /rokid/ttsservice/passwd?uploadId=D468E486D1D94D90A1AB8885A4E3****</StringToSign> <StringToSignBytes>50 4F 53 54 0A 0A 61 70 70 6C 69 63 61 74 69 6F 6E 2F 78 2D 77 77 77 2D 66 6F 72 6D 2D 75 72 6C 65 6E 63 6F 64 65 64 0A 53 61 74 2C 20 32 39 20 44 65 63 20 32 30 31 38 20 30 37 3A 33 32 3A 33 34 20 47 4D 54 0A 2F 72 6F 6B 69 64 2D 6F 70 73 2D 6D 6F 64 65 6C 2F 74 74 73 73 65 72 76 69 63 65 2F 70 61 73 73 77 64 3F 75 70 6C 6F 61 64 49 64 3D 44 34 36 38 45 34 38 36 44 31 44 39 34 44 39 30 41 31 41 42 38 38 38 35 41 34 45 33 32 41 45 30 </StringToSignBytes> </Error>
如果服务端收到的签名(Signature)和客户端计算的签名信息不一致,说明请求的内容已被改动,建议使用HTTPS的方式上传。
以上是客户端抓取的报文信息。请将获取的请求头信息带入以下脚本,并将计算结果与SDK进行比较。
import base64 import hmac import sha mac = hmac.new("<Secretkey>","POST\n\napplication/x-www-form-urlencoded\nSat, 29 Dec 2018 07:32:34 GMT\n/rokid/ttsservice/passwd?uploadId=D468E486D1D94D90A1AB8885A4E3****", sha) Signature = base64.b64encode(mac.digest()) print(Signature)
如果抓包数据和脚本计算的结果一致,则说明SDK计算正确。如果抓包数据和脚本计算的结果不一致,可能是因为SDK在Ubuntu平台编译的适配问题导致MD5值不一样。
在Mac环境中用Python启动多线程并在子线程中使用OSS时,import tensorflow会报错,没有import tensorflow则不会报错。如果没有启动多线程,使用OSS时import tensorflow不会报错。
Python多线程运行时,报如下错误:
objc[2483]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. objc[2483]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
解决方法:
添加环境变量
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
,如下图所示:
更多信息,请参见macOS 10.13系统使用多线程的错误说明。
如何添加重试策略
Python SDK自身没有重试机制。在网络状况不好的情况下,可能会出现请求失败的情况。此时,建议您参考如下代码自行添加重试策略。
def test_get_object(): MAX_RETRIES = 3 retry_count = 0 while True: try: retry_count += 1 # yourObjectName表示不包含Bucket名称在内的OSS文件的完整路径,例如abc/efg/example.jpg。 # yourFileName表示下载到本地文件的完整路径,例如/users/local/example.jpg。 bucket.get_object_to_file("yourObjectName", "yourFileName") break except Exception: if retry_count >= MAX_RETRIES: raise