Flask.g का प्रयोग कब किया जाना चाहिए?


173

मैंने देखा कि gफ्लास्क 0.10 में एप्लिकेशन के संदर्भ में अनुरोध के संदर्भ से हट जाएगा, जिसने मुझे इसके उपयोग के बारे में भ्रमित कर दिया g

मेरी समझ (फ्लास्क 0.9 के लिए) यह है:

  • g अनुरोध के संदर्भ में, अर्थात, अनुरोध शुरू होने पर नए सिरे से बनाया गया है, और जब तक यह समाप्त नहीं होता है तब तक उपलब्ध है
  • g एक "अनुरोध ब्लैकबोर्ड" के रूप में उपयोग करने का इरादा है, जहां मैं अनुरोध की अवधि के लिए प्रासंगिक सामग्री रख सकता हूं (यानी, अनुरोध की शुरुआत में एक ध्वज सेट करें और इसे अंत में संभाल लें, संभवतः एक से before_request / after_requestजोड़ी से)
  • अनुरोध-स्तर-राज्य रखने के अलावा, g संसाधन प्रबंधन के लिए इस्तेमाल किया जा सकता है और इसका मतलब है, डेटाबेस कनेक्शनों को रखना आदि।

फ्लास्क 0.10 में इनमें से कौन सा वाक्य अब सही नहीं है? क्या कोई मुझे बदलाव के कारणों पर चर्चा करने वाले संसाधन की ओर इशारा कर सकता है ? फ्लास्क 0.10 में मुझे "अनुरोध ब्लैकबोर्ड" के रूप में क्या उपयोग करना चाहिए - क्या मुझे अपना ऐप / एक्सटेंशन विशिष्ट थ्रेड-स्थानीय प्रॉक्सी बनाना चाहिए और इसे संदर्भ स्टैक पर धकेलना चाहिए before_request? आवेदन के संदर्भ में संसाधन प्रबंधन का क्या मतलब है, अगर मेरा आवेदन लंबे समय तक रहता है (अनुरोध की तरह नहीं) और इस तरह संसाधनों को कभी मुक्त नहीं किया जाता है?


मैं सहमत हूं, यह एक बहुत ही अजीब बदलाव है। उम्मीद है कि mitsuhiko g0.10 में बदलने के लिए किसी प्रकार के अनुरोध संदर्भ वस्तु को लागू करता है , अन्यथा ऐसा लगता है कि बहुत सारे कोड कुछ कुटिल कीड़े विकसित करना शुरू कर सकते हैं।
औरोव

11
एफडब्ल्यूआईडब्ल्यू, अर्मिन रोनचेर (फ्लास्क के लेखक) ने "एडवांस्ड फ्लास्क पैटर्न" का सीक्वल जारी किया है, जो नए का उपयोग करने के बारे में कुछ उदाहरण कोड दिखाता है flask.gस्पीकरडेक.com
मार्कस अनटवाडित्जर

1
एक नया अनुरोध संदर्भ भी एक नया ऐप संदर्भ देता है, इसलिए इसे सामान्य उपयोग में ठीक काम करना चाहिए
Ronny

जवाबों:


119

उन्नत फ्लास्क पैटर्न , जैसा कि मार्कस द्वारा जोड़ा गया है , g0.10 में कुछ बदलाव बताते हैं :

  • g अब आवेदन के संदर्भ में रहता है।
  • हर अनुरोध एक नया अनुप्रयोग संदर्भ देता है , पुराने को मिटा देता है, इसलिएg अभी भी कोड में बदलाव के बिना प्रति-अनुरोध झंडे सेट करने के लिए उपयोग किया जा सकता है।
  • अनुप्रयोग संदर्भ पॉपअप के बाद teardown_request कहा जाता है। (आर्मिन की प्रस्तुति बताते हैं इस वजह से डीबी कनेक्शन बनाने जैसी चीजों के कार्यों के लिए जो कर रहे हैं सेटअप अनुरोध के लिए पर्यावरण, और अंदर से संभाला नहीं किया जाना चाहिए before_requestऔर after_request)

आपके द्वारा लिंक किए गए स्रोत कोड में, जब app_ctx is None or app_ctx.app != self.appगलत है, तो पुराने एप्लिकेशन संदर्भ का पुन: उपयोग किया जा रहा है? यह सही प्रतीत नहीं होता, क्योंकि अनुप्रयोग संदर्भ "अनुरोधों के बीच साझा नहीं किया जाएगा" ...
nalzok

2
क्या आप धक्का देने कीapp.app_context() बात कर रहे हैं ? यदि ऐसा है, तो यह ध्यान दिया जाना चाहिए कि app_context()हर कॉल पर एक नया एप्लिकेशन संदर्भ तुरंत दिया जाए - यह कभी भी संदर्भ का पुन: उपयोग नहीं करता है।
theY4Kman

1
हां यह सच है, लेकिन जब app_ctx is not None and app_ctx.app == self.app, app_ctx = self.app.app_context()लाइन निष्पादित नहीं होती है ; केवल self._implicit_app_ctx_stack.append(None)इस मामले में निष्पादित किया जाता है।
नलज़ोक

1
ओह, माफ करना, मैं गलत! उत्पादन सेटिंग में, प्रति थ्रेड (या ग्रीनलेट) में केवल एक ही अनुरोध है। केवल एक RequestContextको धक्का दिया जाता है, इसलिए केवल एक AppContextको धक्का दिया जाता है। लेकिन अगर डिबग मोड चालू है और एक अनुरोध विफल हो जाता है, तो फ्लास्क संदर्भ को बचाता है , इसलिए इसका उपयोग डीबगर के साथ किया जा सकता हैNoneसे जोड़ा जाता है _app_ctx_stack, इसलिए जब अनुरोध को फाड़ा जा रहा है, तो यह AppContextअभी तक पॉप नहीं करना जानता है। परीक्षण क्लाइंट के साथ एक ही बात होती है, जो संदर्भ को बनाए रखता है, इसलिए इसका निरीक्षण किया जा सकता है।
theY4Kman

इसलिए जी का दायरा अनुरोध (धागा) के अनुसार है और यह बाद के अनुरोध में मूल्य को बरकरार नहीं रखेगा।
चर

83

इस सूत्र में जानकारी के लिए एक परिशिष्ट के रूप में: मैं flask.gभी व्यवहार से थोड़ा भ्रमित हो गया हूं , लेकिन कुछ त्वरित परीक्षण ने मुझे इसे स्पष्ट करने में मदद की है। यहाँ मैंने क्या आज़माया है:

from flask import Flask, g
app = Flask(__name__)

with app.app_context():
    print('in app context, before first request context')
    print('setting g.foo to abc')
    g.foo = 'abc'
    print('g.foo should be abc, is: {0}'.format(g.foo))

    with app.test_request_context():
        print('in first request context')
        print('g.foo should be abc, is: {0}'.format(g.foo))
        print('setting g.foo to xyz')
        g.foo = 'xyz'
        print('g.foo should be xyz, is: {0}'.format(g.foo))

    print('in app context, after first request context')
    print('g.foo should be abc, is: {0}'.format(g.foo))

    with app.test_request_context():
        print('in second request context')
        print('g.foo should be abc, is: {0}'.format(g.foo))
        print('setting g.foo to pqr')
        g.foo = 'pqr'
        print('g.foo should be pqr, is: {0}'.format(g.foo))

    print('in app context, after second request context')
    print('g.foo should be abc, is: {0}'.format(g.foo))

और यहाँ उत्पादन है कि यह देता है:

in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc  

in first request context
g.foo should be abc, is: abc
setting g.foo to xyz
g.foo should be xyz, is: xyz  

in app context, after first request context
g.foo should be abc, is: xyz  

in second request context
g.foo should be abc, is: xyz
setting g.foo to pqr
g.foo should be pqr, is: pqr  

in app context, after second request context
g.foo should be abc, is: pqr

जैसा कि theY4Kman ने ऊपर कहा है, "प्रत्येक अनुरोध एक नया अनुप्रयोग संदर्भ धक्का देता है"। और जैसा कि फ्लास्क डॉक्स कहते हैं , आवेदन का संदर्भ "अनुरोधों के बीच साझा नहीं किया जाएगा"। अब, जो स्पष्ट रूप से नहीं कहा गया है (हालांकि मुझे लगता है कि यह इन कथनों से निहित है), और मेरे परीक्षण से स्पष्ट रूप से पता चलता है, यह है कि आपको कभी भी एक आवेदन के संदर्भ में निहित कई अनुरोध संदर्भों को स्पष्ट रूप से नहीं बनाना चाहिए , क्योंकिflask.g (और सह) doesn ' t का कोई जादू है जिससे यह संदर्भ के दो अलग-अलग "स्तरों" में काम करता है, अलग-अलग राज्यों में स्वतंत्र रूप से आवेदन और अनुरोध के स्तर पर मौजूद है।

क्योंकि वास्तविकता है कि "आवेदन संदर्भ" संभावित काफी भ्रामक नाम है app.app_context() है एक प्रति-अनुरोध संदर्भ , के रूप में बिल्कुल वैसा ही "अनुरोध संदर्भ" । इसे एक "अनुरोध संदर्भ लाइट" के रूप में सोचें, केवल उस मामले में आवश्यक है जहां आपको कुछ ऐसे चर की आवश्यकता होती है जो सामान्य रूप से अनुरोध के संदर्भ की आवश्यकता होती है, लेकिन आपको किसी भी अनुरोध ऑब्जेक्ट तक पहुंचने की आवश्यकता नहीं है (जैसे जब बैच डीबी संचालन चल रहा है शेल स्क्रिप्ट)। यदि आप एक से अधिक अनुरोध संदर्भ को शामिल करने के लिए आवेदन संदर्भ का प्रयास करते हैं और बढ़ाते हैं, तो आप परेशानी पूछ रहे हैं। इसलिए, मेरे परीक्षण के बजाय, आपको फ्लास्क के संदर्भों के साथ इस तरह कोड लिखना चाहिए:

from flask import Flask, g
app = Flask(__name__)

with app.app_context():
    print('in app context, before first request context')
    print('setting g.foo to abc')
    g.foo = 'abc'
    print('g.foo should be abc, is: {0}'.format(g.foo))

with app.test_request_context():
    print('in first request context')
    print('g.foo should be None, is: {0}'.format(g.get('foo')))
    print('setting g.foo to xyz')
    g.foo = 'xyz'
    print('g.foo should be xyz, is: {0}'.format(g.foo))

with app.test_request_context():
    print('in second request context')
    print('g.foo should be None, is: {0}'.format(g.get('foo')))
    print('setting g.foo to pqr')
    g.foo = 'pqr'
    print('g.foo should be pqr, is: {0}'.format(g.foo))

जो अपेक्षित परिणाम देगा:

in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc  

in first request context
g.foo should be None, is: None
setting g.foo to xyz
g.foo should be xyz, is: xyz  

in second request context
g.foo should be None, is: None
setting g.foo to pqr
g.foo should be pqr, is: pqr

7
अंतिम पैराग्राफ की वजह से अपटेड, फ्लास्क के संदर्भों को पहली बार में समझने के लिए काफी भ्रामक हैं। नाम से, आपको लगता है कि अनुरोध संदर्भ संदर्भ अनुरोध के अनुसार है और यह एप्लिकेशन संदर्भ अनुरोध के बाद भी मौजूद है या यह जीवनकाल से प्रभावित नहीं है।
सिमानियास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.