2013-02-26 25 views
104

I saw कि g अनुरोध संदर्भ से फ्लास्क 0.10 में ऐप संदर्भ में स्थानांतरित हो जाएगा, जिसने मुझे g के इच्छित उपयोग के बारे में भ्रमित कर दिया। अनुरोध संदर्भ मेंFlask.g का उपयोग कब किया जाना चाहिए?

  • g रहता है, यानी, बनाया नए सिरे से जब अनुरोध शुरू होता है, और जब तक यह उपलब्ध समाप्त होता है
  • g इस्तेमाल किया जा करने का इरादा है:

    मेरे समझ (बोतल 0.9 के लिए) है कि है "अनुरोध ब्लैकबोर्ड" के रूप में, जहां मैं अनुरोध की अवधि के लिए प्रासंगिक सामान रख सकता हूं (यानी, अनुरोध की शुरुआत में ध्वज सेट करें और संभवत: before_request/after_request जोड़ी से)

  • में अनुरोध-स्तर-राज्य,रखने के अलावासंसाधन प्रबंधन के लिए उपयोग किया जा सकता है और इसका उपयोग किया जाना चाहिए, यानी डेटाबेस कनेक्शन, आदि

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

+0

मैं सहमत हूं, यह एक बहुत ही अजीब परिवर्तन है। उम्मीद है कि mitsuhiko 0.10 में 'g' को प्रतिस्थापित करने के लिए किसी प्रकार का अनुरोध संदर्भ ऑब्जेक्ट लागू करता है, अन्यथा ऐसा लगता है कि बहुत से कोड कुछ दुर्भाग्यपूर्ण बग विकसित करना शुरू कर सकते हैं। – Anorov

+7

एफडब्ल्यूआईडब्ल्यू, आर्मीन रोनाकर (फ्लास्क के लेखक) ने "उन्नत फ्लास्क पैटर्न" का एक अनुक्रम जारी किया है जो नए '' flask.g'' का उपयोग करने के तरीके पर कुछ उदाहरण कोड दिखाता है। https://speakerdeck.com/mitsuhiko/advanced-flask-patterns-1 –

+1

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

उत्तर

72

Advanced Flask Patterns, के रूप में मार्कस से जुड़े हुए, 0.10 में g में कुछ बदलाव बताते हैं:

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

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

+1

क्या आप [app.app_context() '] को दबा रहे हैं (https://github.com/ पैलेट/कुप्पी/ब्लॉब/मास्टर/कुप्पी/ctx.py # L317)? यदि ऐसा है, तो यह ध्यान दिया जाना चाहिए ['app_context()'] (https://github.com/pallets/flask/blob/master/flask/app.py#L2080-L2093) हर कॉल का एक नया एप्लिकेशन संदर्भ तत्काल करता है - यह कभी भी एक संदर्भ का पुन: उपयोग नहीं करता है। – theY4Kman

+1

हां यह सच है, लेकिन जब 'app_ctx कोई नहीं है और app_ctx.app == self.app',' app_ctx = self.app.app_context() 'line _not_ निष्पादित नहीं है; इस मामले में केवल 'self._implicit_app_ctx_stack.append (कोई नहीं)' निष्पादित किया गया है। –

33

इस सूत्र में जानकारी का एक परिशिष्ट के रूप में: मैं 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 जैसा कि ऊपर कहा, "हर अनुरोध एक नया आवेदन संदर्भ भेजता है"। और as the Flask docs say, एप्लिकेशन संदर्भ "अनुरोधों के बीच साझा नहीं किया जाएगा"। अब, जो स्पष्ट रूप से नहीं बताया गया है (हालांकि मुझे लगता है कि यह इन बयानों से जुड़ा हुआ है), और मेरा परीक्षण स्पष्ट रूप से दिखाता है, यह है कि आपको कभी स्पष्ट रूप से एक आवेदन संदर्भ के अंदर नेस्टेड एकाधिक अनुरोध संदर्भ नहीं बना सकते हैं, क्योंकि flask.g (और सह) में कोई जादू नहीं है जिससे यह संदर्भ के दो अलग-अलग "स्तर" में कार्य करता है, जिसमें अलग-अलग राज्य स्वतंत्र रूप से आवेदन और अनुरोध स्तर पर मौजूद होते हैं।

वास्तविकता यह है कि "आवेदन संदर्भ" संभावित, काफी भ्रामक नाम है, क्योंकि 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)) 

कौन सा अपेक्षित परिणाम दे देंगे।

संबंधित मुद्दे