Requests: المهلة الإجمالية

تم إنشاؤها على ١٦ أبريل ٢٠١٦  ·  38تعليقات  ·  مصدر: psf/requests

نحن بالفعل نستفيد بشكل كبير من معلمة timeout التي تسمح بتحديد مهلات معاملة TCP. هذا مفيد جدا! ومع ذلك ، نحتاج أيضًا إلى دعم المهلة الإجمالية عبر الاتصال. قراءة المستندات في المهلات التي أرى أن هذا غير مدعوم حاليًا ، وأثناء البحث في المشكلات على الأقل قليلاً ، لم أر طلبًا آخر لهذه الميزة - عفوا إذا كان هناك.

أدرك أنه يمكننا ضبط مؤقتات في مكتبتنا لإنجاز ذلك ، لكني قلق بشأن النفقات الإضافية (واحد لكل سلسلة رسائل ، وقد يكون لدينا الكثير) بالإضافة إلى أي آثار سلبية لتجميع الاتصال إذا انتهى بنا الأمر إلى إحباط طلب. هل هناك طريقة جيدة لإجهاض الطلب في المقام الأول؟ لم أر أي شيء واضح في المستندات.

لذلك: على المدى الطويل ، سيكون من الرائع أن نتمكن من إضافة المهلة الإجمالية إلى مكتبة الطلبات. على المدى القصير ، هل هناك طريقة موصى بها لتنفيذ ذلك من جانبي؟

Propose Close

التعليق الأكثر فائدة

jribbens هناك بعض المشاكل مع هذا.

الجزء الأول هو أن درجة تعقيد مثل هذه الرقعة عالية جدًا. لجعله يتصرف بشكل صحيح ، تحتاج إلى تغيير المهلات بشكل متكرر على مستوى المقبس. هذا يعني أن التصحيح يحتاج إلى أن يتم تمريره على نطاق واسع من خلال برنامج الموقع الإلكتروني ، والذي قمنا بتصحيحه بالفعل أكثر مما نرغب في ذلك. بشكل أساسي ، سنحتاج إلى الوصول إلى HTplib وإعادة تنفيذ حوالي 50٪ من أساليبها الأكثر تعقيدًا من أجل تحقيق هذا التغيير الوظيفي.

الجزء الثاني هو أن الحفاظ على مثل هذا التصحيح مرهق نسبيًا. سنحتاج على الأرجح إلى البدء في الحفاظ على ما يرقى إلى مستوى متفرع متوازي من الموقع (http.client بشكل أكثر ملاءمة في هذا الوقت) من أجل القيام بذلك بنجاح. بدلاً من ذلك ، سنحتاج إلى تحمل عبء الصيانة الخاص بمكدس HTTP مختلف يكون أكثر قابلية لهذا النوع من التغيير. هذا الجزء ، كما أظن ، غالبًا ما يفتقده أولئك الذين يرغبون في الحصول على مثل هذه الميزة: تكلفة تنفيذه مرتفعة ، لكن هذا _ لا شيء _ مقارنة بتكاليف الصيانة المستمرة لدعم مثل هذه الميزة على جميع الأنظمة الأساسية.

الجزء 3 هو أن ميزة هذا التصحيح غير واضحة. لقد كانت تجربتي أن معظم الأشخاص الذين يريدون تصحيح مهلة كاملة لا يفكرون بوضوح تام فيما يريدون. في معظم الحالات ، ينتهي المطاف بمعلمات المهلة الإجمالية بالتأثير في قتل الطلبات الجيدة تمامًا دون سبب.

على سبيل المثال ، لنفترض أنك صممت قليلاً من التعليمات البرمجية لتنزيل الملفات ، وترغب في التعامل مع حالات التعليق. في حين أنه من المغري في البداية تحديد مهلة إجمالية ثابتة ("قد لا يستغرق أي طلب أكثر من 30 ثانية!") ، فإن مثل هذه المهلة تفوت النقطة. على سبيل المثال ، إذا تغير حجم الملف من 30 ميغابايت إلى 30 غيغابايت ، فلا يمكن تنزيل مثل هذا الملف أبدًا في هذا النوع من الفاصل الزمني ، على الرغم من أن التنزيل قد يكون سليمًا تمامًا.

بعبارة أخرى ، تعد المهلات الإجمالية مصدر إزعاج جذاب: يبدو أنها تحل مشكلة ، لكنها لا تفعل ذلك بشكل فعال. هناك نهج أكثر فائدة ، في رأيي ، هو الاستفادة من مهلة الإجراء لكل مقبس ، جنبًا إلى جنب مع stream=True و iter_content ، وتخصيص مهلات لأجزاء من البيانات. بالطريقة التي يعمل بها iter_content ، سيتم إرجاع تدفق التحكم إلى الكود الخاص بك في فترة زمنية منتظمة إلى حد ما. هذا يعني أنه يمكنك تعيين مهلات على مستوى المقبس (على سبيل المثال 5 ثوانٍ) ثم iter_content على أجزاء صغيرة إلى حد ما (على سبيل المثال 1 كيلو بايت من البيانات) وكن واثقًا نسبيًا من أنه ما لم تتعرض لهجوم نشط ، فلا يوجد رفض للخدمة ممكن هنا. إذا كنت قلقًا حقًا بشأن رفض الخدمة ، فقم بتعيين مهلة مستوى المقبس لديك على مستوى أقل بكثير وحجم مجموعتك أصغر (0.5 ثانية و 512 بايت) للتأكد من أنك تتحكم بانتظام في التدفق إليك.

نتيجة كل هذا هو أنني أعتقد أن المهلات الإجمالية هي ميزة غير ملائمة في مكتبة مثل هذه. أفضل نوع من المهلة هو الذي يتم ضبطه لإتاحة وقت كافٍ للاستجابات الكبيرة للتنزيل في سلام ، وأفضل وقت يتم تقديمه من خلال المهلات على مستوى المقبس و iter_content .

ال 38 كومينتر

مرحبًا @ emgerner-msft ،

كمرجع ، ما يلي هو جميع الاختلافات في هذا الموضوع إذا لم يكن طلب الميزة بالضبط:

لقد ناقشنا هذا الأمر أيضًا على https://github.com/sigmavirus24/requests-toolbelt/issues/51

ستلاحظ أن الرابط الأخير يناقش هذه الحزمة التي يجب أن تتعامل معها دون إضافتها إلى الطلبات. الحقيقة هي أنه ليست هناك حاجة لطلبات للقيام بذلك عندما تقوم حزمة أخرى بذلك بالفعل بشكل جيد للغاية.

الحزمة التي تشير إليها تقوم بذلك عن طريق إجراء عملية منفصلة لتشغيل طلب الويب. هذه طريقة ثقيلة للغاية لتحقيق الهدف البسيط المتمثل في انتهاء المهلة ، وفي رأيي ليست بأي حال من الأحوال بديلاً للطلبات نفسها التي تحتوي على ميزة مهلة أصلية.

jribbens إذا كان بإمكانك التوصل إلى طريقة لا تستخدم الخيوط أو العمليات ، فسيكون ذلك رائعًا. حتى ذلك الحين ، إذا كنت تريد مهلة ساعة الحائط ، فإن أفضل رهان لك هو تلك الحزمة لأنها الطريقة الأكثر موثوقية لتحقيق ذلك في الوقت الحالي.

لا أعتقد أن jribbens يقول لا سلاسل ولا عمليات. مجرد أن عملية _ لكل_ طلب ويب مفرطة. تمتلك العديد من اللغات وسيلة لمؤقتات متعددة تتشارك في سلسلة أو عملية إضافية واحدة. أنا لست على دراية بكيفية القيام بذلك بشكل أفضل في بايثون.

يبدو أن # 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 ولكنها أقل من مهلة القراءة (أفترض أننا نطبق ذلك عند البث ، ولكن قد لا نزال كذلك) هم حددوا . بالتأكيد يبدو أنه يجب التعامل مع هذا ببساطة من خلال الحل الخاص بك jribbens حتى تتذكر كيف تنجرف الساعات والتوقيت الصيفي وأنهم time.time() غير كافيين بشكل محزن.

أخيرًا ، من المهم أن تضع في اعتبارك أنه تم تجميد واجهة برمجة تطبيقات الطلبات. لا توجد واجهة برمجة تطبيقات جيدة أو متسقة لتحديد إجمالي المهلة. وإذا طبقنا مهلة كما تقترح ، فسنحصل على عدد لا يحصى من الأخطاء التي حددوها لمدة دقيقة واحدة إجمالاً ، لكنها استغرقت وقتًا أطول لأن آخر مرة تحققنا فيها كنا أقل من دقيقة ولكن مهلة القراءة التي تمت تهيئتها كانت طويلة بما يكفي لأن المهلة الخاصة بهم أثير الخطأ حوالي دقيقة ونصف. إنها مهلة _very_ تقريبية للجدار والتي ستكون أفضل قليلاً للأشخاص الذين يبحثون عن هذا ، ولكنها لا تختلف عن الشخص الذي ينفذ هذا بنفسه.

أعتذر إذا لم أكن واضحًا في @ sigmavirus24 ، يبدو أنك قد انتقدت توضيح المبدأ الخاص بي للرمز الزائف كما لو كنت تعتقد أنه تصحيح حرفي. يجب أن أشير إلى أن time.time() لا يعمل بالطريقة التي تعتقدها على ما يبدو - التوقيت الصيفي ليس مناسبًا ، ولا أيضًا انحراف الساعة على المقاييس الزمنية التي نتحدث عنها هنا. كما أنك أساءت فهم الاقتراح إذا كنت تعتقد أن الخطأ الذي وصفته سيحدث. أخيرًا ، لست متأكدًا مما تقصده ب "تجميد" واجهة برمجة التطبيقات للطلبات حيث تم تغيير واجهة برمجة التطبيقات مؤخرًا مثل الإصدار 2.9.0 لذا من الواضح أن كل ما تقصده ليس ما أفهمه عادةً بالكلمة.

فقط لفصل مناقشتي: أنا في الواقع لا أجادل أن هذا سهل. إذا كان الأمر بسيطًا تمامًا ، لكنت سأكتبه فقط وأتوقف عن إزعاجك. :)

مشاكلي هي:
1) كل شيء في المواضيع التي ذكرتها كان عبارة عن رقع قرد. لا بأس بذلك ، لكني أستخدم هذا في مكتبة جودة الإنتاج ولا يمكنني تحمل التحذير من التغييرات الداخلية التي تكسر كل شيء.
2) مصمم المهلة في الرابط الذي قدمته رائع ، لكني لست واضحًا بشأن كيفية تأثير ذلك على الاتصال. حتى لو قبلنا أن الطريقة الجيدة الوحيدة للقيام بالمهلة هي باستخدام مجموعة من الخيوط ، فكيف تفرض هذه المكتبة أن يتم إغلاق المقبس ، وانقطاع الاتصال ، وما إلى ذلك. إننا نقوم بالكثير من الاتصالات وهذا يبدو على الأرجح تمامًا عرضة للتسرب. لا تحتوي الطلبات على طريقة "إحباط" يمكنني العثور عليها (صححني إذا كنت مخطئًا) فكيف يتم إغلاق الاتصال؟

كل ما أبحث عنه هو نسخة "مباركة" واضحة لكيفية حل هذه المشكلة بمفردي ، أو إذا لم يكن هناك حل مثالي ، فقد تمت مناقشة حلين مع المحاذير. هل هذا منطقي؟

@ emgerner-msft بافتراض أنك تستخدم CPython ، فسيتم إيقاف الاتصال عندما يتوقف الطلب عن الاستمرار. في هذه المرحلة ، ستفقد جميع الإشارات إلى الاتصال الأساسي وسيتم إغلاق المقبس والتخلص منه.

@ لوكاسا حسنًا ، شكرًا! كيف تحدد المكتبة أن الطلب لم يعد مستمرًا؟ على سبيل المثال ، إذا استخدمت مسار timeout decorator وانقطعت في منتصف التنزيل ، فمتى سيتوقف التنزيل بالفعل؟ هل أحتاج إلى فعل أي شيء خاص مع خيارات البث؟

إذا كنت تستخدم مصمم المهلة ، فسيتوقف التنزيل عند انتهاء المهلة. وذلك لأن الإشارات تقاطع syscalls ، مما يعني أنه لن تكون هناك مكالمات أخرى في المقبس. بمجرد أن يصبح الطلب غير موجود في النطاق (على سبيل المثال ، تم فك المكدس إلى خارج وظيفة requests.* الخاصة بك) ، سيكون هذا في: CPython سينظف كائن الاتصال ويمزق الاتصال. لا توجد خيارات تدفق خاصة مطلوبة هناك.

في احسن الاحوال. أنا جيد لإغلاق الموضوع بعد ذلك ، ما لم يكن لدى الآخرين المزيد ليقولوه.

في الواقع ، آسف ، مصدر قلق آخر. كنت تبحث عن رمز مصمم المهلة عن كثب لأنك قلت إنه يستخدم إشارات كانت ذات صلة ، على عكس شيء مثل Python Timers (على الأرجح). يبدو أنه يستدعي الإشارة باستخدام SIGALRM الموثقة في Python Signal لعدم العمل على Windows. أحتاج إلى هذا للعمل في كل من بيئات نظام التشغيل Unix و Windows ، وكذلك في Python 2.7 و 3.3+ (يشبه إلى حد كبير الطلبات نفسها). سوف أتحرك أكثر قليلاً وأرى ما إذا كان هذا سيعمل بالفعل في ضوء ذلك.

@ emgerner-msft هذا محبط. = (

Lukasa Yup ، جرب مقتطف الاستخدام الأساسي ولا يعمل على Windows. لقد قرأت المزيد من التعليمات البرمجية / الأمثلة وتم العبث بها ويبدو أنه إذا لم نستخدم إشارات ، فقد تعمل الحزمة ، ولكن يجب أن يكون كل شيء قابلاً للاختيار وهذا ليس هو الحال بالنسبة لطلبي. وبقدر ما أستطيع أن أقول ، فإن timeout decorator لن يحل مشكلتي. أي أفكار أخرى؟

@ emgerner-msft هل أنت واثق من عدم ملاءمة أي من الإشارات الخاصة بـ Windows؟

Lukasa لأكون صريحا ، أنا ببساطة لا أعرف. لم أستخدم الإشارات من قبل ، ومثلما لم أكن أدرك حتى أخبرتني أنهم قاطعوا الطلب ، لست متأكدًا مما هو مناسب. أنا أيضًا لا أحاول جعل هذا يعمل فقط على Windows. أحتاج إلى دعم شامل لـ crossplat (Windows و Unix) ودعم كل من Python 2 و Python 3. الكثير من الإشارات تبدو خاصة بالمنصة إنها ترمي إلي. كان Timer أحد الحلول التي كنت أبحث عنها والتي بدت أقل انخفاضًا وبالتالي قد تعتني بالقيود الخاصة بي ، لكنني لست متأكدًا من كيفية إغلاق الاتصال. يمكنني قراءة المزيد ، ولكن هذا هو السبب في أنني كنت آمل في الحصول على إرشادات إضافية منكم يا رفاق. :)

لذلك هذا مكان صعب حقًا ليكون فيه.

الحقيقة هي أنه لا توجد طريقة عبر النظام الأساسي إلى حد ما لقتل الخيط إلا عن طريق مقاطعته ، وهو في الأساس ماهية الإشارة. هذا يعني ، على ما أعتقد ، أن الإشارات هي الطريق الوحيد لديك حقًا لإنجاح هذا الأمر عبر الأنظمة الأساسية. أميل إلى محاولة إجراء اختبار ping في أحد خبراء Windowsy Pythony: brettcannon ، هل لديك اقتراح جيد هنا؟

بدافع الاهتمام ، هل هناك سبب لعدم تنفيذ "إجمالي المهلة" في الطلبات بخلاف ذلك التنفيذ والاختبار الذي يتطلب عملاً؟ أعني لو ظهر اليوم تصحيح لتنفيذه بطريقة سحرية هل سيتم رفضه نظرياً أم قبوله؟ أقدر وأوافق على وجهة نظر "إزالة التعقيد غير الضروري" ، ولكن "يمكنك القيام بذلك عن طريق إجراء عملية منفصلة" لا يجعل هذه الميزة غير ضرورية في رأيي.

jribbens هناك بعض المشاكل مع هذا.

الجزء الأول هو أن درجة تعقيد مثل هذه الرقعة عالية جدًا. لجعله يتصرف بشكل صحيح ، تحتاج إلى تغيير المهلات بشكل متكرر على مستوى المقبس. هذا يعني أن التصحيح يحتاج إلى أن يتم تمريره على نطاق واسع من خلال برنامج الموقع الإلكتروني ، والذي قمنا بتصحيحه بالفعل أكثر مما نرغب في ذلك. بشكل أساسي ، سنحتاج إلى الوصول إلى HTplib وإعادة تنفيذ حوالي 50٪ من أساليبها الأكثر تعقيدًا من أجل تحقيق هذا التغيير الوظيفي.

الجزء الثاني هو أن الحفاظ على مثل هذا التصحيح مرهق نسبيًا. سنحتاج على الأرجح إلى البدء في الحفاظ على ما يرقى إلى مستوى متفرع متوازي من الموقع (http.client بشكل أكثر ملاءمة في هذا الوقت) من أجل القيام بذلك بنجاح. بدلاً من ذلك ، سنحتاج إلى تحمل عبء الصيانة الخاص بمكدس HTTP مختلف يكون أكثر قابلية لهذا النوع من التغيير. هذا الجزء ، كما أظن ، غالبًا ما يفتقده أولئك الذين يرغبون في الحصول على مثل هذه الميزة: تكلفة تنفيذه مرتفعة ، لكن هذا _ لا شيء _ مقارنة بتكاليف الصيانة المستمرة لدعم مثل هذه الميزة على جميع الأنظمة الأساسية.

الجزء 3 هو أن ميزة هذا التصحيح غير واضحة. لقد كانت تجربتي أن معظم الأشخاص الذين يريدون تصحيح مهلة كاملة لا يفكرون بوضوح تام فيما يريدون. في معظم الحالات ، ينتهي المطاف بمعلمات المهلة الإجمالية بالتأثير في قتل الطلبات الجيدة تمامًا دون سبب.

على سبيل المثال ، لنفترض أنك صممت قليلاً من التعليمات البرمجية لتنزيل الملفات ، وترغب في التعامل مع حالات التعليق. في حين أنه من المغري في البداية تحديد مهلة إجمالية ثابتة ("قد لا يستغرق أي طلب أكثر من 30 ثانية!") ، فإن مثل هذه المهلة تفوت النقطة. على سبيل المثال ، إذا تغير حجم الملف من 30 ميغابايت إلى 30 غيغابايت ، فلا يمكن تنزيل مثل هذا الملف أبدًا في هذا النوع من الفاصل الزمني ، على الرغم من أن التنزيل قد يكون سليمًا تمامًا.

بعبارة أخرى ، تعد المهلات الإجمالية مصدر إزعاج جذاب: يبدو أنها تحل مشكلة ، لكنها لا تفعل ذلك بشكل فعال. هناك نهج أكثر فائدة ، في رأيي ، هو الاستفادة من مهلة الإجراء لكل مقبس ، جنبًا إلى جنب مع stream=True و iter_content ، وتخصيص مهلات لأجزاء من البيانات. بالطريقة التي يعمل بها iter_content ، سيتم إرجاع تدفق التحكم إلى الكود الخاص بك في فترة زمنية منتظمة إلى حد ما. هذا يعني أنه يمكنك تعيين مهلات على مستوى المقبس (على سبيل المثال 5 ثوانٍ) ثم iter_content على أجزاء صغيرة إلى حد ما (على سبيل المثال 1 كيلو بايت من البيانات) وكن واثقًا نسبيًا من أنه ما لم تتعرض لهجوم نشط ، فلا يوجد رفض للخدمة ممكن هنا. إذا كنت قلقًا حقًا بشأن رفض الخدمة ، فقم بتعيين مهلة مستوى المقبس لديك على مستوى أقل بكثير وحجم مجموعتك أصغر (0.5 ثانية و 512 بايت) للتأكد من أنك تتحكم بانتظام في التدفق إليك.

نتيجة كل هذا هو أنني أعتقد أن المهلات الإجمالية هي ميزة غير ملائمة في مكتبة مثل هذه. أفضل نوع من المهلة هو الذي يتم ضبطه لإتاحة وقت كافٍ للاستجابات الكبيرة للتنزيل في سلام ، وأفضل وقت يتم تقديمه من خلال المهلات على مستوى المقبس و iter_content .

ربما يمتلك zooba فكرة لأنه يعرف بالفعل كيفية عمل Windows. :)

(بشكل غير مرتبط ، أحد الأشياء المفضلة لدي هو إنشاء سلسلة من الخبراء في مشكلة GitHub.)

هاها ، أعرف بالفعل zooba و @ brettcannon. يمكنني أن أناقش معهم هنا أو داخليًا كحل لذلك ربما يساعدهم أيضًا.

@ emgerner-msft اعتقدت أنك ربما ، لكني لم أرغب في الافتراض: MSFT هي منظمة كبيرة!

Lukasa مجرد قراءة من خلال جدار النص الذي كتبته للتو - ممتع! في مناقشة الدفق = True و iter_content للتنزيلات الزمنية ، ما هي الطريقة المكافئة للتعامل مع التحميلات الكبيرة؟

_PS_: الفقرة أعلاه التي تبدأ بعبارة "بعبارة أخرى ، .." هي نوع من الإرشادات التي بحثت عنها في المستندات. نظرًا لعدد الطلبات التي تحصل عليها لأقصى مهلة (والأسباب الصحيحة لعدم القيام بذلك) ، فربما يكون أفضل شيء تفعله هو إضافة بعض هذه المعلومات في مستندات المهلة ؟

لول lukasa أنا آخذ وجهة نظرك حول الصيانة ، والتي كانت بالفعل في ذهني ، ولكن في "الميزة مقابل الخطأ" أخشى أنني أعارضك تمامًا. أعتقد أن أي شخص _ لا يرغب_ في مهلة كاملة لا يفكر بوضوح بشأن ما يريده ، وأواجه صعوبة في تخيل موقف يكون فيه ما تصفه بأنه خطأ "يتغير تنزيل 30 ميغابايت إلى 30 غيغابايت وبالتالي يفشل" في الواقع ميزة مفيدة!

يمكنك كما تقول أن تفعل شيئًا مشابهًا إلى حد ما (لكنني أظن أنه بدون معظم فوائد إجمالي المهلة) باستخدام stream=True لكنني اعتقدت أن الهدف من الطلبات هو أنها تعاملت مع الأشياء نيابة عنك ...

اعتقدت أن الهدف من الطلبات هو أنها تعاملت مع الأشياء نيابة عنك

يتعامل مع HTTP نيابة عنك. تعتبر الحقائق التي نتعامل معها بالفعل مع الاتصال وقراءة المهلات وأننا حصلنا على استثناءين لتجميد الميزات لعدة سنوات عرضية لمناقشة المنفعة والاستحسان والاتساق (عبر منصات متعددة) وقابلية الصيانة. نحن نقدر ملاحظاتك ورأيك. إذا كانت لديك معلومات جديدة تريد تقديمها ، فنحن نقدر ذلك.

قد يكون من الواضح أيضًا أن الطلبات لا تتعامل مع كل شيء ، من خلال عدد طلبات الميزات المرفوضة في هذا المشروع وحقيقة أن هناك مشروعًا منفصلاً ينفذ أنماط الاستخدام الشائعة للمستخدمين (حزام أدوات الطلبات). إذا كانت المهلة الإجمالية تنتمي إلى أي مكان ، فستكون موجودة ، ولكن مرة أخرى ، يجب أن تعمل على أنظمة Windows و BSD و Linux و OSX مع تغطية اختبار ممتازة وبدون أن تكون كابوسًا للمحافظة عليه.

في مناقشة الدفق = True و iter_content للتنزيلات الزمنية ، ما هي الطريقة المكافئة للتعامل مع التحميلات الكبيرة؟

حدد منشئًا للتحميل الخاص بك ، وقم بتمريره إلى data . أو ، إذا لم يكن الترميز المقسم هو الفائز بالنسبة لك ، فحدد كائنًا يشبه الملف باستخدام طريقة read السحرية وقم بتمرير _that_ إلى data .

اسمحوا لي أن أتوسع قليلا. إذا قمت بتمرير مولد إلى data ، فستتكرر الطلبات فوقه ، وسوف ترسل كل جزء بدوره. هذا يعني أنه لإرسال البيانات ، سيتعين علينا بالضرورة تسليم تدفق التحكم إلى التعليمات البرمجية الخاصة بك لكل جزء. يتيح لك ذلك القيام بكل ما تريد في ذلك الوقت ، بما في ذلك استثناءات الرمي لإلغاء الطلب تمامًا.

إذا لم تتمكن لسبب ما من استخدام ترميز النقل المقسم لعمليات التحميل الخاصة بك (غير مرجح ، ولكن ممكن إذا كان الخادم المعني سيئًا حقًا) ، فيمكنك فعل الشيء نفسه عن طريق إنشاء كائن يشبه الملف بطول ثم إجراء السحر في المكالمة read ، والتي سيتم استدعاؤها مرارًا وتكرارًا لقطع 8192 بايت. مرة أخرى ، يضمن هذا أن تدفق التحكم يمر عبر شفرتك بشكل متقطع ، مما يتيح لك استخدام منطقك الخاص.

ملاحظة: الفقرة أعلاه التي تبدأ بعبارة "بعبارة أخرى ، .." هي نوع التوجيه الذي بحثت عنه في المستندات. نظرًا لعدد الطلبات التي تحصل عليها لأقصى مهلة (والأسباب الصحيحة لعدم القيام بذلك) ، فربما يكون أفضل شيء تفعله هو إضافة بعض هذه المعلومات في مستندات المهلة؟

أقترح - أرى - أحبذ_. بشكل عام ، على الرغم من ذلك ، فأنا دائمًا متوتر بشأن وضع نص دفاعي إلى حد ما في الوثائق. أعتقد أنه يمكن أن يدخل في الأسئلة الشائعة ، ولكن النص الذي يشرح لماذا لا نمتلك شيئًا نادرًا ما يكون مفيدًا في التوثيق. أظن أنه من الأفضل تقديم المساحة في المستندات عن طريق وصفة لعمل شيء ما.

أعتقد أن أي شخص لا يريد مهلة كاملة لا يفكر بوضوح بشأن ما يريده ، وأواجه صعوبة في تخيل موقف يكون فيه ما تصفه بأنه خطأ "يتغير تنزيل 30 ميغابايت إلى 30 غيغابايت وبالتالي يفشل" في الواقع ميزة مفيدة!

هيه ، أنا لست:

  • مدير الحزم (على سبيل المثال ، النقطة ، التي تستخدم الطلبات) ، حيث يمكن أن تختلف الحزم بشكل كبير في حجم البيانات
  • مكشطة الويب ، والتي قد تعمل مع مواقع متعددة تختلف بشكل كبير في الحجم
  • مُجمّع السجلات الذي يقوم بتنزيل ملفات السجل من المضيفين الذين لديهم مستويات مختلفة جدًا منا (وبالتالي أحجام ملفات السجل)
  • أداة تنزيل الفيديو (يمكن أن تختلف أحجام مقاطع الفيديو بشكل كبير)

في الواقع ، أعتقد أن الحالة التي يعرفها المطور في نطاق واحد من حيث الحجم ما هي أحجام الملفات التي سيتعاملون معها هي الحالة غير الشائعة. في معظم الحالات ليس لدى المطورين أي فكرة. وعمومًا ، أود أن أقول إن وضع افتراضات حول هذه الأحجام أمر غير حكيم. إذا كانت لديك قيود على حجم التنزيل ، فيجب أن تقوم الكود الخاص بك بترميز هذه الافتراضات عن عمد (على سبيل المثال في شكل فحوصات على طول المحتوى) ، بدلاً من تشفيرها ضمنيًا ودمجها مع عرض النطاق الترددي لشبكة المستخدم حتى يتمكن الأشخاص الآخرون من قراءة رمز يمكن رؤيتها بوضوح.

لكنني اعتقدت أن الهدف من الطلبات هو أنها تعاملت مع الأشياء من أجلك ...

الطلبات عمدًا جدًا لا تتعامل مع كل شيء للمستخدمين. محاولة القيام بكل شيء مهمة مستحيلة ، ومن المستحيل بناء مكتبة جيدة تقوم بذلك. نطلب من المستخدمين بانتظام أن ينزلوا إلى urllib3 من أجل تحقيق شيء ما.

نضع التعليمات البرمجية في الطلبات فقط إذا كان بإمكاننا القيام بذلك بشكل أفضل أو أنظف مما يستطيع معظم المستخدمين القيام به. إذا لم يكن كذلك ، فليس هناك قيمة. لم أقم بعد ببيع إجمالي المهلة كواحدة من تلك الأشياء ، لا سيما بالنظر إلى ما أعتبره فائدة هامشية نسبيًا عند تجميعها عبر قاعدة مستخدمينا.

بعد قولي هذا ، أنا منفتح على الاقتناع بأنني مخطئ: لم أر حجة مقنعة حتى الآن (ولإبعادك عند التمريرة ، فإن عبارة "أنا في حاجة إليها!" ليست حجة مقنعة: يجب إعطاء بعض الأسباب!).

@ sigmavirus24

إذا كانت المهلة الإجمالية تنتمي إلى أي مكان ، فستكون موجودة ، ولكن مرة أخرى ، يجب أن تعمل على أنظمة Windows و BSD و Linux و OSX مع تغطية اختبار ممتازة وبدون أن تكون كابوسًا للمحافظة عليه.

متفق!

lukasa أفترض أن تفكيري هو أنني لا أريده فقط ، بل في الواقع يريده جميع المستخدمين تقريبًا إذا فكروا فيه (أو لم يدركوا أنه ليس موجودًا بالفعل). نصف سيناريوهات الاستخدام أعلاه حيث تقول أنه يجب تجنبها ، أود أن أقول إنها ضرورية (مكشطة الويب ومجمع السجلات) - وهما الآخران أقل أهمية حيث من المحتمل أن يكون هناك مستخدم ينتظر النتيجة ويمكنه إلغاء التنزيل يدويًا إذا هم يريدون. أي شيء يتم تشغيله في الخلفية بدون واجهة مستخدم ولا يستخدم مهلة عامة هو عربات التي تجرها الدواب من وجهة نظري!

أفترض أن تفكيري هو أنني لا أريد ذلك فحسب ، بل في الواقع يريده جميع المستخدمين تقريبًا إذا فكروا فيه (أو لم يدركوا أنه ليس موجودًا بالفعل).

jribbens لدينا عدة سنوات (أكثر من عقد إذا جمعت خبرات الثلاثة منا) للتحدث مع مستخدمينا وفهم احتياجاتهم. ما كان ضروريًا تقريبًا لجميع المستخدمين (98٪ على الأقل) هو مهلة الاتصال والقراءة. نحن نتفهم أن أقلية صاخبة جدًا من مستخدمينا يريدون مهلة عامة. بالنظر إلى ما يمكننا استقراءه ليكون حجم مجموعة المستخدمين المحتملين لهذه الميزة مقابل الحجم المحتمل للمستخدمين الذين لا يحتاجون إلى هذه الميزة وتعقيد صيانة الميزة وتطويرها ، فهذا ليس شيئًا نذهب إليه حقًا لكى يفعل.

إذا كان لديك أي شيء _ جديد_ تريد مشاركته ، فنحن نرغب في سماع ذلك ، ولكن كل ما قلته حتى الآن هو أنه في رأيك ، فإن أي شيء يستخدم الطلبات بدون مهلة عامة هو عربات التي تجرها الدواب ويمكنني أن أتخيل أن هناك الكثير من المستخدمين الذين قد يسيء إلى تأكيدك أن قرارات التصميم الخاصة بهم هي أخطاء عربات التي تجرها الدواب. لذا ، يرجى الامتناع عن إهانة ذكاء مستخدمينا.

@ sigmavirus24 طوال هذا الموضوع ، كنت تتنازل دون داع ، ملتهب ووقح ، وأنا أسألك بأدب ، من فضلك توقف.

Lukasa لقد بحثت بالتفصيل في اقتراحاتك حول كيفية تحميل وتنزيل البث وقراءة المستندات الخاصة بهذه الموضوعات. إذا كان بإمكانك التحقق من صحة افتراضاتي / أسئلتي ، فسيكون ذلك رائعًا.

  1. بالنسبة إلى عمليات التنزيل المتدفقة ، إذا كنت أستخدم شيئًا مثل مهلة القراءة '(على سبيل المثال 5 ثوانٍ) ثم iter_content على أجزاء صغيرة إلى حد ما (على سبيل المثال 1 كيلوبايت من البيانات) ، فهذا يعني أن مكتبة الطلبات ستطبق مهلة 5 ثوانٍ لكل قراءة 1 كيلوبايت والمهلة إذا كانت يستغرق أكثر من 5 ثوان. صيح؟
  2. بالنسبة إلى التحميلات المتدفقة إذا كنت أستخدم منشئًا أو ملفًا مثل الكائن الذي يعيد أجزاء من البيانات وقمت بتعيين مهلة القراءة على 5 ثوانٍ ، ستطبق مكتبة الطلب مهلة 5 ثوانٍ لكل جزء أعود إليه وانتهاء المهلة إذا استغرق الأمر وقتًا أطول. صيح؟
  3. إذا لم أستخدم منشئًا للتحميل وقمت بتمرير البايتات مباشرة ، كيف تقرر مكتبة الطلبات تطبيق مهلة القراءة التي قمت بتعيينها؟ على سبيل المثال ، إذا مررت بقطعة بحجم 4 ميغا بايت ومهلة قراءة 5 ثوانٍ ، فمتى يتم تطبيق مهلة القراءة بالضبط؟
  4. إذا لم أستخدم iter_content وكان لدي طلبات لتنزيل كل المحتوى مباشرةً في الطلب مع مهلة قراءة 5 ثوانٍ ، فمتى يتم تطبيق مهلة القراءة هذه بالضبط؟

لدي فهم عام للمآخذ / بروتوكول TCP / وما إلى ذلك ولكن ليس بالضبط كيف يعمل urllib مع هذه المفاهيم على مستوى أدنى أو إذا كانت الطلبات تفعل أي شيء خاص إلى جانب تمرير القيم إلى أسفل. أريد أن أفهم بالضبط كيف يتم تطبيق المهلات لأن مجرد استعادة تدفق التحكم وتطبيق مخطط المهلة الخاص بي لا يعمل في ضوء مشكلات Crossplat مع إنهاء سلسلة الرسائل. إذا كانت هناك مواد قراءة إضافية للإجابة على أسئلتي ، فلا تتردد في إحالتي! على أي حال ، آمل أن تكون هذه آخر مجموعة من أسئلتي. :)

شكرا لمساعدتك حتى الآن.

@ emgerner-msft طيب:

  1. لا. إنه أكثر تعقيدًا من ذلك ، للأسف. كما تمت مناقشته ، تنطبق كل مهلة على مكالمة مأخذ التوصيل ، لكن لا يمكننا ضمان عدد مكالمات المقبس في قطعة معينة. والسبب المعقد جدًا لذلك هو أن المكتبة القياسية تقوم بتغليف مأخذ التوصيل في كائن المخزن المؤقت (عادةً ما يكون شيئًا مثل io.BufferedReader ). سيؤدي ذلك إلى إجراء العديد من مكالمات recv_into التي يجب إجراؤها حتى توفر بيانات كافية. قد يكون هذا أقل من الصفر (إذا كان هناك ما يكفي من البيانات في المخزن المؤقت بالفعل) أو أكبر عدد من البايتات التي تلقيتها بالضبط إذا كان النظير البعيد يغذيك بالتنقيط بايت واحد في كل مرة. هناك القليل جدًا مما يمكننا فعله حيال ذلك: نظرًا لطبيعة استدعاء read() ضد مثل هذا الكائن المخزن مؤقتًا ، فإننا لا نحصل حتى على تدفق التحكم مرة أخرى بين كل مكالمة recv_into .

هذا يعني أن الطريقة _only_ لضمان عدم حصولك على أكثر من n ثانية من الانتظار هي القيام بـ iter_content بحجم قطعة 1 . هذه طريقة غير فعالة بشكل سخيف لتنزيل ملف (تقضي الكثير من الوقت في كود Python) ، لكنها الطريقة الوحيدة للحصول على الضمان الذي تريده.

  1. أعتقد أيضًا أن الإجابة على ذلك هي لا. ليس لدينا حاليًا فكرة عن انتهاء مهلة الإرسال. طريقة الحصول على واحدة هي استخدام socket.setdefaulttimeout .
  2. يتم تطبيق مهلة القراءة على القراءات فقط ، لذلك لا يهم كيفية تمرير الجسم.
  3. تعاني مهلة القراءة هذه من نفس مخاوف حالة iter_content : إذا كان لديك طلبات لتنزيل كل شيء ، فسننتهي بإصدار العديد من المكالمات recv_into حسب الحاجة لتنزيل الجسم ، وتنطبق المهلة لكل واحد بدوره.

أنت تصطدم بالمشكلة الأساسية هنا: الطلبات لا تقترب بما يكفي من المقبس لتحقيق ما تبحث عنه بالضبط. يمكننا _could_ إضافة مهلة إرسال: هذا طلب ميزة يتم النظر فيه ، ولا يعاني من نفس المشكلات التي تعاني منها مهلة القراءة ، ولكن بالنسبة لكل شيء آخر ، فإننا عالقون لأن httplib يصر (بحق) على التبديل إلى تمثيل مأخذ توصيل مؤقت ، ثم يستخدم باقي httplib هذا التمثيل المخزن مؤقتًا.

تضمين التغريدة

آه ، يا لها من فوضى ، هاها. اعتقدت أن هذا قد يكون هو الحال ولكني كنت آمل حقًا أن أكون مخطئًا.

أولاً ، نحن بحاجة ماسة إلى مهلة الإرسال. لا يمكنني ببساطة إخبار المستخدمين أن تحميلاتهم يمكن أن تتوقف بلا حدود وليس لدينا خطة لإصلاح المشكلة. : /

يبدو أنني في وضع مستحيل نوعًا ما في هذه المرحلة. لا يوجد دعم مكتبة لإجمالي المهلة (وهو ما أفهمه بالفعل). لا توجد ضمانات حول كيفية عمل المهلة الحالية بالضبط مع أحجام مجموعات مختلفة - إذا كان هناك ، يمكنني فقط تلخيص الوقت: مهلة الاتصال + مهلة القراءة * حجم القطعة. إن القدرة على مقاطعة التدفق باستخدام وضع الدفق والمولدات أمر رائع ، ولكن نظرًا لعدم وجود حل لإجهاض الخيوط فعليًا بطريقة عبر النظام الأساسي ، فإن هذا لا يساعد أيضًا. هل ترى خيارات أخرى للمضي قدمًا؟ ماذا يفعل المستخدمون الآخرون لحل هذه المشكلات؟

أولاً ، نحن بحاجة ماسة إلى مهلة الإرسال. لا يمكنني ببساطة إخبار المستخدمين أن تحميلاتهم يمكن أن تتوقف بلا حدود وليس لدينا خطة لإصلاح المشكلة. : /

لذا فإن منطق المهلة المستخدم في الطلبات هو في الأساس منطق urllib3 ، لذلك يجب أن يكون كافيًا لإجراء التغيير هناك: لا تتردد في فتح طلب ميزة ويمكننا مساعدتك خلال التغيير. وعلى المدى الأقصر ، لا تتردد في التحقيق باستخدام setdefaulttimeout .

هل ترى خيارات أخرى للمضي قدمًا؟ ماذا يفعل المستخدمون الآخرون لحل هذه المشكلات؟

الخيارات المتاحة أمامك هنا تعتمد على قيودك المحددة.

إذا كان يجب أن يكون لديك مهلة محددة (أي ، إذا كان يجب أن يكون من الممكن ضمان أن الطلب لن يستغرق أكثر من _n_ ثانية) ، فلا يمكنك القيام بذلك بسهولة باستخدام مكتبة Python القياسية كما هي موجودة اليوم. في Python 2.7 ، ستحتاج إلى تصحيح socket._fileobject للسماح لك بتشغيل مهلة متسلسلة لكل recv مكالمة ، لكن في Python 3 يكون الأمر أكثر صعوبة لأنك تحتاج إلى التصحيح في فصل يتم تنفيذه في C ( io.BufferedReader ) ، والذي سيكون كابوسًا.

خلاف ذلك ، فإن الطريقة الوحيدة للحصول عليها هي إيقاف التخزين المؤقت في المكتبة القياسية. سيؤدي ذلك إلى كسر HTplib وجميع التصحيحات الموجودة فوقه ، والتي تفترض أنه يمكننا إجراء مكالمة read(x) لن تتصرف مثل read syscall على المقبس ولكن بدلاً من ذلك مثل read syscall على ملف (أي إرجاع طول محدد).

بعبارة أخرى: إذا كنت بحاجة إلى مهلة حتمية ، فستجد أن عددًا كبيرًا من المكتبات غير قادر ببساطة على توفيرها لك. بشكل أساسي ، إذا استخدموا httplib أو socket.makefile ، فستكون محظوظًا: لا توجد طريقة نظيفة لضمان عودة التحكم إليك في وقت محدد باستثناء طول الإصدار المتكرر -1 يقرأ. يمكنك فعل ذلك ، لكنه سيضر بأدائك.

إذن لديك مقايضة هنا: إذا كنت تريد مهلة حتمية ، فإن الطريقة التي يتم بها تنفيذ التخزين المؤقت في مكتبة Python القياسية (وهكذا ، في الطلبات) لن تجعل ذلك متاحًا لك. يمكنك استعادة ذلك من خلال تعطيل التخزين المؤقت وإعادة كتابة الكود ، ولكن هذا قد يضر بأدائك بشكل سيئ للغاية ما لم تعيد تنفيذ التخزين المؤقت بطريقة تتعرف على المهلات.

يمكنك أن تهدف إلى تنفيذ الكود المطلوب في مكتبة Python القياسية في فئة BufferedReader : يمكنك بالتأكيد أن تسأل أفراد Python عما إذا كانوا مهتمين. لكنني لم أكن لأحبس أنفاسي.

لذا فإن منطق المهلة المستخدم في الطلبات هو في الأساس منطق urllib3 ، لذلك يجب أن يكون كافيًا لإجراء التغيير هناك: لا تتردد في فتح طلب ميزة ويمكننا مساعدتك خلال التغيير. وعلى المدى الأقصر ، لا تتردد في التحقيق باستخدام setdefaulttimeout.

طلب ميزة في urllib3 أو هنا؟ سيتم فتح واحد (أو كليهما) في أسرع وقت ممكن.

طلب الميزة في urllib3: لسنا بحاجة إلى كشف أي شيء جديد في الطلبات.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات