🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Webサーバー

Webサーバーとは、HTTPリクエストに応じて、クライアントに情報を提供するシステムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

1回答

3050閲覧

「Waiting for connections to close」となり一発で停止することができない。裏で処理が続いてしまっている?(Python)

obon_t

総合スコア52

Webサーバー

Webサーバーとは、HTTPリクエストに応じて、クライアントに情報を提供するシステムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2021/01/19 08:09

編集2021/01/19 08:18

イメージ説明

前提・実現したいこと

python(FastAPI)にてServer-Sent Eventsを行おうとしています。

プログラム自体は問題なく動作するのですが、ターミナル上から Control+C で終了しようとすると、
「Waiting for connections to close.」とエラーメッセージが表示され一発で終了することができません。

一度で無事すべてのプロセスを終了させる方法をご教授いただきたいです。
コードの書き方が適切でないため、このメッセージが表示されるのではないかと思っているのですが、
どう直してあげればよいかがわからず、苦戦しております。

発生している問題・エラーメッセージ

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [23908] using watchgod INFO: Started server process [23910] INFO: Waiting for application startup.  ︙ INFO: 127.0.0.1:55249 - "GET /static/favicon.ico HTTP/1.1" 200 OK INFO: 127.0.0.1:55249 - "POST /ajax HTTP/1.1" 200 OK ^CINFO: Shutting down INFO: Waiting for connections to close. (CTRL+C to force quit) ^CINFO: Finished server process [23910] INFO: Stopping reloader process [23908]

該当のソースコード

python

1from fastapi import FastAPI, Request, WebSocket 2from fastapi.staticfiles import StaticFiles 3from fastapi.templating import Jinja2Templates 4from fastapi.responses import StreamingResponse 5import random 6import asyncio 7import queue 8 9app = FastAPI() 10app.mount("/static", StaticFiles(directory="static"), name="static") 11templates = Jinja2Templates(directory="templates") 12 13q = asyncio.Queue() 14 15# EventStream 16@app.get('/stream') 17async def message_stream(request: Request): 18 async def event_stream(): 19 while True: 20 event = "test" 21 data = await q.get() 22 yield "event:{}\ndata:{}\n\n".format(event,data) 23 await asyncio.sleep(5) 24 return StreamingResponse(event_stream(), media_type="text/event-stream") 25 26# index 27@app.get("/") 28async def index(request: Request): 29 return templates.TemplateResponse("index.html", {"request": request}) 30 31# ajax 32@app.post("/ajax") 33def ajax(): 34 q.put_nowait("処理①") 35 q.put_nowait("処理②") 36 q.put_nowait("処理③") 37 q.put_nowait("処理④") 38 q.put_nowait("処理⑤") 39 q.put_nowait("処理⑥") 40 q.put_nowait("処理⑦") 41 q.put_nowait("処理⑧") 42 q.put_nowait("処理⑨") 43 q.put_nowait("処理⑩") 44 return "サーバーメッセージ"

javascript

1$(function () { 2 3 var evtSource = new EventSource("/stream"); 4 evtSource.addEventListener("test", function (e) { 5 console.log(e.data); 6 }); 7 8 $("#btn").click(function () { 9 console.log(evtSource); 10 11 $.ajax({ 12 url: "/ajax", 13 type: "POST", 14 }) 15 .done(function (data) { 16 console.log(data); 17 }) 18 .fail(function () { 19 console.log("Error"); 20 }); 21 }); 22}); 23

試したこと・メッセージが発生するパターン

(1)先に開いているブラウザのタブを閉じてから、ターミナル上でControl+Cで閉じると今回のメッセージは発生しません。(タブを開いている状態でターミナルから終了しようとすると、メッセージが発生してしまします。)
(2)エラーメッセージが表示されたあと、Control+C を再度することで強制終了できることは確認済みです。
(3)Ajaxと連携しているボタンをクリックしない状態で、終了しようとした場合も同じメッセージが表示され変化なし。
(4)async関連が悪さをしているのかと睨んで、await asyncio.sleep をコメントアウトしてみたが変化なし。

補足情報(FW/ツールのバージョンなど)

・python3.9
・FastAPI
・Uvicorn

足りない部分がありましたら、再度調べ直し、記載いたしますのでコメント下さい。
何卒、お力添えのほどよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

これはコード上正しい動作をしています。まず uvnicorn は Graceful shutdown といって、サーバーを終了する際、処理中のリクエストがすべて終わる(かタイムアウトする)のを待ってから終了するという挙動になっています。
Server Behavior - Uvicorn
uvicorn/server.py at master · encode/uvicorn

@app.post("/ajax") を呼び出すと 10 個の処理がキューに入ります。それを @app.get('/stream') 内で一つずつ取り出し配信しています。そこにタイムラグがあるためこのような挙動になるのです。

どうしても強制終了させたい場合は Ctrl + C を 2 回押しましょう。コードを見る限りそのような作りになっているようです。

投稿2021/01/19 08:31

A_kirisaki

総合スコア2853

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

obon_t

2021/01/19 08:45 編集

ご回答ありがとうございます。 Graceful shutdownという処理があるのですね。 コードを追記するなど、Ctrl + C を 2 回押す以外で終了させる方法は無いのでしょうか? そのフラグを強制的に立たせないなど、もし可能でしたら使われる技術名などヒントになるキーワードを教えていただけると幸いです。
A_kirisaki

2021/01/19 09:05

こればっかりはそういう作りになっているので自分で uvnicorn のソースコードを fork してそういうふうに書き換えるとか、ついでにそういうオプション作ったよって公式にプルリク送るとか、そういう手段しかありませんね。オープンソースのソフトウェアですので「文句があったら自分で実装しろ」ですので……。そうでなくても試しに GitHub の issue に書き込んでみれば実装される「かも」しれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問