ページ上の既存のコンテンツを置き換えるには、javascriptが必要な場合があります。つまり、送信したり、リクエストを作成したり、長いポーリングやWebソケットなどを使用したりできます。多くの方法があります。ここには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
:接続が失われた場合、ブラウザは3秒で、デフォルトでは再接続
<!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>
。何も送信しない場合、サーバーは404を返すか、次の要求に応答して'text/event-stream'
コンテンツタイプ以外を送信することができます。サーバーにさらにデータがある場合でもクライアント側で停止するには、source.close()
と呼ぶことができます。
注:ストリームが無限であることを意味していないならば、(無限技術)のテキストを置き換えるためにはJavaScriptスニペットを送って、例えば他の技術(ないSSE)を使用します。
#!/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)
私がインライン化しましたここには何もないことを示すためにHTML(ここでは魔法)はありません。ここでは上記と同じですが、テンプレートを使用します:
#!/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でバックアップを開始します。どのようにこれを再試行して、これにアクセスしようとするクライアントが、同じデータ/カウンターを見て、アプリケーションが開始されてからカウントアップするようにしますか?私はあなたが別のスレッドでカウンタを実行する必要があると仮定しているが、私はこれを実装する方法がわからない。 –
@DavidMarx:少なくとも2つの質問があります:(1)フラスコ内の複数の同時クライアントをサポートする方法は? - 答え:どのようなwsgiアプリケーションでも同じように、guncorn(2)を使用して、複数のクライアントの同じカウンタにアクセスする方法を教えてください。 - あなたが単一のワーカーを想定している、例えばグローバルなイテレータを定義し、ループ内で 'next(it)'を呼び出すなど、任意のサーバプログラムの共有データへのアクセスを提供するのと同じ方法です。とにかく、これらは別々の質問です。特定の問題に固有の新しい質問をしてください。 – jfs
ありがとうございます。私はここでより焦点を絞ったトピックで新しい質問を投稿しました:http://stackoverflow.com/questions/33877359/building-a-front-end-webapp-for-a-real-time-data-stream-in- python –