Requests: 全体的なタイムアウト

作成日 2016ĺš´04月16日  Âˇ  38コメント  Âˇ  ソース: psf/requests

TCPトランザクションごとのタイムアウトを設定できるtimeoutパラメータをすでに活用しています。 これはとても役に立ちます! ただし、接続全体の全体的なタイムアウトもサポートする必要があります。 タイムアウトに関するドキュメントを読むと、これは現在サポートされていないことがわかります。少なくとも少し前に問題を検索しても、この機能に対する別のリクエストは見つかりませんでした。すみません。

これを実現するためにライブラリにタイマーを設定できることはわかっていますが、追加のオーバーヘッド(スレッドごとに1つ、多くの場合があります)と、接続プールを中止する必要が生じた場合の悪影響について懸念しています。リクエスト。 そもそもリクエストを中止する良い方法はありますか? ドキュメントに明らかなものは何もありませんでした。

つまり、長期的には、リクエストライブラリに全体的なタイムアウトを追加できれば素晴らしいと思います。 短期的には、これを私の側で実装するための推奨される方法はありますか?

Propose Close

最も参考になるコメント

@jribbensこれにはいくつかの問題があります。

パート1は、そのようなパッチの複雑さが非常に高いことです。 正しく動作させるには、ソケットレベルでタイムアウトを繰り返し変更する必要があります。 これは、パッチがhttplibを介して広範囲に渡される必要があることを意味します。これは、必要以上にパッチを適用しています。 基本的に、この機能変更を実現するには、httplibにアクセスし、より複雑なメソッドの約50%を再実装する必要があります。

パート2は、そのようなパッチの保守が比較的面倒であるということです。 正常に実行するには、httplib(現時点ではより適切にはhttp.client)の並列フォークに相当するものの維持を開始する必要があります。 あるいは、この種の変更により適した別のHTTPスタックの保守負担を引き受ける必要があります。 この部分は、そのような機能を望んでいる人にはよく見落とされていると思います。それを実装するコストは高いですが、すべてのプラットフォームでそのような機能をサポートするための継続的なメンテナンスコストと比較すると、それは何もありません。

パート3は、そのようなパッチの利点が不明確であるということです。 完全なタイムアウトパッチを必要とするほとんどの人は、自分が何を望んでいるかについて完全に明確に考えていないというのが私の経験です。 ほとんどの場合、合計タイムアウトパラメータは、理由もなく完全に適切なリクエストを強制終了する効果があります。

たとえば、ファイルをダウンロードするコードを少し設計し、ハングを処理したいとします。 最初はフラットな合計タイムアウトを設定したいのですが(「リクエストに30秒以上かかることはありません!」)、そのようなタイムアウトはポイントを逃します。 たとえば、ファイルのサイズが30MBから30GBに変更された場合、ダウンロードが完全に正常であっても、そのようなファイルはそのような時間間隔でダウンロードすることはできません。

言い換えると、合計タイムアウトは魅力的な厄介な問題です。問題を解決しているように見えますが、効果的には実行していません。 私の意見では、より便利なアプローチは、 stream=Trueおよびiter_contentと組み合わせて、ソケットアクションごとのタイムアウトを利用し、データのチャンクにタイムアウトを割り当てることです。 iter_contentが機能する方法では、制御フローはある程度一定の間隔でコードに返されます。 つまり、ソケットレベルのタイムアウト(例:5秒)を設定してから、かなり小さなチャンク(例:1KBのデータ)に対してiter_contentを設定し、積極的に攻撃されていない限り、サービス拒否がないことを比較的確信できます。ここで可能です。 サービス拒否が本当に心配な場合は、ソケットレベルのタイムアウトをはるかに低く設定し、チャンクサイズを小さく(0.5秒と512バイト)して、制御フローが定期的に返されるようにします。

これらすべての結果は、このようなライブラリでは、合計タイムアウトが誤った機能であると私が信じていることです。 最適な種類のタイムアウトは、大きな応答が安心してダウンロードできるように調整されたものです。このようなタイムアウトは、ソケットレベルのタイムアウトとiter_contentによって最適に処理されます。

全てのコメント38件

こんにちは@ emgerner-msft、

参考までに、この正確な機能要求ではない場合、以下はこのテーマのすべてのバリエーションです。

これについては、 https://github.com/sigmavirus24/requests-toolbelt/issues/51でも説明しています。

最後のリンクでこのパッケージについて説明していることに気付くでしょう。このパッケージは、リクエストに追加せずにこれを処理する必要があります。 現実には、別のパッケージがすでに非常にうまく機能している場合は、これを実行するように要求する必要はありません。

参照するパッケージは、Webリクエストを実行するための別のプロセスをフォークすることによってそれを行います。 これは、タイムアウトという単純な目標を達成するための非常に重要な方法であり、私の見解では、ネイティブのタイムアウト機能を備えたリクエスト自体に代わるものではありません。

@jribbensスレッドもプロセスも使用しない方法を思い付くことができれば、それは素晴らしいことです。 それまでは、壁掛け時計のタイムアウトが必要な場合は、現時点でそれを達成するための最も信頼できる方法であるパッケージが最善の策です。

@jribbensがスレッドもプロセスも言っていないと思います。 プロセス_per_Webリクエストが過剰であるというだけです。 多くの言語には、単一の追加のスレッドまたはプロセスを共有する複数のタイマーの方法があります。 私はPythonでそれを最もよく行う方法を知らないだけです。

#1928が代替案について最も多く議論されているようですが、ほとんどの場合、多くの注意事項があります(これは、ユースケースなどでは機能しません)。 ライブラリにカスタムコードを入れて、これが本当にリクエストに属していない場合は独自のカスタムソリューションを作成しても問題ありませんが、それがどのようになるかについてもう少し情報が必要だと思います。 リクエストを使用する理由はすべて、低レベルのTCP接続プールロジックから離れるためですが、このカスタムコードを作成するには、そのロジックを知る必要があるスレッドを読んでいるようです。これが問題になっています。 。

@ emgerner-msftは正しいです。 @ sigmavirus24のコメントに少し混乱しています。スレッドやプロセスを使用せずに「完全なタイムアウト」を設定すると、かなり歩行者のように見え、まったく「驚くべき」ことではありません。 プロセス全体の開始時に期限を計算し(例: deadline = time.time() + total_timeout )、個々の操作でタイムアウトをdeadline - time.time()に設定します。

スレッドやプロセスを使用せずに「完全なタイムアウト」を設定することは、非常に歩行者のようであり、まったく「驚くべき」ことではありません。

そして、あなたの解決策はかなり原始的です。 ほとんどの人が合計(またはウォールクロック)タイムアウトを必要とする理由は、読み取りが「ハング」しないようにするためです。つまり、次のような場合です。

r = requests.get(url, stream=True)
for chunk in r.iter_content(chunksize):
    process_data(chunk)

iter_contentの途中で各読み取りに長い時間がかかるが、読み取りタイムアウトよりも短い場合(ストリーミング時に適用すると想定していますが、そうでない場合もあります)、指定しました。 確かに、これは、時計がどのようにドリフトし、夏時間がどのように機能するかを思い出し、それらのtime.time()がひどく不十分であるまで、ソリューション@jribbensによって単純に処理されるべきであるように思われます。

最後に、RequestsのAPIがフリーズしていることを覚えておくことが重要です。 合計タイムアウトを指定するための適切で一貫性のあるAPIはありません。 そして、あなたが提案するようにタイムアウトを実装した場合、合計タイムアウトを1分間指定するというバグが無数にありますが、前回チェックしたときに1分未満でしたが、構成された読み取りタイムアウトがタイムアウトになるほど長いため、時間がかかりましたエラーは約1分半で発生しました。 これは_非常に_大まかな壁のタイムアウトであり、これを探している人にとっては少し良いでしょうが、これを自分で実装している人と同じです。

申し訳ありませんが、 @ sigmavirus24が不明な場合は、私の疑似コードの原理の図を、文字通りのパッチだと思っているかのように批判しているようです。 ただし、 time.time()は、見た目どおりに機能しないことを指摘しておく必要があります。夏時間は関係ありません。また、ここで説明しているタイムスケールのクロックスキューも関係ありません。 また、説明したバグが発生すると思われる場合は、提案を誤解しています。 最後に、APIがバージョン2.9.0と同じくらい最近変更されたため、Requests APIが「凍結」されているとはどういう意味かわかりません。そのため、私が通常理解していることとは異なります。

私の議論を分離するためだけに:私は実際、これが簡単であると主張しているわけではありません。 それが完全に単純であるならば、私はそれを書いて、あなたを悩ますのをやめます。 :)

私の問題は次のとおりです。
1)リストしたスレッドのすべてがモンキーパッチでした。 それは問題ありませんが、私はこれを本番品質のライブラリで使用しており、すべてを壊す内部変更の警告を受け取ることはできません。
2)あなたが与えたリンクのタイムアウトデコレータは素晴らしいですが、それが接続にどのように影響するかはわかりません。 タイムアウトを実行する唯一の良い方法が多数のスレッドを使用することであると認めたとしても、このライブラリは、ソケットのシャットダウン、接続の切断などをどのように強制しますか。多くの接続を実行しており、これは潜在的にかなりのようです。漏れやすい。 リクエストには私が見つけることができる「abort」メソッドがありません(私が間違っている場合は修正してください)ので、接続のシャットダウンはどのように発生しますか?

私が探しているのは、この問題を自分で解決する方法の明確な「祝福された」バージョンです。完璧な解決策がない場合は、注意事項を含むいくつかの解決策について説明します。 それは理にかなっていますか?

@ emgerner-msft CPythonを使用しているとすると、リクエストが続行されなくなると接続がシャットダウンします。 その時点で、基になる接続へのすべての参照が失われ、ソケットが閉じられて破棄されます。

@Lukasaわかりました、ありがとう! ライブラリは、リクエストが継続されなくなったことをどのように判断しますか? たとえば、タイムアウトデコレータルートを使用してダウンロードの途中で切断した場合、ダウンロードは実際にいつ停止しますか? ストリーミングオプションで何か特別なことをする必要がありますか?

タイムアウトデコレータを使用する場合、タイムアウトが発生するとダウンロードが停止します。 これは、シグナルがsyscallを中断するためです。これは、ソケットへのそれ以上の呼び出しがないことを意味します。 リクエストがスコープ内になくなると(たとえば、スタックがrequests.*関数の外側に巻き戻されると)、次のようになります。CPythonは接続オブジェクトをクリーンアップし、接続を切断します。 そこでは特別なストリーミングオプションは必要ありません。

完全。 他の人がもっと言うことがない限り、私はその時スレッドを閉じるのは良いことです。

実際、申し訳ありませんが、もう1つ懸念があります。 Pythonタイマーのようなもの(おそらく)とは対照的に、シグナルを使用することが適切であるとあなたが言ったので、タイムアウトデコレータコードをより詳しく調べていました。 Windowsでは動作しないようにPythonSignalに記載されているSIGALRMでsignalを呼び出しているようです。 これは、Unix環境とWindows環境の両方、およびPython 2.7と3.3以降(リクエスト自体と同じように)で機能するために必要です。 もう少し詳しく見て、これが実際に機能するかどうかを確認します。

@ emgerner-msftそれはイライラします。 =(

@Lukasaうん、基本的な使用法スニペットを試しましたが、Windowsでは機能しません。 コード/例をもう少し読んでいじくり回しました。シグナルを使用しないとパッケージが機能するように見えますが、すべてを選択可能にする必要があります。これは私のアプリケーションには当てはまりません。 私の知る限り、タイムアウトデコレータは私の問題を解決しません。 他のアイデアはありますか?

@ emgerner-msft Windows固有の信号はどれも適切ではないと確信していますか?

@Lukasa率直に言って、私にはわかりません。 私はこれまでシグナルを使用したことがなく、リクエストを中断すると言われるまで気づかなかったように、何が適切かわかりません。 また、Windowsで動作させるためだけにこれを取得しようとはしていません。 完全なクロスプラットサポート(WindowsとUnix)と、Python2とPython3の両方のサポートが必要です。 信号の多くはプラットフォーム固有に見えますが、それは私を投げています。 タイマーは私が見ていた解決策の1つであり、低レベルではないように見えたため、制約を処理できる可能性がありますが、接続を閉じる方法がわかりません。 私はもっ​​と読むことができますが、これが私があなたたちから追加のガイダンスを得ることを望んでいた理由です。 :)

ですから、これは本当にトリッキーな場所です。

現実には、スレッドを中断する以外に、スレッドを強制終了するクロスプラットフォームの方法は多かれ少なかれありません。これは基本的にシグナルです。 つまり、プラットフォーム間でこれを機能させるために実際に必要なルートは信号だけだと思います。 私はWindowsyPythonyの専門家にpingを送信しようとする傾向があります: @brettcannon 、ここに良い提案がありますか?

興味深いことに、実装とテストに作業が必要な場合を除いて、リクエストに「合計タイムアウト」を実装しない理由はありますか? つまり、それを実装するためのパッチが今日魔法のように登場した場合、理論的には拒否または受け入れられますか? 「不必要な複雑さを排除する」という観点に感謝し、同意しますが、「別のプロセスをフォークすることでそれを実行できる」という観点から、この機能が不要になるわけではないと思います。

@jribbensこれにはいくつかの問題があります。

パート1は、そのようなパッチの複雑さが非常に高いことです。 正しく動作させるには、ソケットレベルでタイムアウトを繰り返し変更する必要があります。 これは、パッチがhttplibを介して広範囲に渡される必要があることを意味します。これは、必要以上にパッチを適用しています。 基本的に、この機能変更を実現するには、httplibにアクセスし、より複雑なメソッドの約50%を再実装する必要があります。

パート2は、そのようなパッチの保守が比較的面倒であるということです。 正常に実行するには、httplib(現時点ではより適切にはhttp.client)の並列フォークに相当するものの維持を開始する必要があります。 あるいは、この種の変更により適した別のHTTPスタックの保守負担を引き受ける必要があります。 この部分は、そのような機能を望んでいる人にはよく見落とされていると思います。それを実装するコストは高いですが、すべてのプラットフォームでそのような機能をサポートするための継続的なメンテナンスコストと比較すると、それは何もありません。

パート3は、そのようなパッチの利点が不明確であるということです。 完全なタイムアウトパッチを必要とするほとんどの人は、自分が何を望んでいるかについて完全に明確に考えていないというのが私の経験です。 ほとんどの場合、合計タイムアウトパラメータは、理由もなく完全に適切なリクエストを強制終了する効果があります。

たとえば、ファイルをダウンロードするコードを少し設計し、ハングを処理したいとします。 最初はフラットな合計タイムアウトを設定したいのですが(「リクエストに30秒以上かかることはありません!」)、そのようなタイムアウトはポイントを逃します。 たとえば、ファイルのサイズが30MBから30GBに変更された場合、ダウンロードが完全に正常であっても、そのようなファイルはそのような時間間隔でダウンロードすることはできません。

言い換えると、合計タイムアウトは魅力的な厄介な問題です。問題を解決しているように見えますが、効果的には実行していません。 私の意見では、より便利なアプローチは、 stream=Trueおよびiter_contentと組み合わせて、ソケットアクションごとのタイムアウトを利用し、データのチャンクにタイムアウトを割り当てることです。 iter_contentが機能する方法では、制御フローはある程度一定の間隔でコードに返されます。 つまり、ソケットレベルのタイムアウト(例:5秒)を設定してから、かなり小さなチャンク(例:1KBのデータ)に対してiter_contentを設定し、積極的に攻撃されていない限り、サービス拒否がないことを比較的確信できます。ここで可能です。 サービス拒否が本当に心配な場合は、ソケットレベルのタイムアウトをはるかに低く設定し、チャンクサイズを小さく(0.5秒と512バイト)して、制御フローが定期的に返されるようにします。

これらすべての結果は、このようなライブラリでは、合計タイムアウトが誤った機能であると私が信じていることです。 最適な種類のタイムアウトは、大きな応答が安心してダウンロードできるように調整されたものです。このようなタイムアウトは、ソケットレベルのタイムアウトとiter_contentによって最適に処理されます。

たぶん@zoobaは、Windowsがどのように機能するかを実際に知っているので、アイデアを持っています。 :)

(無関係に、私の好きなことの1つは、GitHubの問題で専門家のデイジーチェーンを設定することです。)

ハハ、私はすでに@zoobaと@brettcannonを知っています。 これに対する解決策はおそらく彼らにも役立つので、私はここで、または社内で彼らと話し合うことができます。

@ emgerner-msft私はあなたがそうかもしれないと思いましたが、推測したくありませんでした:MSFTは大きな組織です!

@Lukasa上で書いたテキストの壁を読んでいるだけです-面白いです! stream = Trueとiter_contentから時間ダウンロードまでの議論で、より大きなアップロードを処理する同等の方法は何ですか?

_PS_:「別の言い方をすれば..」で始まる上記の段落は、私がドキュメントで探していた種類のガイダンスです。 最大タイムアウトで取得するリクエストの数(およびそれを行わない正当な理由)を考えると、おそらく最善の方法は、タイムアウトドキュメントにその情報の一部を追加することです。

笑@lukasaすでに頭に浮かんだメンテナンスについておっしゃっていますが、「機能vs誤機能」については、正反対です。 完全なタイムアウトを_望まない_人は、彼らが何を望んでいるのかを明確に考えていないと思います。あなたがバグとして説明している「30MBのダウンロードが30GBに変更され、失敗する」という状況を想像するのは難しいです。実際、有益な機能です!

あなたが言うように、 stream=Trueを使用して少し似たようなことをすることができます(しかし、完全なタイムアウトの利点のほとんどがないと思います)が、リクエストのポイントはそれがあなたのために物事を処理することだと思いました...

リクエストのポイントは、それがあなたのために物事を処理することだと思いました

HTTPを処理します。 接続と読み取りのタイムアウトをすでに処理しており、数年間の機能のフリーズに対して2つの例外があったという事実は、ユーティリティ、望ましさ、一貫性(複数のプラットフォーム間)、および保守性の議論に正接しています。 皆様からのフィードバックとご意見をお待ちしております。 提示する新しい情報があれば、それをいただければ幸いです。

また、このプロジェクトで拒否された機能リクエストの数と、ユーザーの一般的な使用パターンを実装する別のプロジェクト(リクエストツールベルト)があるという事実によって、リクエストがすべてを処理するわけではないこともわかります。 合計タイムアウトがどこかにある場合、それはそこにありますが、繰り返しになりますが、Windows、BSD、Linux、およびOSXで、優れたテストカバレッジを備え、維持するのが悪夢になることなく動作する必要があります。

stream = Trueとiter_contentから時間ダウンロードまでの議論で、より大きなアップロードを処理する同等の方法は何ですか?

アップロード用のジェネレーターを定義し、それをdataに渡します。 または、チャンクエンコーディングが勝者でない場合は、魔法のreadメソッドを使用してファイルのようなオブジェクトを定義し、_that_をdataに渡します。

少し詳しく説明させてください。 ジェネレーターをdataに渡すと、リクエストはジェネレーターを繰り返し処理し、各チャンクを順番に送信します。 つまり、データを送信するには、チャンクごとにコードに制御フローを渡す必要があります。 これにより、例外をスローしてリクエストを完全に中止するなど、その間にやりたいことが何でもできます。

何らかの理由でアップロードにチャンク転送エンコーディングを使用できない場合(可能性は低いですが、問題のサーバーが本当に悪い場合は可能です)、長さのあるファイルのようなオブジェクトを作成してから、 read呼び出しの魔法。これは、8192バイトのチャンクに対して繰り返し呼び出されます。 繰り返しになりますが、これにより、制御フローがコードを断続的に通過するようになり、独自のロジックを使用できるようになります。

PS:「別の言い方をすれば..」で始まる上記の段落は、私がドキュメントで探していた種類のガイダンスです。 最大タイムアウトで取得するリクエストの数(およびそれを行わない正当な理由)を考えると、おそらく最善の方法は、タイムアウトドキュメントにその情報の一部を追加することです。

私は考えます_。 しかし、一般的に言って、私は常に、いくらか防御的なテキストをドキュメントに入れることに神経質になっています。 それは私が推測するFAQに入る可能性がありますが、なぜ私たちが何かを持っていないのかを説明するテキストがドキュメントで役立つことはめったにありません。 ドキュメント内のスペースは、何かをするためのレシピによって、より適切に提供されると思います。

完全なタイムアウトを望まない人は、自分が何を望んでいるのかを明確に考えていないと思います。「30MBのダウンロードが30GBに変更されるため、失敗する」というバグとして説明するものがそうではない状況を想像するのは難しいです。実際、有益な機能です!

ええ、私は違います:

  • パッケージマネージャー(リクエストを使用するpipなど)。パッケージのデータサイズは大きく異なります。
  • サイズが大きく異なる複数のサイトに対して実行される可能性のあるWebスクレイパー
  • 私たちのレベルが大きく異なるホストからログファイルをダウンロードするログアグリゲーター(したがって、ログファイルのサイズ)
  • ビデオダウンローダー(ビデオのサイズは大きく異なる場合があります)

実際には、開発者が処理するファイルサイズを1桁以内で知っているというのは、珍しいケースだと思います。 ほとんどの場合、開発者は何も知りません。 そして、一般的に、これらのサイズについて仮定することは賢明ではないと思います。 ダウンロードサイズに制約がある場合、コードはそれらの仮定を暗黙的にエンコードしてユーザーのネットワークの帯域幅と混合するのではなく、意図的にエンコードする必要があります(たとえば、コンテンツの長さのチェックの形で)。コードはそれらをはっきりと見ることができます。

でもリクエストのポイントはそれがあなたのために物事を処理することだと思いました...

リクエストは、ユーザーにとってすべてを意図的に処理するわけではありません。 すべてを実行しようとすることは不可能な作業であり、それを実行する優れたライブラリを構築することは不可能です。 何かを達成するために、定期的にurllib3にドロップダウンするようにユーザーに指示します。

コードをリクエストに入れるのは、ほとんどのユーザーが実行できるよりも優れた、またはクリーンなコードを実行できる場合のみです。 そうでなければ、価値はありません。 特に、ユーザーベース全体で集計したときに比較的限界効用であると私が認識していることを考えると、私はまだそれらの1つである合計タイムアウトで売られていません。

とは言うものの、私は自分が間違っていると確信することを受け入れています。私はまだ説得力のある議論を見ていません(そして、パスであなたを先導するために、「私はそれが必要です!」は説得力のある議論ではありません:いくつかの理由を挙げなければなりません!)。

@ sigmavirus24

合計タイムアウトがどこかにある場合、それはそこにありますが、繰り返しになりますが、Windows、BSD、Linux、およびOSXで、優れたテストカバレッジを備え、維持するのが悪夢になることなく動作する必要があります。

同意しました!

@lukasa私の考えでは、私はそれが欲しいだけでなく、実際、ほとんどすべてのユーザーがそれについて考えればそれを望んでいると思います(または彼らはそれがまだそこにないことに気づいていません)。 上記の使用シナリオの半分は避けるべきだと言っていますが、それは重要だと思います(Webスクレイパーとログアグリゲーター)-他の2つは、結果を待っているユーザーが手動でダウンロードをキャンセルできる可能性があるため、それほど必要ではありません。彼らが望む。 UIなしでバックグラウンドで実行され、全体的なタイムアウトを使用しないものはすべて、私の見解ではバグがあります。

私の考えでは、私はそれが欲しいだけでなく、実際、ほとんどすべてのユーザーがそれについて考えればそれを望んでいるだろうと思います(または彼らはそれがまだそこにないことに気づいていません)。

@jribbensユーザーのニーズと話し合い、理解するのに数年(3人全員の経験を組み合わせると10年以上)あります。 ほとんどすべて(少なくとも98%)のユーザーに必要なのは、接続と読み取りのタイムアウトです。 非常に少数のユーザーが全体的なタイムアウトを望んでいることを理解しています。 その機能の潜在的なユーザーのグループのサイズと、その機能を必要としないユーザーの潜在的なサイズ、および機能の保守と開発の複雑さを推定できることを考えると、それは実際には私たちが行っていることではありませんすること。

共有する_新しい_ものがあれば、それを聞きたいのですが、これまでのところ、全体的なタイムアウトなしでリクエストを使用するものはバグがあり、多くのユーザーがいると思います。彼らの設計上の決定はバグがあるというあなたの主張に腹を立てるでしょう。 したがって、ユーザーの知性を侮辱することはご遠慮ください。

@ sigmavirus24このスレッドを通して、あなたは不必要に見下し、炎症を起こし、失礼でした。丁寧にお願いします。やめてください。

@Lukasaストリーミングのアップロードとダウンロードを行う方法についての提案を詳しく調べ、これらのトピックに関するドキュメントを読みました。 私の仮定/質問を検証できれば、それは素晴らしいことです。

  1. ストリーミングダウンロードの場合、読み取りタイムアウト(たとえば、5秒)のようなものを使用してから、かなり小さなチャンク(たとえば、1KBのデータ)でiter_contentを使用する場合、これは、リクエストライブラリが1KBの読み取りごとに5秒のタイムアウトを適用し、それがあればタイムアウトを適用することを意味します5秒以上かかります。 正しい?
  2. ストリーミングアップロードの場合、データのチャンクを返すジェネレーターまたはオブジェクトのようなファイルを使用し、読み取りタイムアウトを5秒に設定すると、リクエストライブラリは、返すチャンクごとに5秒のタイムアウトを適用し、時間がかかる場合はタイムアウトします。 正しい?
  3. アップロードにジェネレーターを使用せず、バイトを直接渡す場合、リクエストライブラリは設定した読み取りタイムアウトをどのように適用するかを決定しますか? たとえば、サイズ4MBのチャンクと5秒の読み取りタイムアウトを渡した場合、その読み取りタイムアウトはいつ適用されますか?
  4. iter_contentを使用せず、リクエストにすべてのコンテンツを5秒の読み取りタイムアウトでリクエストに直接ダウンロードさせる場合、その読み取りタイムアウトはいつ適用されますか?

私はソケット/ TCPプロトコルなどの一般的な理解を持っていますが、urllibがこれらの概念を下位レベルでどのように機能するか、または要求が値を渡す以外に特別なことを行うかどうかは正確にはわかりません。 単に制御フローを取り戻し、スレッドの終了に関するクロスプラットの問題を考えると、独自のタイムアウトスキームを適用しても機能しないため、タイムアウトがどのように適用されるかを正確に理解したいと思います。 私の質問に答えるための追加の読み物がある場合は、遠慮なく私を紹介してください! いずれにせよ、これが私の最後の質問になることを願っています。 :)

これまでのご協力に感謝します。

@ emgerner-msft Ok:

  1. いいえ。悲しいことに、それよりも複雑です。 説明したように、各タイムアウトは_ソケット呼び出しごと_に適用されますが、特定のチャンクに含まれるソケット呼び出しの数を保証することはできません。 これの非常に複雑な理由は、標準ライブラリがバッキングソケットをバッファオブジェクト(通常はio.BufferedReaderのようなもの)でラップすることです。 これにより、十分なデータが提供されるまで、必要な数のrecv_into呼び出しが行われます。 これは、ゼロ(バッファにすでに十分なデータがある場合)またはリモートピアが一度に1バイトずつドリップフィードしている場合は、受信したバイト数と同じくらいの数になる可能性があります。 これについてできることはほとんどありません。このようなバッファリングされたオブジェクトに対するread()呼び出しの性質上、各recv_into呼び出しの間に制御フローを戻すことすらできません。

つまり、n秒以内の待機を保証する唯一の方法は、チャンクサイズが1のiter_contentを実行することです。 これは、ファイルをダウンロードするための非常に非効率的な方法です(Pythonコードで非常に多くの時間を費やします)が、必要な保証を取得する唯一の方法です。

  1. また、その答えはノーだと思います。 現在、_send_タイムアウトの概念はありません。 1つを取得する方法は、 socket.setdefaulttimeoutを使用することです。
  2. 読み取りタイムアウトは読み取りにのみ適用されるため、本文をどのように渡すかは問題ではありません。
  3. その読み取りタイムアウトには、 iter_contentの場合と同じ懸念があります。すべてをダウンロードするリクエストがある場合、本文をダウンロードするために必要な数のrecv_into呼び出しを発行することになり、タイムアウトが適用されます。順番にそれぞれに。

ここでコアの問題にぶつかっています。要求は、探しているものを正確に達成するためにソケットに十分に近づかないだけです。 送信タイムアウトを追加することは_可能_です。これは機能要求の作業を考慮したものであり、読み取りタイムアウトと同じ問題は発生しませんが、 httplibが(正しく)スワッピングを要求するため、他のすべての問題が発生します。バッファリングされたソケット表現に変換すると、残りのhttplibはそのバッファリングされた表現を使用します。

@ルカサ

ああ、なんてめちゃくちゃだ、ハハ。 そうかもしれないと思いましたが、自分が間違っていることを本当に望んでいました。

まず、送信タイムアウトがどうしても必要です。 アップロードが無限にハングする可能性があることをユーザーに伝えることはできず、問題を修正する計画はありません。 :/

現時点では、私は不可能な状況にあるようです。 合計タイムアウトに対するライブラリのサポートはありません(私は理解しています)。 既存のタイムアウトがさまざまなチャンクサイズでどのように機能するかについての正確な保証はありません-もしあれば、時間を合計することができます:接続タイムアウト+読み取りタイムアウト*チャンクサイズ。 ストリームモードとジェネレーターでフローを中断できるのは素晴らしいことですが、クロスプラットフォームの方法で実際にスレッドを中止するソリューションがないため、これも役に立ちません。 前進するための他のオプションがありますか? これらの問題を解決するために他のユーザーは何をしていますか?

まず、送信タイムアウトがどうしても必要です。 アップロードが無限にハングする可能性があることをユーザーに伝えることはできず、問題を修正する計画はありません。 :/

したがって、リクエストで使用されるタイムアウトロジックは、基本的にurllib3のロジックであるため、そこで変更を加えるだけで十分です。機能リクエストを自由に開いてください。変更をお手伝いします。 そして短期的には、 setdefaulttimeoutを使用して自由に調査してください。

前進するための他のオプションがありますか? これらの問題を解決するために他のユーザーは何をしていますか?

ここにあるオプションは、特定の制約によって異なります。

確定的なタイムアウトが必要な場合(つまり、リクエストが_n_秒以内にかかることを保証できる必要がある場合)、現在存在するPython標準ライブラリでは簡単にそれを行うことはできません。 Python 2.7では、 socket._fileobjectにパッチを適用して、 recv呼び出しごとに順次タイムアウトを実行できるようにする必要がありますが、Python 3では、実装が実装されているクラスにパッチを適用する必要があるため、さらに困難です。はC( io.BufferedReader )であり、これは悪夢になります。

それ以外の場合、それを取得する唯一の方法は、標準ライブラリのバッファリングを_オフ_にすることです。 これにより、httplibとその上のすべてのパッチが破損します。これは、ソケットでのreadシステムコールではなく、 read #のように動作するread(x)呼び出しを実行できることを前提としています。ファイルに対するread syscall(つまり、決定論的な長さを返します)。

別の言い方をすれば、決定論的なタイムアウトが_必要_な場合、膨大な数のライブラリがそれを提供できないことに気付くでしょう。 基本的に、彼らがhttplibまたはsocket.makefileを使用する場合、運が悪くなります。長さを繰り返し発行することを除いて、定義された時間内に制御が返されることを保証するクリーンな方法はありません。 -1回の読み取り。 あなたはそれを_できます_が、それはあなたのパフォーマンスを損なうでしょう。

したがって、ここでトレードオフがあります。決定論的なタイムアウトが必要な場合、Python標準ライブラリ(およびリクエスト)でバッファリングを実装する方法では、それを利用できるようにはなりません。 バッファリングを無効にしてコードを書き直すことでそれを取り戻すことができますが、タイムアウトを確認する方法でバッファリングを再実装しない限り、パフォーマンスが大幅に低下する可能性があります。

BufferedReaderクラスのPython標準ライブラリに必要なコードを実装することを目指すことができます。Pythonの人々に興味があるかどうかを確実に尋ねることができます。 しかし、私は息を止めませんでした。

したがって、リクエストで使用されるタイムアウトロジックは、基本的にurllib3のロジックであるため、そこで変更を加えるだけで十分です。機能リクエストを自由に開いてください。変更をお手伝いします。 また、短期的には、setdefaulttimeoutを使用して自由に調査してください。

urllib3またはここでの機能リクエスト? できるだけ早く一方(または両方)を開きます。

urllib3の機能リクエスト:リクエストで新しいものを公開する必要はありません。

このページは役に立ちましたか?
0 / 5 - 0 評価