फ्लास्क देव सर्वर चलाने से दो बार ही क्यों चलता है?


107

मैं एक वेबसाइट विकसित करने के लिए फ्लास्क का उपयोग कर रहा हूं और विकास में मैं निम्नलिखित फाइल का उपयोग करके फ्लास्क चलाता हूं:

#!/usr/bin/env python
from datetime import datetime
from app import app
import config

if __name__ == '__main__':
    print '################### Restarting @', datetime.utcnow(), '###################'
    app.run(port=4004, debug=config.DEBUG, host='0.0.0.0')

जब मैं सर्वर शुरू करता हूं, या जब यह ऑटो-रीस्टार्ट होता है क्योंकि फाइलें अपडेट हो चुकी होती हैं, तो यह हमेशा प्रिंट लाइन को दो बार दिखाता है:

################### Restarting @ 2014-08-26 10:51:49.167062 ###################
################### Restarting @ 2014-08-26 10:51:49.607096 ###################

हालांकि यह वास्तव में कोई समस्या नहीं है (बाकी उम्मीद के मुताबिक काम करता है), मुझे बस आश्चर्य है कि यह इस तरह क्यों व्यवहार करता है? कोई विचार?

जवाबों:


153

Werkzeug पुनः लोडर एक बच्चे की प्रक्रिया को जन्म देता है ताकि यह आपके कोड में परिवर्तन होने पर हर बार उस प्रक्रिया को पुनः आरंभ कर सके। Werkzeug एक ऐसी लाइब्रेरी है जो कॉल करने पर विकास सर्वर के साथ फ्लास्क की आपूर्ति करती है app.run()

restart_with_reloader()फ़ंक्शन कोड देखें ; आपकी स्क्रिप्ट के साथ फिर से चलाया जाता है subprocess.call()

यदि आप निर्धारित करते हैं use_reloaderकि Falseआप व्यवहार को चले जाते देखेंगे, लेकिन फिर आप पुनः लोडिंग कार्यक्षमता भी खो देंगे:

app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)

flask runकमांड का उपयोग करते समय आप पुनः लोडर को निष्क्रिय कर सकते हैं :

FLASK_DEBUG=1 flask run --no-reload

WERKZEUG_RUN_MAINयदि आप पुन: लोड करने की प्रक्रिया में हैं, तो आप पर्यावरण चर की तलाश कर सकते हैं:

import os
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
    print '################### Restarting @ {} ###################'.format(
        datetime.utcnow())

हालांकि, यदि आपको मॉड्यूल ग्लोबल्स स्थापित करने की आवश्यकता है, तो आपको इसके बजाय किसी फ़ंक्शन पर @app.before_first_requestडेकोरेटर का उपयोग करना चाहिए और उस फ़ंक्शन को ऐसे ग्लोबल्स को सेट करना होगा। पहला अनुरोध आने पर इसे हर बार लोड करने के बाद एक बार बुलाया जाएगा:

@app.before_first_request
def before_first_request():
    print '########### Restarted, first request @ {} ############'.format(
        datetime.utcnow())

इस बात का ध्यान रखें कि यदि आप इसे पूर्ण-स्तरीय WSGI सर्वर में चलाते हैं, जो अनुरोधों को संभालने के लिए forking या नए उपप्रोसेस का उपयोग करता है, तो प्रत्येक नए उपप्रोसेस के लिए before_first_requestहैंडलर को आमंत्रित किया जा सकता है।


2
आह अच्छा। स्पष्टीकरण के लिए धन्यवाद! तो इसका सामान्य व्यवहार माना जाता है? कम से कम अच्छा है कि मेरे कोड के साथ कुछ भी गलत नहीं है .. :)
kramer65

1
@ kramer65: यह पूरी तरह से सामान्य और अपेक्षित व्यवहार है। :-)
मार्टिन पीटर्स

1
क्या केवल एक बार धीमी गति से आरंभ करने का एक व्यावहारिक तरीका है, यह सुनिश्चित करना कि इसे wsgi के तहत चलाने के दौरान भी कॉल किया जाता है (यानी इससे नहीं app.run), लेकिन पहले अनुरोध का इंतजार नहीं करना चाहिए? मैं नहीं चाहता कि पहले अनुरोध को आरंभिक लागत के बोझ से दबा दिया जाए।
काइलोटन

1
@ किलोटन: आपको पर्यावरण का निरीक्षण करना होगा; यदि आप विकास में भाग लेते समय केवल DEBUG सेट करते हैं, तो आप WERKZEUG_RUN_MAINपर्यावरण चर की तलाश कर सकते हैं और केवल अपना कोड चला सकते हैं जब DEBUGगलत है या WERKZEUG_RUN_MAINउदाहरण के लिए सेट किया गया है। थोड़ा थकाऊ हो जाता है।
मार्टिजन पीटरर्स

बस स्पष्ट करने के लिए, मैंने सोचा कि "कार्यक्षमता को फिर से लोड करना" का मतलब था प्रतिक्रियाशीलता (जो dashमेरे लिए उपयोग करने के पूरे उद्देश्य को हरा देगा)। noobsखुद की तरह किसी अन्य के लिए , इसका मतलब केवल कार्यक्षमता है जिसमें फ़ाइल को संपादित / सहेजना एक लाइव अपडेट को ट्रिगर करता है।
हेंडी

12

यदि आप आधुनिक flask runकमांड का उपयोग कर रहे हैं, तो उपयोग किए जाने वाले विकल्पों में से कोई भी उपयोग नहीं app.runकिया जाता है। रीलोडर को पूरी तरह से निष्क्रिय करने के लिए, पास करें --no-reload:

FLASK_DEBUG=1 flask run --no-reload

इसके अलावा, __name__ == '__main__'कभी भी यह सच नहीं होगा क्योंकि ऐप को सीधे निष्पादित नहीं किया गया है। मार्टिज़न के उत्तर से समान विचारों का उपयोग करें , बिना __main__ब्लॉक के।

if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
    # do something only once, before the reloader

if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
    # do something each reload

7

मेरे पास एक ही मुद्दा था, और मैंने इसे सेटिंग करके हल app.debugकिया False। इसे स्थापित करने के Trueकारण मुझे __name__ == "__main__"दो बार बुलाया गया।


मेरा __main__अभी भी दोनों के साथ दो बार चलता है app.debug = Falseऔर app.run_server(debug=False)। क्या आप सुनिश्चित हैं कि यह आपके लिए था, या आप कुछ प्रतिलिपि प्रस्तुत करने योग्य कोड को आज़मा सकते हैं?
हेंडी

App.debug को बदलना मेरे लिए इसे हल करना था। क्या आप पुष्टि कर सकते हैं कि फ्लास्क सर्वर शुरू होने पर मुख्य केवल दो बार चल रहा है? चल रहा है और अगर समस्या होती है देखने के लिए एक कम से कम काम कर उदाहरण प्राप्त करने का प्रयास करें। इसके अलावा एक न्यूनतम उदाहरण चलाने की कोशिश करें जो कई अजगर संस्करणों में विफल रहता है, जो कि एक मुद्दा हो सकता है। जब से मैंने अजगर और फ्लास्क के बजाय जावा और स्पार्कजवा में अपनी परियोजना को स्थानांतरित किया है, तो मुझे याद नहीं है कि वास्तव में क्या मुद्दा तय किया गया था।
कार्वेल वाकमैन

मैं के flaskमाध्यम से उपयोग कर रहा हूँ plotly dash, और पता चला कि उन्होंने हाल ही में डिफ़ॉल्ट debug तर्क को बदल दिया है flask। मैं अनुमान लगा रहा हूं कि मुझे ऊपर गलत किया गया था और शायद किया था app.debug=False(जो कि शायद डिफ़ॉल्ट आर्गन्स द्वारा ओवरराइड किया गया है run_server), या केवल गुजरने की कोशिश की गई True, ऊपर दिखाए अनुसार स्पष्ट रूप से सेटिंग नहीं। यह अब मेरे लिए सही तरीके से काम कर रहा है (यह सुनिश्चित करना debug=False)। धन्यवाद!
हेन्डी

2

फ्लास्क 0.11 से, इसके flask runबजाय अपने ऐप को चलाने की अनुशंसा की जाती है python application.py। उत्तरार्द्ध का उपयोग करने के परिणामस्वरूप आपका कोड दो बार चल सकता है।

जैसा कि यहाँ कहा गया है :

... फ्लास्क 0.11 से फ्लास्क विधि की सिफारिश की जाती है। इसका कारण यह है कि पुनः लोड तंत्र कैसे काम करता है, इसके कारण कुछ विचित्र दुष्परिणाम होते हैं (जैसे कुछ निश्चित रूप से दो बार निष्पादित ...)


0

फ्लास्क ऐप को दो बार चलाने के संभावित कारणों में से एक WEB_CONCURRENCYहेरोकू पर सेटिंग का एक कॉन्फ़िगरेशन है । एक में सेट करने के लिए, आप कंसोल में लिख सकते हैं heroku config:set WEB_CONCURRENCY=1


-1

धागे के बारे में एक अवलोकन

यह विशेष रूप से कष्टप्रद है जब आपका एप्लिकेशन थ्रेड का उपयोग करता है क्योंकि उन्हें स्टार्टअप पर दो बार निकाल दिया जाएगा। जहाँ तक मैंने कोशिश की एकल गायिकाएं इसका उपाय नहीं करतीं (जो आश्चर्य की बात है)। हालाँकि, आपके थ्रेड प्रारंभ होने से पहले कुछ सेकंड की प्रारंभिक देरी को जोड़ने से समस्या हल हो सकती है।

यदि एप्लिकेशन आपके देरी की अवधि से पहले की तुलना में जल्दी पुनरारंभ होता है, तो दिए गए धागे को पुनरारंभ के बाद केवल एक बार ही देखा जाता है।


@ डॉववोटर: समझाने की परवाह क्यों?
pfabri

-1

मेरी भी यही समस्या थी। मैंने इसे अपने मुख्य को संशोधित करके और इसमें use_reloader = False को सम्मिलित करके हल किया। यदि कोई भी निकाय इस समस्या के लिए वर्कअराउंड की तलाश में है तो नीचे दिया गया कोड आपको मिल जाएगा, हालाँकि आपको कोड में बदलावों की कार्यक्षमता का पता स्वतः ही लग जाएगा और फिर से शुरू करने से काम नहीं चलेगा। कोड में प्रत्येक संपादन के बाद आपको मैन्युअल रूप से आवेदन करना और रोकना होगा।

if __name__ == '__main__':
    app.run(debug=True, use_reloader=False)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.