curlをPythonとrequestsライブラリに置き換えようとしています。curlを使用すると、curl-Tオプションを使用して単一のXMLファイルをRESTサーバーにアップロードできます。私はリクエストライブラリで同じことをすることができませんでした。
基本的なシナリオは機能します:
payload = '<person test="10"><first>Carl</first><last>Sagan</last></person>'
headers = {'content-type': 'application/xml'}
r = requests.put(url, data=payload, headers=headers, auth=HTTPDigestAuth("*", "*"))
XMLファイルを開いてペイロードをより大きな文字列に変更すると、.putメソッドがハングします(コーデックライブラリを使用して適切なUnicode文字列を取得します)。たとえば、66KBのファイルの場合:
xmlfile = codecs.open('trb-1996-219.xml', 'r', 'utf-8')
headers = {'content-type': 'application/xml'}
content = xmlfile.read()
r = requests.put(url, data=content, headers=headers, auth=HTTPDigestAuth("*", "*"))
マルチパートオプション(ファイル)の使用を検討してきましたが、サーバーはそれを好まないようです。
そのため、Pythonリクエストライブラリでcurl-Tの動作をシミュレートする方法があるかどうか疑問に思いました。
更新1:プログラムはtextmateでハングしますが、コマンドラインでUnicodeEncodeErrorエラーをスローします。それが問題のようです。したがって、質問は次のようになります。リクエストライブラリを使用してサーバーにUnicode文字列を送信する方法はありますか?
更新2:Martijn Pietersのコメントのおかげで、UnicodeEncodeErrorはなくなりましたが、新しい問題が発生しました。リテラル(ASCII)XML文字列の場合、ロギングには次の行が表示されます。
2012-11-11 15:55:05,154 INFO Starting new HTTP connection (1): my.ip.address
2012-11-11 15:55:05,294 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 401 211
2012-11-11 15:55:05,430 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 201 0
サーバーは常に最初の認証試行(?)をバウンスしますが、2回目の認証試行を受け入れます。
ファイルオブジェクト(open('trb-1996-219.xml'、'rb'))がデータに渡されると、ログファイルには次のように表示されます。
2012-11-11 15:50:54,309 INFO Starting new HTTP connection (1): my.ip.address
2012-11-11 15:50:55,105 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 401 211
2012-11-11 15:51:25,603 WARNING Retrying (0 attempts remain) after connection broken by 'BadStatusLine("''",)': /v1/documents?uri=/example/test.xml
したがって、最初の試行は以前と同様にブロックされますが、2回目の試行は行われません。
Martijn Pieters(下記)によると、2番目の問題はサーバーの障害(空の回線)によって説明できます。私はこれを調べますが、誰かが(カールを使用することを除いて)回避策を持っているなら、私はそれを聞いてもかまいません。
そして、リクエストライブラリが小さな文字列とファイルオブジェクトに対して非常に異なる動作をすることに、私はまだ驚いています。とにかく、ファイルオブジェクトはサーバーに到達する前にシリアル化されていませんか?