Werkzeug: هل لدى werkzeug خطط لدعم ASGI؟

تم إنشاؤها على ٧ يونيو ٢٠١٨  ·  21تعليقات  ·  مصدر: pallets/werkzeug

يقدم Werkzeug العديد من الطرق المفيدة ، وسيكون من الأسهل بكثير إذا كان يدعم ASGI مما لو بدأنا من الصفر.

ASGI

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

نعم ، سيدعم Werkzeug و Flask في النهاية ASGI. ليس لدي جدول زمني لهذا ، على الرغم من أنني سأكون سعيدًا بالمساعدة في مراجعة العلاقات العامة إذا بدأ شخص ما.

ومع ذلك ، لن أكون الشخص الذي ينفذ ذلك ، فأنا بحاجة إلى مساعدة من المجتمع. راجع آخر تحديث أدناه: https://github.com/pallets/werkzeug/issues/1322#issuecomment -600926145

ال 21 كومينتر

نعم ، سيدعم Werkzeug و Flask في النهاية ASGI. ليس لدي جدول زمني لهذا ، على الرغم من أنني سأكون سعيدًا بالمساعدة في مراجعة العلاقات العامة إذا بدأ شخص ما.

ومع ذلك ، لن أكون الشخص الذي ينفذ ذلك ، فأنا بحاجة إلى مساعدة من المجتمع. راجع آخر تحديث أدناه: https://github.com/pallets/werkzeug/issues/1322#issuecomment -600926145

أنا مهتم بالعمل على هذا.

لدي بعض دعم ASGI العامل ولكن المبتكر مستمر: werkzeug ، flask . أود أن أفهم المزيد عن أي خطط قد تكون لديك قبل المضي قدمًا.

الأشياء التي تحدث لي بالفعل ، بخلاف حقيقة أن كل ما قمت به هناك يمكن أن يكون أجمل بشكل عام:

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

أخبرني بأفكارك إذا سمحت.

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

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

دعم السياق المحلي هش للغاية.

يوجد السياق المحلي (لـ asyncio) في 3.7 stdlib. https://docs.python.org/3.7/library/contextvars.html
أعتقد أن استخدام هؤلاء ، مع مكتبة متوافقة اختيارية لدعم الإصدارات السابقة من بيثون. (أو افترض فقط أن ASGI في Flask سينتهي به الأمر إلى 3.7+ شيء)

هل تستخدم werkzeug الخيوط المحلية؟ (أنا أعلم أن Flask يفعل)

لا توجد طريقة واضحة ، عند التشغيل تحت ASGI ، لتحليل بيانات النموذج عند الطلب لوظيفة متزامنة

أقترح عدم تقديم واجهة متزامنة لتحليل بيانات النموذج. (أو للوصول إلى نص الطلب بأي طريقة) ، وبدلاً من ذلك ، قم فقط بتقديم واجهات برمجة تطبيقات غير متزامنة عليه. راجع واجهة برمجة تطبيقات Starlette للحصول على بعض الأمثلة هنا ... https://github.com/encode/starlette#body

نظرًا لأن Python 3.7 خارج ، فلن أعارض وجود ميزات غير متزامنة تتطلب Python 3.7 طالما لم يتأثر أي رمز آخر بها. ولكن إذا كان هناك منفذ خلفي جيد مثل الحل الأصلي 3.7 - فهو أفضل!

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

بالتأكيد ، أو فقط اجعل values والأصدقاء غير متزامنين: values = await request.values أو values = await request.values() ، اعتمادًا في الغالب على أيهما يبدو أجمل.

ألا يتطلب ذلك أشياء قبيحة إلى حد ما مثل (await request.form)['foo'] لإجراء مكالمة غير متزامنة أثناء الحصول على عنصر deb مباشرة دون تخصيص بينهما؟

نعم :(

لست متأكدًا من أنه يمكن تجنب ذلك بشكل خاص. لا اعتقد

form = await request.form
form['foo']

هو في الحقيقة أكثر أو أقل بشاعة من

await request.parse()
request.form['foo']

على الرغم من أنه من الواضح أن هذا يخضع للذوق.

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

بالتأكيد ، أو اجعل القيم والأصدقاء غير متزامنين بأنفسهم: القيم = انتظار الطلب. القيم أو القيم = انتظار الطلب.

أقترح استخدام استدعاءات الوظائف لعمليات الإدخال / الإخراج ، بدلاً من الخصائص.

ألا يتطلب ذلك أشياء قبيحة إلى حد ما مثل (انتظار request.form) ['foo'] لإجراء مكالمة غير متزامنة أثناء الحصول على عنصر deb مباشرة دون تخصيص بينهما؟

تتغاضى - لا تفعل ذلك.

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

form = await request.form()
form['foo']

بينما أقوم جميعًا بإضافة دعم غير متزامن ، ما زلنا لا نستطيع كسر Python 2 وإصدارات المزامنة. أحد الأساليب التي سمعت عنها من njsmith هو كتابة كل شيء على أنه غير متزامن ، ثم استخدام أداة مشابهة لـ 2to3 لإنشاء إصدار المزامنة. يبدو أنه يتم تجربته في urllib3 ، لكنني لا أعرف ما يكفي عنه.

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

أو ... request_class = AsyncRequest إذا أراد شخص ما غير متزامن ؛ قد يكون هذا في الواقع افتراضيًا في فئة AsyncFlask .

أو ... request_class = AsyncRequest إذا كان شخص ما يريد غير متزامن ؛ يمكن أن يكون هذا في الواقع افتراضيًا في فئة AsyncFlask.

هذا هو نوع النهج الذي سيكون منطقيًا بالنسبة لي ، نعم.

فيما يتعلق بالمحلل اللغوي للنموذج ، قمت بمحاولة في sansio-ing it في # 1330.

هناك أيضًا تطبيق محلل نموذج التدفق على https://github.com/andrew-d/python-multipart بتغطية 100٪. (لقد وجدت أحدهما الآخر ولكن لم يكن واضحًا أنه يمكن تكييفه بسهولة في تدفق "بيانات التغذية ، التعامل مع الأحداث".)

python-multipart هي المكتبة التي أستخدمها الآن لـ Starlette. يمكنك إلقاء نظرة على التكامل مع الدفق غير المتزامن هنا: https://github.com/encode/starlette/blob/master/starlette/formparsers.py#L207

كنت أفكر أيضًا في أفضل الطرق لتقديم واجهة متوافقة مع مزامنة وغير متزامنة ، لأنني أريد ذلك أيضًا لـ Starlette (على الرغم من الانتقال في الاتجاه الآخر إلى Werkzeug ، فإن الأمر بالنسبة لي يتعلق "لدي واجهة غير متزامنة حالية ، كيف يمكنني قدم الآن أيضًا مزامنة واحدة ")

بالنسبة إلى Starlette ، أعتقد أنني سأقوم على الأرجح بدفع التحليل الفعلي إلى طريقة async parse(self) ، وعادة ما يتم استدعاء ذلك في وقت ما أثناء إرسال الطلب ، ولكن الكشف عن الخصائص العادية العادية form ، files إلخ ... للوصول إلى النتائج من رمز المستخدم.

خارج الموضوع ، ولكنه مرتبط بقضية ASGI و werkzeug شائعة (لا أريد إخراج هذه المشكلة عن مسارها ، لكن لا أريد إنشاء مشكلة مكررة بدون إضافة مادة):

إذا كنت تقوم بتشغيل https://github.com/django-extensions/django-extensions مع ./manage.py runserver_plus و https://github.com/django/channels (التي تستخدم ASGI) تمنح Opcode -1 (كود التشغيل ناقص 1) في المفتش ، حاول تشغيل ./manage.py runserver الآن حتى يتم دعم ASGI.

(يتم استخدام Werkzeug أسفل غطاء محرك السيارة على Django مع امتدادات django وقضيت بضع ساعات في معرفة السبب لأنني معتاد جدًا على التطوير باستخدام runserver_plus للتصحيح)

أستخدم runserver_plus حتى أتمكن من استخدام https في التطوير.
أحاول الآن إضافة دعم Websockets باستخدام قنوات Django ، وقد واجهت مشكلة أن القنوات تستخدم خادم التشغيل ولا تدعم runserver_plus. لذا ، يمكنني استخدام القنوات أو يمكنني استخدام https ، وليس كليهما!

davidism من فضلك أخبرني إذا كانت هناك أي تغييرات في تنفيذ دعم ASGI لـ Flask منذ إجابتك الأخيرة في هذا الموضوع وما إذا كانت خططك قد تغيرت فيما يتعلق بهذه المهمة لإنهاء دعم Python 2؟

في 2 يوليو 2018 ، كتب davidism :

يبدو أنه يتم تجربته في urllib3 ، لكنني لا أعرف ما يكفي عنه.

لقد رأيت هذا للتو منذ فترة - إذا كان أي شخص مهتمًا بمعرفة المزيد ، فيبدو أن python-trio / urllib3 # 1 يحتوي على مجموعة من التفاصيل. لاحظ رابط urllib3 / urllib3 # 1323 ، والذي يحتوي على:

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

(استمر في القراءة هناك إذا كنت مهتمًا).

من الجيد أن نرى أن هذا استمر على ما يبدو في العمل بشكل جيد ، بناءً على التقدم المطرد الذي يتم إحرازه على https://github.com/python-trio/urllib3/commits/bleach-spike.

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

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

في هذه الأثناء ، أصبحpgjones ، مؤلف Quart ، أكثر مشاركة في Werkzeug. يستخدم Quart الآن Werkzeug وراء الكواليس حيثما أمكن ذلك ، ونحن نواصل تطوير ذلك. كان هناك بعض التراجع من مشرف Flask حول استخدام ASGI ، لذلك أنشأ Phil أيضًا منصات / قارورة # 3412 التي سمحت على الأقل بالتوجيه إلى وظائف async def ، لكن ذلك ظل موجودًا لفترة من الوقت الآن. في هذه المرحلة ، أفضل الذهاب إلى ASGI بدلاً من الاكتفاء بذلك. أنشأ @ edk0 # 1330 لإجراء تحليل للنموذج sans-io ، لكنه أيضًا كان جالسًا ، وربما يجب أن يمر ببعض التصميم والمراجعة أولاً.

قد تسأل ، "لماذا لا يستطيع Flask فعل ما فعله Django؟" أنا لست خبيرًا في الأجزاء الداخلية لـ Django ، لكن andrewgodwin أوضح لي منذ فترة أن Django لديه وقت "أسهل" (اقرأ: لا يزال معقدًا للغاية) نظرًا لكيفية تكييفه في الأصل مع WSGI ، على عكس واجهة برمجة تطبيقات تتمحور حول WSGI والتي بدأها Werkzeug و Flask. أيضًا ، يحصل Django على الكثير من الاهتمام والموارد بدوام كامل أكثر من Pallets.

إذن أين يترك ذلك هذه القضية؟ إذا كنت تريد إطار عمل متوافق مع Flask يستخدم Werkzeug ، فاستخدم Quart. ساهم في Quart (أو Flask) لجعلها أكثر توافقًا مع API حيثما كان ذلك مفقودًا. إذا كنت تريد من Werkzeug و Flask دعم ASGI ، فستحتاج إلى تصعيد الأمر. ابدأ في التعرف على ASGI. ابدأ في تحديد الأجزاء الخاصة بـ WSGI وأجزاء الحظر من واجهة برمجة تطبيقات Werkzeug. ابدأ في التفكير في الأفكار المجردة التي يمكننا إجراؤها لتمكين عمليات التنفيذ لكل من WSGI و ASGI. ثم أعد هذا البحث إلى هذه المناقشة حتى نتمكن من البدء في تصميم وكتابة العلاقات العامة.

شكرًا لاقتراح Quart ، سأكون سعيدًا جدًا لقبول المساهمات فيه.

لقد حاولت أن أجيب لماذا أعتقد أن Flask لا يمكنه فعل ما فعله Django في هذه المقالة . في النهاية ، أعتقد أن المنصات / القارورة # 3412 هي أفضل حل للقارورة.

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

خطتي هي الاستمرار في دمج Werkzeug في Quart مع تعديل Werkzeug نحو ASGI (sans-io) أثناء ذهابي (بقدر ما يمكن قبوله) - العقبة الوحيدة هي ضيق الوقت.

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

القضايا ذات الصلة

davidism picture davidism  ·  9تعليقات

androiddrew picture androiddrew  ·  14تعليقات

d42 picture d42  ·  6تعليقات

SimonSapin picture SimonSapin  ·  12تعليقات

taion picture taion  ·  7تعليقات