本文介紹使用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執行個體。