पृष्ठ पर मौजूदा सामग्री को प्रतिस्थापित करने के लिए आपको जावास्क्रिप्ट की आवश्यकता हो सकती है यानी, आप इसे भेज सकते हैं या इसे आपके लिए अनुरोध कर सकते हैं, लंबे मतदान, websockets, आदि का उपयोग कर सकते हैं। ऐसा करने के कई तरीके हैं, यहां एक है जो server send events का उपयोग करता है :
#!/usr/bin/env python
import itertools
import time
from flask import Flask, Response, redirect, request, url_for
app = Flask(__name__)
@app.route('/')
def index():
if request.headers.get('accept') == 'text/event-stream':
def events():
for i, c in enumerate(itertools.cycle('\|/-')):
yield "data: %s %d\n\n" % (c, i)
time.sleep(.1) # an artificial delay
return Response(events(), content_type='text/event-stream')
return redirect(url_for('static', filename='index.html'))
if __name__ == "__main__":
app.run(host='localhost', port=23423)
कहाँ static/index.html
:
<!doctype html>
<title>Server Send Events Demo</title>
<style>
#data {
text-align: center;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
if (!!window.EventSource) {
var source = new EventSource('/');
source.onmessage = function(e) {
$("#data").text(e.data);
}
}
</script>
<div id="data">nothing received yet</div>
ब्राउज़र 3 सेकंड में डिफ़ॉल्ट रूप से पुन: कनेक्ट हो, तो कनेक्शन टूट जाए। यदि सर्वर भेजने के लिए और कुछ नहीं है तो सर्वर 404 लौटा सकता है या अगले अनुरोध के जवाब में 'text/event-stream'
सामग्री प्रकार से कुछ अन्य भेज सकता है। क्लाइंट पक्ष पर रुकने के लिए, भले ही सर्वर के पास अधिक डेटा हो, तो आप source.close()
पर कॉल कर सकते हैं।
नोट: यदि धारा अनंत होने के लिए नहीं होती है तो, अन्य तकनीकों (नहीं SSE) जैसे का उपयोग JavaScript स्निपेट भेज पाठ बदलने के लिए (अनंत तकनीक):
#!/usr/bin/env python
import time
from flask import Flask, Response
app = Flask(__name__)
@app.route('/')
def index():
def g():
yield """<!doctype html>
<title>Send javascript snippets demo</title>
<style>
#data {
text-align: center;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<div id="data">nothing received yet</div>
"""
for i, c in enumerate("hello"):
yield """
<script>
$("#data").text("{i} {c}")
</script>
""".format(i=i, c=c)
time.sleep(1) # an artificial delay
return Response(g())
if __name__ == "__main__":
app.run(host='localhost', port=23423)
मैं inlined गए यह दिखाने के लिए यहां एचटीएमएल है कि इसमें कुछ और नहीं है (कोई जादू नहीं)। यहाँ ऊपर, लेकिन टेम्पलेट का उपयोग कर के रूप में ही है:
#!/usr/bin/env python
import time
from flask import Flask, Response
app = Flask(__name__)
def stream_template(template_name, **context):
# http://flask.pocoo.org/docs/patterns/streaming/#streaming-from-templates
app.update_template_context(context)
t = app.jinja_env.get_template(template_name)
rv = t.stream(context)
# uncomment if you don't need immediate reaction
##rv.enable_buffering(5)
return rv
@app.route('/')
def index():
def g():
for i, c in enumerate("hello"*10):
time.sleep(.1) # an artificial delay
yield i, c
return Response(stream_template('index.html', data=g()))
if __name__ == "__main__":
app.run(host='localhost', port=23423)
कहाँ templates/index.html
:
<!doctype html>
<title>Send javascript with template demo</title>
<style>
#data {
text-align: center;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<div id="data">nothing received yet</div>
{% for i, c in data: %}
<script>
$("#data").text("{{ i }} {{ c }}")
</script>
{% endfor %}
डेमो आपके द्वारा दी गई (विशेष रूप से मैं SSE डेमो के साथ खेल रहा हूँ) केवल एक ही ग्राहक के लिए काम करता है। यदि मैं एक नई ब्राउज़र विंडो खोलता हूं और पृष्ठ स्ट्रीमिंग डेटा तक पहुंचने का प्रयास करता हूं, तब तक कुछ नहीं होता जब तक कि मैं पिछले पृष्ठ को बंद या बंद नहीं करता। और फिर, काउंटर 0 पर वापस शुरू होता है। आप इसे कैसे पुन: कार्य करेंगे ताकि कोई भी ग्राहक इसे एक्सेस करने का प्रयास कर रहा हो, तो सभी एक ही डेटा/काउंटर देखेंगे, जो ऐप शुरू होने के समय से गिन रहा है? मुझे लगता है कि आपको काउंटर को एक अलग थ्रेड में चलाने की ज़रूरत है, लेकिन मुझे यकीन नहीं है कि इसे कैसे कार्यान्वित किया जाए। –
@ डेविड मैक्स: कम से कम दो प्रश्न हैं: (1) फ्लास्क में एकाधिक समवर्ती ग्राहकों का समर्थन कैसे करें? - उत्तर: वैसे ही आप इसे किसी भी wsgi ऐप के लिए करते हैं, उदाहरण के लिए, गनिकॉर्न (2) का उपयोग करें ताकि एकाधिक क्लाइंट के लिए एक ही काउंटर तक पहुंच प्रदान की जा सके? - वैसे ही आप किसी भी सर्वर प्रोग्राम में साझा डेटा तक पहुंच प्रदान करते हैं, उदाहरण के लिए, एक एकल कार्यकर्ता मानते हुए: वैश्विक पुनरावर्तक को परिभाषित करें और लूप में 'अगला (इसे)' कॉल करें। वैसे भी, ये अलग प्रश्न हैं। अपनी विशेष समस्या के लिए विशिष्ट एक नया प्रश्न पूछें। – jfs
धन्यवाद जेएफ। मैंने यहां एक अधिक केंद्रित विषय के साथ एक नया प्रश्न पोस्ट किया है: http://stackoverflow.com/questions/33877359/building-a-front-end-webapp-for-a-real-time-data-stream-in- पायथन –