本文介绍使用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
部分操作系统无法安装crcmod的C扩展模式怎么办?
对于无法成功安装crcmod的C扩展模式的系统,您可以关闭CRC64校验。具体步骤,请参见关闭CRC64数据校验。
如何确保生成的签名URL以https开头?
如果您希望生成的签名URL以https开头,您需要在初始化SDK时设置endpoint以https开头,例如https://oss-cn-hangzhou.aliyuncs.com
。
在多进程下怎么使用Bucket实例?
您需要在多进程初始化完成后创建Bucket实例。